webfakes/0000755000176200001440000000000015026575142012050 5ustar liggesuserswebfakes/tests/0000755000176200001440000000000014740243712013207 5ustar liggesuserswebfakes/tests/testthat/0000755000176200001440000000000015026575142015052 5ustar liggesuserswebfakes/tests/testthat/test-mw-multipart.R0000644000176200001440000000156115026556433020621 0ustar liggesusersapp <- new_app() app$use(mw_multipart()) app$put("/form", function(req, res) { ret = list(form = req$form, files = req$files) res$send_json(ret, pretty = TRUE, auto_unbox = TRUE) }) web <- local_app_process(app) test_that("mw_multipart", { on.exit(rm(tmp), add = TRUE) tmp <- tempfile() writeBin(charToRaw("foobar\n"), con = tmp) url <- web$url("/form") handle <- curl::new_handle() curl::handle_setopt(handle, customrequest = "PUT") curl::handle_setform( handle, a = "1", b = "2", c = curl::form_file(tmp, type = "text/plain") ) resp <- curl::curl_fetch_memory(url, handle = handle) echo <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_equal(echo$form, list(a = "1", b = "2")) expect_equal( echo$files$c, list( filename = basename(tmp), value = base64_encode("foobar\n") ) ) }) webfakes/tests/testthat/test-print.R0000644000176200001440000000361615026556433017316 0ustar liggesusersapp <- new_app() app$use(function(req, res) { tmp <- tempfile() saveRDS(list(req = req, res = res), file = tmp) res$set_status(200)$send(normalizePath(tmp)) }) proc <- local_app_process(app) withr::local_options(list(HTTPUserAgent = "It is me, libcurl")) resp <- curl::curl_fetch_memory(proc$url()) tmp <- rawToChar(resp$content) withr::defer(unlink(tmp)) # Verify_output uses a png() graphics device, and fails if there is # no png() support. So we skip theses tests then. capabilities() # is very slow on macOS, because it starts up X11, so we'll just assume # that macOS has a png device. skip_without_png_device <- function() { if (.Platform$OS.type == "windows") { return() } if (!capabilities("png") || !capabilities("X11")) { skip("Needs a PNG device") } } test_that("webfakes_app", { skip_without_png_device() app <- new_app() app$use("add etag" = mw_etag()) app$get("/api", function(req, res) res$send("foobar")) verify_output( test_path("fixtures", "output", "webfakes_app.txt"), app ) }) test_that("webfakes_request", { skip_without_png_device() req <- readRDS(tmp)$req req$url <- "http://127.0.0.1:3000/" req$headers$Host <- "127.0.0.1:3000" req$headers$`Accept-Encoding` <- "deflate, gzip" verify_output( test_path("fixtures", "output", "webfakes_request.txt"), req ) }) test_that("webfakes_response", { skip_without_png_device() res <- readRDS(tmp)$res verify_output( test_path("fixtures", "output", "webfakes_response.txt"), res ) }) test_that("webfakes_regexp", { skip_without_png_device() verify_output( test_path("fixtures", "output", "webfakes_regexp.txt"), new_regexp("^(foo|bar)$") ) }) test_that("webfakes_app_process", { skip_without_png_device() app <- new_app() proc <- new_app_process(app, start = TRUE) proc$stop() # make the output deterministic proc$.port <- 3000 expect_snapshot(proc) }) webfakes/tests/testthat/test-threads.R0000644000176200001440000000115114741433021017572 0ustar liggesuserstest_that("parallel requests", { url <- httpbin$url("/delay/0.5") p <- curl::new_pool() handles <- replicate(3, curl::new_handle(url = url, http_version = 2)) resps <- list() for (handle in handles) { curl::multi_add( handle, done = function(x) resps <<- c(resps, list(x)), fail = stop, pool = p ) } st <- system.time(curl::multi_run(timeout = 5, pool = p)) expect_true(st[["elapsed"]] >= 0.5) expect_true(st[["elapsed"]] < 1.5) expect_equal(resps[[1]]$status_code, 200L) expect_equal(resps[[2]]$status_code, 200L) expect_equal(resps[[3]]$status_code, 200L) }) webfakes/tests/testthat/test-oauth.R0000644000176200001440000001010515026556433017271 0ustar liggesuserstest_that("oauth2", { skip_on_cran() # Create the resource server rsapp <- local_app_process( oauth2_resource_app(), opts = server_opts(num_threads = 3) ) regi_url <- rsapp$url("/register") auth_url <- rsapp$url("/authorize") toke_url <- rsapp$url("/token") # Create the third party app server tpapp <- local_app_process( oauth2_third_party_app("3P app"), opts = server_opts(num_threads = 3) ) redi_url <- tpapp$url("/login/redirect") conf_url <- tpapp$url("/login/config") # Register the third party app at the resource server # In real life this is done by the admin of the third party app url <- paste0( regi_url, "?name=3P%20app", "&redirect_uri=", redi_url ) resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200L) regdata <- jsonlite::fromJSON(rawToChar(resp$content)) # Now set this data on the third party app # In real life this is included in the config of the third party app # by its admin auth_data <- jsonlite::toJSON( list( auth_url = auth_url, token_url = toke_url, client_id = regdata$client_id, client_secret = regdata$client_secret ), auto_unbox = TRUE ) handle <- curl::new_handle() curl::handle_setheaders( handle, "content-type" = "application/json" ) curl::handle_setopt( handle, customrequest = "POST", postfieldsize = nchar(auth_data), postfields = auth_data ) resp2 <- curl::curl_fetch_memory(conf_url, handle = handle) expect_equal(resp2$status_code, 200L) # Now everything is set up, a user can go to the login page of the # third party app: # browseURL(tpapp$url("/login")) # Scripting it is a bit tedious, because we need to parse the HTML and # submit a form. The `oauth2_login()` helper function does this. resp3 <- oauth2_login(tpapp$url("/login")) token <- jsonlite::fromJSON(rawToChar(resp3$token_response$content)) expect_equal(resp3$login_response$status_code, 200L) expect_equal(resp3$login_response$type, "text/html") expect_equal(resp3$token_response$status_code, 200L) expect_match(token$access_token, "^token-[0-9a-f]+$") }) test_that("oauth + httr", { skip_on_cran() # Not great, the OS should allocate a port, really... withr::local_envvar(c( HTTP_SERVER = "127.0.0.1", HTTP_SERVER_PORT = httpuv::randomPort() )) # Create the resource server rsappex <- oauth2_resource_app(access_duration = 0.1) log <- tempfile("webfakes-log-", fileext = ".log") on.exit(unlink(log, recursive = TRUE), add = TRUE) rsappex$use(logger = mw_log(stream = log), .first = TRUE) rsapp <- local_app_process( rsappex, opts = server_opts(num_threads = 3) ) regi_url <- rsapp$url("/register") auth_url <- rsapp$url("/authorize") toke_url <- rsapp$url("/token") # Register httr url <- paste0( regi_url, "?name=httr%20local%20app", "&redirect_uri=", httr::oauth_callback() ) reg_resp <- httr::GET(url) httr::stop_for_status(reg_resp) regdata <- httr::content(reg_resp) app <- httr::oauth_app( regdata$name[[1]], key = regdata$client_id[[1]], secret = regdata$client_secret[[1]], redirect_uri = httr::oauth_callback() ) endpoint <- httr::oauth_endpoint( authorize = auth_url, access = toke_url ) token <- suppressMessages(oauth2_httr_login( httr::oauth2.0_token(endpoint, app, cache = FALSE) )) # This will refresh the token automatically Sys.sleep(0.1) expect_message( cnt <- httr::content( httr::GET(rsapp$url("/data"), config = token), as = "parsed", type = "application/json" ), "Auto-refreshing stale OAuth" ) expect_equal(cnt, list(data = list("top secret!"))) loglines <- readLines(log) endpoints <- parse_url(map_chr(strsplit(loglines, " "), "[[", 2))$path expect_equal( endpoints, c( "/register", "/authorize", "/authorize/decision", "/token", "/data", "/token", "/data" ) ) status <- map_chr(strsplit(loglines, " "), "[[", 3) expect_equal( as.numeric(status), c(200, 200, 302, 200, 401, 200, 200) ) }) webfakes/tests/testthat/test-mime.R0000644000176200001440000000022615026556433017103 0ustar liggesuserstest_that("mime_find", { expect_equal(mime_find("json"), c(json = "application/json")) expect_equal(mime_find("blahxml"), c(xml = "text/xml")) }) webfakes/tests/testthat/test-mw-range-parser.R0000644000176200001440000000133715026556433021167 0ustar liggesuserstest_that("parse_range", { expect_snapshot({ parse_range("foobar=1-100") parse_range("bytes=0-100, 50-150") parse_range("bytes=200-100") parse_range("bytes=x-100") parse_range("bytes=1-100") parse_range("bytes=1-") parse_range("bytes=-100") parse_range("bytes=0-100, 200-") parse_range("bytes=200-300, 0-100") }) }) test_that("intervals_overlap", { ok <- list( matrix(0, nrow = 0, ncol = 2), rbind(1:2), rbind(1:2, 3:4) ) for (x in ok) { expect_false(intervals_overlap(x), info = x) } bad <- list( rbind(c(1, 10), c(5, 10)), rbind(c(1, 20), c(1, 20)), rbind(c(1, 1), c(1, 4)) ) for (x in bad) { expect_true(intervals_overlap(x), info = x) } }) webfakes/tests/testthat/fixtures/0000755000176200001440000000000014740243712016720 5ustar liggesuserswebfakes/tests/testthat/fixtures/views/0000755000176200001440000000000014172041777020063 5ustar liggesuserswebfakes/tests/testthat/fixtures/views/test-view.html0000644000176200001440000000011414172041777022674 0ustar liggesusers { greeting } { user } webfakes/tests/testthat/fixtures/static2/0000755000176200001440000000000014172041777020277 5ustar liggesuserswebfakes/tests/testthat/fixtures/static2/static.tar.gz0000644000176200001440000000026614172041777022721 0ustar liggesusers0^K 0]E܀Mx;)eH⬈CK8!cpRpj+VϙqIXbcI2TJf65zs*gWC5|=K+D>|wHello world! webfakes/tests/testthat/fixtures/output/0000755000176200001440000000000014740737023020263 5ustar liggesuserswebfakes/tests/testthat/fixtures/output/webfakes_response.txt0000644000176200001440000000151115003627403024520 0ustar liggesusers> res fields and methods: app # the webfakes_app the response belongs to locals # response-wide shared data get_header(field) # query response header on_response(fun) # call handler function for complete response redirect(path, status) # send redirect response render(view, locals) # render template send(body) # send text or raw data send_file(path, root) # send a file (automatic Content-Type) send_json(object, text, ...) # send JSON data send_status(status) # send HTTP status and empty body set_header(field, value) # set a response header set_status(status) # set response status code set_type(type) # set Content-Type # see ?webfakes_response for details webfakes/tests/testthat/fixtures/output/webfakes_request.txt0000644000176200001440000000151715003627403024360 0ustar liggesusers> req method: get url: http://127.0.0.1:3000/ client: 127.0.0.1 query: headers: Host: 127.0.0.1:3000 User-Agent: It is me, libcurl Accept: */* Accept-Encoding: deflate, gzip fields and methods: app # the webfakes_app the request belongs to headers # HTTP request headers hostname # server hostname, the Host header method # HTTP method of request (lowercase) path # server path protocol # http or https query_string # raw query string without '?' query # named list of query parameters remote_addr # IP address of the client url # full URL of the request get_header(field) # get a request header # see ?webfakes_request for details webfakes/tests/testthat/fixtures/output/webfakes_regexp.txt0000644000176200001440000000007515003627403024160 0ustar liggesusers> new_regexp("^(foo|bar)$") "^(foo|bar)$" webfakes/tests/testthat/fixtures/output/webfakes_app.txt0000644000176200001440000000114515003627403023445 0ustar liggesusers> app routes: use * # add etag get /api fields and methods: all(path, ...) # add route for *all* HTTP methods delete(path, ...) # add route for DELETE engine(ext, engine) # add template engine for file extension head(path, ...) # add route for HEAD listen(port) # start web app on port patch(path, ...) # add route for PATCH post(path, ...) # add route for POST put(path, ...) # add route for PUT use(...) # add middleware locals # app-wide shared data # see ?webfakes_app for all methods webfakes/tests/testthat/fixtures/git-repo.tar.gz0000644000176200001440000006217314740243712021606 0ustar liggesusers5eX8**P D#EP"! )"|E+Vb⦆`;k{ow. ~=Arb{YYY9c\⋵#femkgoxK.%$vH‘%\~'pj7 Op. 1;)å2V_0lemhoU9"!+pzGk;k5W"xpD| M/I2y"I*[6H"!Y4y|*L"il ?I`pR#1.JqQ)#d8FII|!,2Xbi 80Y-Uz|p'2< 񏦙ʗHD5iQ #B=W=oec_G;:C3gsls|!^;8U#eEu|O[[[+?w\B!;bJù|&KK1hc&*aD,~U 7?Y$J?rd :wb6'2!:mmm/C 7m,/KvĠ L&E*?-6*ǝV<nílG)ތ+Opy8/љd`o:SH-bMYf ef`֖bPiRg@15:9ɀT3*V[8Tqb;>Pat:M dBVLDf/h\OØE8fbi4-& gMm<4ZӲv?`0)HdKZ[[ԓvjo8SOJap c@yc}ةlr@lЕlBW \ d%RK@r@ Q\0P F9O"JPPA?AiRQq݄8"(! PBJYcL&zG.$8;}>.@;JPP%l!'%ZLE O21>B1!A l)QA %TuP{ Hep)5a0[f$&Bs xbw$%d!64@!M5ǝ24p~K#LM  PHV+@,8b S"˔Hsqq%i<>F:(BSAGK3MՕ} hs6.es^ NV@1*}WQ@1T(!/4qP"@>и b1Ӕ`!*Fk* '%@ "A ㉯DoVeNV&t W(%(9<N_ # *a`H,5drc#f?+W 3 yyD`ITj tXHN7q%ACI$duE?FYʆ=T|jrԩAX?*)JWwڔH&49x v%AbHJ.4:]u&!2 #I!B"]T!A5-R ґb\"@'5.Fabρ )lF'5]lPTpI0*3T_MM8+3h,@s{` -Sfj+ ѳ~ 8<3U #f A6  S$ YBR6*zҊ fh@G CT$Д @)dMǨ $DD)(J+;'I('Ɂ(mP'J5/%zrY0`~`P wēBafX$OhX@yE2@(8kIlMq>@/92 FK7`|^4SA T^FPR q|0:O8D,%>)Xpz=8`< Qb@!pr,Ey|D!΁hI&1d Ra:@9#h2|0)2A( Pm+$39la|IF,BSIK@2ᛱ Xpa5a"PՒ4^JT5B@ ?ҌL_Q —{E= -BQ:`oSkb+A$] $HN!b>W>*XHؐQaMDTHRz: 6Vgt!C6moQDsalp:9A.0/"8QHB"@ ͷZzR 8T`]Ɛ?,0;,@L:*$6TADo!A] ؤIiIOf``ф+e!*'!gARʡP(dX4J;03"'Tg5JRq@}&é x_S1$ӣGAIx'b dYY<7@SܘW7-Un[E޵$߳ľ QG$$i4O 8½<!D'/ug!OI Ga2 Bex|!Pɾ2Ȳ҆ ~4DYMiRT7 %@]Y Pu.aC{0IOBB`pKI8ͫ^PA@ IAMh Bo@u(ȶFJ_W6OȐsh[J1(QC^_Jq`u`i?;;+:_;+o.QLl 1S -,QRiG8> ڌ:ٯ:s6@F՚Tf_3. tW&<\ C%/`бX.ekJBe7*Z)hJ3i#`BIq f-% MR9No WԼHى"{X`B0l6RK'٠QF'INHr/($} \JHeHL%!0E #u`ĆS7_+K@o1Ul|DH }M 4UטQ9`>FLD UoBZB8dSi}c0(APȿ,er(4P}3z l &C4u`Тh*:,S@p BХUMc ֤ϖ6:<9LjL$A5g`ݻC@A;0!P2JM[ | b XESPn&"??+#K-?h` &0hCU |ҞZ&AU[ .7`#RXLd@ Zl0F3@dv! seBe iawƣt[5hS+I2 }T$$lĚ b!..4M[K=qJ6\ mdh(T/`˅xRy"V9 1ԳxDIXʶp+&]<TD@Vn.IQ"pL&}YKڐ TIB'`Pδ>9-0+ ̚iC'VDހBh6TuZZ . @$˸cnntM^f ǡx3F-zmT'`1tHh@ X'̈́"}@A;'!TB &U* wR*'AxʷwǮԈȴt(qmehFR뫍^J7 vQ%"}a BUAtUU*%T.KJae\l Y #@q2u<)ГlrffDGr\tJE2#w"ps˒&HN.׹u.QWت/?97]шw4@% =O #|RPF˱L)9HT"! 3OBfKE<*(*LmKdt'`2+"Ԥ*X 0Mp(4<-_o [=ϕwL]SdTTQ} xh^GHW 5#'=$=V L2R|w+fz2C?S z9M,tG{yIK(/ Cf#!S*_])LbC3l2T(DD0q&1c`ˀ( 7p/GlG?2@6VGEE HQPP`"ʽ`&R0K8#Mz <%8ޯ i02B R;|&X UADJdHkD6H>-Xh& w*AXkXt,g;T+)7,凂` CpRZJ9Q)-3Y;z2; p3uCLP3\%g0|Vʊ0 m6+rTF vwSD$p5I$"rl :>(mwp7Dy6>F4ZC|V";"8fBx ie{}jb ,0M,PLȨf1FQ Ć9a0!Zk_,a NI%5,`k CY#cUCc1TµyH>8)Lwp@71|!`ƤRI !V+EV-z ف 2 (\ v!6WH*cz z?烨D#*FD MHZ*9AE1)%&<_`ƿC=ݟ{xbߴKF䀇L$VTD(]*IZݔhg. ?oe4`_o{_9aj_wlIC8@H~吮ɯɯ"~XO_hCj~ ~S×pmD08%24HB2JG2ɢJ"|VfzR~O{t*H#6mUGQ~tm3&DI0:&砬&r|hk%?nT6rg`&V& X1x֊wGW Uo T FX@~ `Ny e3HJ1x@V~'kZ.ߨ~T? IRWpP$z,C T 0huY{ _ 06YZ!-~m "` >`#LT\*s\V)VBjfD 9$x % (AѸG|! vvK^ł`^`l@Z#L6T; SMQ0󕃀)9] FRN(QaF@ BTTTmfA/2k)R$0XlFY'CC%ldWdRNiQT_Y[fTV jN-r+X TBT@ߡ.R )@_IJP=>Jv4Tg ($SnDt#*)cEiNByD%źb{V'SV'^ѵ&T)"ĉSz,4nWqxPPRLXnTW$ޔV9u!}Vtۯ—J[2Ni~5\Tܯhkf1Km{0h!BZN)2A=N\כ<ǟW{[[Ǻ~pljPZxh _8OUB8Ylp\;B (<EB4\@G(ї)i+YʄPi MwB;O&ԅ %D~B 'wي$&.Jj'`j/=3%P-A/ =Vj6FPE'Njc ށOCk]@2&_l yam!Vc@`|ϭuJ%pH/85E31ʢ0Ŗ ΕEf=Щ~/@T5";|*QD I"D\hZ5J݊BU"%/x ̿Bp)5`=j`~1-d".uFJ3X4י8lCT_:E^$/Qqf#//ʝ(!3jR`a k#CS;UaE 7Aɚ}!VG?#4l.5)ǘDVp䵃-T'rYp,NCJ 'F@/2-V M."jEEqA*@7Q2DC@"0u]xGD 0T* K1ٌZ}q\TEr]Ef%t\sG j:+" Syc!aP2<do$ K5%DRex..2a'CLd>ԁJNQ$׏ [d4@4*7E463 ںRKPכ:n2j/UwVXh߯}=֡n/g;.b@|d&.8ȴ@""nFCd8QhCc=Ζ@uk.ΤوdP}-S"h:Ne񋙱bDð?UBj M_Rjہ`/\_R?)mm︾3m#;ʖml8v3džslq'. Z oo_w;{0^:y{v{nGp7 ;`7u$&n[pܾ[5mnpk-ۃ;nWpہ[܍ܚn p7ܝ ~Op;knnnnۀ ܦ7KmNC4`E`Q5p޾tHc nTL30gVi$Y=`NvvdcKj{U H 3Jؾ䀷5nC-W]^Q=w|wQMhÍ.0j6>rnV74hN S7.叴<7ޠToa5SrrIґEWUk.8D-u߃JtKmh~zf:Mcwm7*cٝuqߗIM!'<KM-~; }}1)sJcBoL<-YwA+2<8a]fҠ.y7>{}YޅiOJ=2^ȪN^M{X 33" Sǿk޿]Ō|۴i+gOjyL1}'_>O.n jLif9~I9asL/9`ne7ZXW\NJK6ٷg+&/d(JrJ@' /dtwзzĦU\u8LީŦ͡##{_!B~ H/e + Bs]ẍ˃s.K_~Kwm faIN>kt+0X>O/KNϸxyzrιg$oXˑsǗܥ_ hu;ngؽE]^@>몓 }քF+Ch++8IYkr|'u[y`0k `I|:zudzCLn=ak1/63/@#,kw!e;Uʳ:#f̲ܻúʏw鴫CLq3=I(zkeO5uz{EIFZe ܝ ˦]G3LTtf@}fGk78aڶfw~sgx^:jQ,mD)[Tv\ErvvȥI$fjev}YG< vˁYyyz¤e:;DT T dY^J:e][< ޗGީ [H!6c6a>[_};>쫭z%V:j[̵VSqJq#'Y =l(;{F}4ɹ.1˚o;vr3 w#Z Ѵ<{lGkO6=/t\+?:*!{/ =\xql{֖OXrnMwe[΢_xPrE/AJh֔A=,ʯ|-ZTHJ vsHcϵY{w=NOnR|rek#5"^oU9d#~8uĶ)65 H|woљ{wIԼǮ^MG,Ne  9oxc|XЛO̪jƵ\kŴo = NX~I@3ƞK-[FLRM&n*]ci4uS] 嫚Qx3F׌c'Slȫy_?q}6gk^u0wW]fU+5/8dqz3sO1Orjicg?zk4ںI*hCnEf~8g#=.;c]/8{gk=QW]jsJc'/h%f89(HsVzZI;+wqja3}\Wvr·m'&:w+&|T3YgM UjIQg:!t820~/ca-hI8 0ٜ!6/ch6bZRD\0-ݒCekzmu#dTzzq¹m԰17As羽`6] /js޾].&,@NlYX%+~z?tm54f#iw krH_ Χunἤ<F9@Z}8HZsgll?!O%UWf {`NF_MO[Fú=VL=s٬+{6}77e2PGGȭy֊#b[uzLky.bVм-DΫvm~܋m."1ׄ5*gJ:]}Nc^u.2^6׹_i۰kq~ێK9o:\gFe7Dk<{ <ѻ<6fj;6G$&}ݦ7>0fo[pr_%=-B7]SZ2ͧ=,Z}(ש!#:aXv7Qb[Eŭ`uf9&* kCGT9xG/4Eů.xWdt7{{y&p)k6蜨Vۃh7\Sm&O~E /+'fMD";sox; 6}ƇOO՝2R'oc>{3[%L{|ӊUFz8`p6vgs~#!waۋrg+ZIۏJ?7>tWͽv H}D ]L*q,򾍧Uj2ƌENK0.\.ZȟBqL?հforlw8XtuҼޚirO1rEЙlFg98t<>0kP\WNnPu4 ,G{RxlADA#s^ըM7F42zՏfv<0Scqrcږ-S;H{5md͍,<۳eFۖw݌fl|њ7qv^:<7Mtӭo~p+wNbކų<2'cƭ|'YX1ƅYx;]Fo1Yz\ƒA< g?i“q6nq'ge>4{-˸ 6Yf#LJXաWx&eɖO]f7}24;ͣkUG.kqM#gڜԄf{.|婳NWug/˝9˽<yz ۭf:[nXge ^/٦ɺeqJ'tʃSo֌Nh2ߟ`sl/Q.kk.dz4oGbځ[}8ճyEfm;w+`.F"CzatZ3f.U)m[]iՈc !~[\[~ŮGHy4=ŧ>~3̻.V|dOQzèOo_[&BӠvTw'/n9v |`"N"M}Y]?qR`;nj6 }&];8NMўC6ʺu4;m6X .^?y["O}7)pqݻ3)Vף/(Yi$f}h:QEUjt;$7ieF˞/yXe5m@Zw֜oq̢]hGk^/{tn"-M58iq4(~CFYKN#f:u(зTJ85)~1FA}9ڢiNVǼݰt+KMՌp@svksu o,htY|^i]ud{!mC[V8`ԱZwXx7RbmВwWr&oM?FًnG{2;w0q+}y wԜ}[T uۀNswlX[3ߡ[Uu+mLJ:YY1-673ePv-JWw=a:Ž ?$|n~X+Ŧo\¢ne-r. tcL1F;էx{ՀkmO7eK>5([4-~MgCN0-Yazt:|̲o#~\;KiKҟ| ݚYtD]Ϧ7[jCV?_\ɦO=lЃc ]hGܙ$7JC w-,w]4M u9On2G6=&9سL7su)R69]kukFf܄C>Y}*}>kgy齚ի@KeD.;$>mVĠ.f,K5i6Lk)}F/)Ó,L*V?;W.K_&|8)-#NGWO?env|✼sQ 6;p;k]U٩\[Npl+ٖ2nXc;y ZU!}@;}dߧv<],Pص-RGfϬY).8r&ʸZm& #M1-/gY.th@inr5]v6\nf gjjqmuypȼc@fΌx+n;|mT1{1lp1gc^Iw:qW}9w$øjuBc¦Y?LZ;,ęYeMh3y9°]Ԗk5EjX؍~<[r -"H?UL^]6:'%CXF;iO4w{їouh;meo\ Y`hF4nd#UkO.pQt]\][dx{?e[lΥ^3m72Qճׇz8u쒫^^A=jqݻ[-޽3bnէݚsG74d)J)nO3L쪑䈋I7֝9 *?21MoZ93 +>ezB,F:Nm&.}f _G];FI6}yݑ]=s-XqÈ#?Ӽqm{w[l e0o\tKxWxвV!v5^d%IjFoםch#iN]9g a{tf,?Xڀ->AfݓL4J\aڑww1hMuҳ:{&=̽ث-_95_iLׁ1 &7XgHzIlـ%WN4ǛhΣ bu2wۭ@ާoPlⷎyU9+ّg;@N+^;]]K:!fQ=߫\9&k{[!|l_рM7t`vna ! 6j8׉S=&VU!2L:_*=4Bm}ۜ4}_Z?n-w*Ϙ{Cjlbo;KenenTc {s+6woAc͞a;fiq̗7_=rwpI9:uOj׼3=5d^:d] U #CrNgei>bAk󂬋onthS 1kd:;n񨳣9]^=ɀf_Z֎kٛ 1fT&v1TV#=|thnGC%)0KmΚGk>3CCr'wwS>`CoaD]Fzϫ~zjߞ!hGқ/KoSV+u`Ω+NmgTm1yN^<ී?Kosmh' 6kW4h^GeynyjZ6jt۸~-\}ƦLj ܴ)n2Xb^,dnΓ*xܣʼn3;iF ߢ|ґa![[7x ]}KN2q'(fu;i26 ,(g'2<;o+&0hgIQBIKeeZ<{E/]#8Q3ɡWjZ;W8mGigծR?xǸ֙ڷMQF V3Wv7ixvܸ݊;V~#ǭiU.oP~c7%OO^? +//>k̰R:o=xS3VX{grqcwQu@/(uVض3U%-Uu06>{e##Lv˟$w~2^`Reߋza-k-Yse==woߧtY~m[n&_+00tV.`NxԹr 2kf֮CX'ћhHk΁Zܴ5GiR{_'-dlSv;-=u4dw鷵ˌn]Lm= K[,55?:ܗ Gq0mTp$%>jרR5_02U\8et%r=wV%w南_L9G=1I^MF}t94g&Jx%z:ҕL㸌_a^yVs6TD{72;Wu\7}S?yM{#oI-w誴+Fݖ3C ׮Kyl So&<{UőS%cYso=ҞXvcE=7J{D;渞?[dߍc>?{ջHlw&$=iyuMձw|svgJ7n;i}eFZS?󝋻F5 nzr@|k,cfBIͺZ;H3vd9o^NBU]+E/ڏ(2!u#%4ۮYldyM'O 7$onGUFܩUuޥcG!Σާ _%ޤcMw vzKe/^sc.{LsG)z6'ǚ#`λ4"k߼ڲ5$ A%I IR˕ IIM JP@@ 6 H5LswܪyoU~?NwzɥKF[xHN'Gs53WLSܩ5xʷ:W'\WZYb.1&E k1] d"-͝O0lB^') pX7';7|v<;6@̛ʅlE"IG+7fRW5`DK.'N.]ȋjįQB2>y <5̆{݄Ìe\r*Ye>dA*3w :5ZX;LȲ|۟ RT 1e  ۷ 1+PyHBj]7 }ԖQݏ#rָ-O[*bNr>9v#MHC|!Xh>G؛@yr~?TPL\0̑aj&eP֚*>'M\YN1JjaDTTGCծӼ[Uzt6U>d È,:+ IwH- q6).6tOfm1dR9NFaf@WZ0W 1E t$*K o`a:=_Ycl{g<>9q#[ XfbIQ,s* [5oק& z[7HT}CV9晷q7팞M !ttȠVaӧ\yf3Pey8?зڊg8ުD{t$'mc"3{X(+qd9Y>eQl}ZBrR-l}cQإn3R˲`=B`gU(~(5=PkEf+Мܮly0/(?6Ojl>lZ^%>_|^wpu~Pb'ACDS9ok~j5'[e:~x-Z"h`%MB]+ KdΕq/nawƻh_#CD)uqQ+/aeP+Fk55x^Vw7onoK)CJθ.<Dmx<( `ߩvҦFX~H&Ze8fwۨ"{YiAQWyIBEՏd$EUC%Ә5E24Fk>c֥dM`/!wʾM8\;t b%1%-E}Ij<_ &VHzB#I{=eb0DY} L czS33=Fm쇨HhٔX4t.}_\g%kmu_pi1 &5wLM 2:]]٬5Rk'KG/e_(XVu]S8W'Kw"GCEKEЫc$#Brs arfMֽX ##,l5cDD)i@? LQ͈1Q[/6-:BU|\>nGd=:_lix54+BJ),j2S&A;=LFZ% [<nGyrE07SU!$<'^`Dx#-SgJq0Wo—q*r#_bක!U+v,ssblNw<}GG[\)+OoĮ 4İ\4m2+[h?eָNJis  #,sK HegY2iIP _)vg!@aX c 6]_?l4އO kXc 8Dgxw߲eodaO0x,z6:[H0 3aYEc} 6 4L>EE_(A z [ُ ςtbpv4I<ݗEl9_eĀ -9x4"߱lK(ƄUwAY7;YҢw.Ѹ5u^g\"=7u: *)*}|v[ol23-FflZ+kert-1Pچ{*XB`eTZ t&i&k1ߓnTt&<䘫#.z055B/ku_5,Q hTSڭڡ4\5'O߬{1/7]gEVpc^.f(\8s! 3|ZzW9måyIffW3%k=8*]/`p"a+}t L٦/ULp+`&N>l(Iݲҁiޮ%o^|[L/h\_׼ȭ$iU4$%NfӇӭKgUP`N2ޫ El [~vػxq^NcwF?耛!$QM&+7~Tx'eSY)I{fT!FrZjE)s/0ݒ7=ոQrkr|dE.s"@ĝzxg#kP%`-A"@5\mx?Ƒ15U uk@ɇKˁ$}OփB+qo=16t6E?xe%zkjHT]tZbOkHgݤ,}'s rno'|0̢A'Y&k=FˉxaAc"Y1%c73XDt$.j7Q}L)5Sb*4T6}f܌D1U%_,pr3i4hzq!g,6b9s?4Ufh yS0Uf`%g`42-H4cd% 20@<9@E@Z` -@q:\2@_MÁϦ@60 Y@}t@/7@4Z7^@ 6@_p;'4c#~@ ;Z \rhM)khmC jbY9@OQF.zr3{2/V+zWǘ+~ů+g92webfakes/tests/testthat/fixtures/static/0000755000176200001440000000000014172041777020215 5ustar liggesuserswebfakes/tests/testthat/fixtures/static/subdir/0000755000176200001440000000000014172041777021505 5ustar liggesuserswebfakes/tests/testthat/fixtures/static/subdir/static.json0000644000176200001440000000002114172041777023660 0ustar liggesusers{ "foo": "bar" } webfakes/tests/testthat/fixtures/static/static.html0000644000176200001440000000006414172041777022372 0ustar liggesusersHello world! webfakes/tests/testthat/test-app-process.R0000644000176200001440000000355215026556433020415 0ustar liggesuserstest_that("error if cannot start", { # does not start before the timeout app <- new_app() app$listen <- function(...) Sys.sleep(1) expect_snapshot( error = TRUE, new_app_process(app, process_timeout = 100, start = TRUE) ) # errors before/while starting app <- new_app() app$listen <- function(...) stop("oops") expect_snapshot( error = TRUE, new_app_process(app, start = TRUE) ) # sends a different message first app <- new_app() app$listen <- function(...) "foobar" expect_snapshot( error = TRUE, new_app_process(app, start = TRUE) ) }) test_that("get_state", { app <- new_app() on.exit(proc$stop(), add = TRUE) proc <- new_app_process(app, start = TRUE) expect_equal(proc$get_state(), "live") proc$.process$kill() expect_equal(proc$get_state(), "dead") expect_output(proc$stop(), "webfakes process dead") expect_equal(proc$get_state(), "not running") }) test_that("env vars", { app <- new_app() on.exit(proc$stop(), add = TRUE) withr::local_envvar(list(FOO = "foo")) withr::local_envvar(list(BAR = NA_character_)) proc <- new_app_process(app, start = TRUE) proc$local_env(list(FOO = "bar")) proc$local_env(list(BAR = "{url}")) expect_equal(Sys.getenv("FOO", ""), "bar") expect_equal(Sys.getenv("BAR"), proc$url()) proc$stop() expect_equal(Sys.getenv("FOO", ""), "foo") expect_equal(Sys.getenv("BAR", ""), "") }) test_that("env vars 2", { app <- new_app() on.exit(proc$stop(), add = TRUE) withr::local_envvar(list(FOO = "foo")) withr::local_envvar(list(BAR = NA_character_)) proc <- new_app_process(app) proc$local_env(list(FOO = "bar")) proc$local_env(list(BAR = "{url}")) proc$start() expect_equal(Sys.getenv("FOO", ""), "bar") expect_equal(Sys.getenv("BAR"), proc$url()) proc$stop() expect_equal(Sys.getenv("FOO", ""), "foo") expect_equal(Sys.getenv("BAR", ""), "") }) webfakes/tests/testthat/teardown.R0000644000176200001440000000002515026556433017017 0ustar liggesuserstry(httpbin2$stop()) webfakes/tests/testthat/test-httpbin.R0000644000176200001440000006533215026556433017635 0ustar liggesusers# HTTP methods ========================================================= test_that("/get", { url <- httpbin$url("/get", query = c(q1 = "one", q2 = "two")) handle <- curl::new_handle() curl::handle_setheaders(handle, "foo" = "bar") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(resp$type, "application/json") data <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_equal(data$path, "/get") expect_equal(data$headers$foo, "bar") expect_equal(data$args, list(q1 = "one", q2 = "two")) }) test_that("/post", { url <- httpbin$url("/post", query = c(q1 = "one", q2 = "two")) data <- charToRaw(jsonlite::toJSON(list(foo = "bar", foobar = 1:3))) handle <- curl::new_handle() curl::handle_setheaders( handle, "content-type" = "application/json", foo = "bar" ) curl::handle_setopt( handle, customrequest = "POST", postfieldsize = length(data), postfields = data ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(resp$type, "application/json") data <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = TRUE) expect_equal(data$path, "/post") expect_equal(data$headers$foo, "bar") expect_equal(data$args, list(q1 = "one", q2 = "two")) expect_equal( data$json, list(foo = "bar", foobar = 1:3) ) expect_equal( jsonlite::fromJSON(data$data, simplifyVector = TRUE), data$json ) }) test_that("/post and multipart data", { on.exit(rm(tmp), add = TRUE) tmp <- tempfile() writeBin(charToRaw("foobar\n"), con = tmp) url <- httpbin$url("/post") handle <- curl::new_handle() curl::handle_setopt(handle, customrequest = "POST") curl::handle_setform( handle, a = "1", b = "2", c = curl::form_file(tmp, type = "application/octet-stream") ) resp <- curl::curl_fetch_memory(url, handle = handle) echo <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_equal(resp$status_code, 200L) expect_equal(echo$form, list(a = "1", b = "2")) expect_equal( echo$files$c, list( filename = basename(tmp), value = paste0( "data:application/octet-stream;base64,", base64_encode("foobar\n") ) ) ) }) # Auth ================================================================= test_that("/basic-auth", { # no auth supplied url <- httpbin$url("/basic-auth/Aladdin/OpenSesame") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 401L) expect_equal(resp$type, "text/plain") headers <- curl::parse_headers_list(resp$headers) expect_equal(headers$`www-authenticate`, "Basic realm=\"Fake Realm\"") # correct auth handle <- curl::new_handle() curl::handle_setheaders( handle, "Authorization" = "Basic QWxhZGRpbjpPcGVuU2VzYW1l" ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(resp$type, "application/json") expect_equal( jsonlite::fromJSON(rawToChar(resp$content)), list(authenticated = TRUE, user = "Aladdin") ) # wrong auth handle <- curl::new_handle() curl::handle_setheaders( handle, "Authorization" = "Basic NOLUCK" ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 401L) expect_equal(resp$type, "text/plain") headers <- curl::parse_headers_list(resp$headers) expect_equal(headers$`www-authenticate`, "Basic realm=\"Fake Realm\"") }) test_that("/hidden-basic-auth", { # no auth supplied url <- httpbin$url("/hidden-basic-auth/Aladdin/OpenSesame") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 404L) expect_equal(resp$type, "text/plain") headers <- curl::parse_headers_list(resp$headers) expect_equal(headers$`www-authenticate`, NULL) # correct auth handle <- curl::new_handle() curl::handle_setheaders( handle, "Authorization" = "Basic QWxhZGRpbjpPcGVuU2VzYW1l" ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(resp$type, "application/json") expect_equal( jsonlite::fromJSON(rawToChar(resp$content)), list(authenticated = TRUE, user = "Aladdin") ) # wrong auth handle <- curl::new_handle() curl::handle_setheaders( handle, "Authorization" = "Basic NOLUCK" ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 404L) expect_equal(resp$type, "text/plain") headers <- curl::parse_headers_list(resp$headers) expect_equal(headers$`www-authenticate`, NULL) }) test_that("/digest-auth", { # url <- "http://localhost:3000/digest-auth/auth/user/secret" url <- httpbin$url("/digest-auth/auth/user/secret") handle <- curl::new_handle() resp <- curl::curl_fetch_memory(handle = handle, url) headers <- curl::parse_headers_list(resp$headers) expect_true("www-authenticate" %in% names(headers)) creds <- parse_authorization_header(headers$`www-authenticate`) expect_equal(creds$scheme, "digest") expect_equal(creds$realm, "webfakes.r-lib.org") expect_equal(creds$qop, "auth") expect_equal(creds$algorithm, "MD5") expect_equal(creds$stale, "FALSE") auth <- list( username = "user", realm = "webfakes.r-lib.org", nonce = creds$nonce, uri = "/digest-auth/auth/user/secret", qop = "auth", nc = "00000001", cnonce = "0a4f113b", opaque = creds$opaque ) hash <- function(x) digest::digest(x, algo = "md5", serialize = FALSE) HA1 <- hash(paste(c(auth$username, auth$realm, "secret"), collapse = ":")) HA2 <- hash("GET:/digest-auth/auth/user/secret") auth$response <- hash(paste0( collapse = ":", c(HA1, auth$nonce, auth$nc, auth$cnonce, auth$qop, HA2) )) authorize <- paste0( "Digest ", paste0(names(auth), "=", auth, collapse = ", ") ) curl::handle_setheaders(handle, authorization = authorize) resp2 <- curl::curl_fetch_memory(handle = handle, url) expect_equal(resp2$status_code, 200L) cnt <- jsonlite::fromJSON(rawToChar(resp2$content), simplifyVector = TRUE) expect_equal(cnt, list(authentication = TRUE, user = "user")) }) test_that("/bearer", { # no auth url <- httpbin$url("/bearer") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 401L) headers <- curl::parse_headers_list(resp$headers) expect_equal(headers$`www-authenticate`, "bearer") # bad auth format handle <- curl::new_handle() curl::handle_setheaders(handle, authorization = "foobar") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 401L) headers <- curl::parse_headers_list(resp$headers) expect_equal(headers$`www-authenticate`, "bearer") # correct format handle <- curl::new_handle() curl::handle_setheaders(handle, authorization = "Bearer secret") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) echo <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_equal(echo, list(authenticated = TRUE, token = "secret")) }) # Status codes ========================================================= test_that("/status", { codes <- c(200, 301, 401, 404) # get for (code in codes) { url <- httpbin$url(paste0("/status/", code)) resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, code) } # post data <- charToRaw(jsonlite::toJSON(list(foo = "bar", foobar = 1:3))) handle <- curl::new_handle() curl::handle_setheaders(handle, "content-type" = "application/json") curl::handle_setopt( handle, customrequest = "POST", postfieldsize = length(data), postfields = data ) for (code in codes) { url <- httpbin$url(paste0("/status/", code)) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, code) } }) # Request inspection =================================================== test_that("/headers", { url <- httpbin$url("/headers") handle <- curl::new_handle() curl::handle_setheaders(handle, "header1" = "this", "header2" = "that") resp <- curl::curl_fetch_memory(url, handle = handle) echo <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_equal(echo$headers$header1, "this") expect_equal(echo$headers$header2, "that") }) test_that("/ip", { url <- httpbin$url("/ip") resp <- curl::curl_fetch_memory(url) echo <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_equal(echo, list(origin = "127.0.0.1")) }) test_that("/user-agent", { url <- httpbin$url("/user-agent") ua <- "i am libcurl, that is my name" withr::local_options(list(HTTPUserAgent = ua)) resp <- curl::curl_fetch_memory(url) echo <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_equal(echo, list("user-agent" = ua)) }) # Response inspection ================================================== test_that("/etag", { url <- httpbin$url("/etag/foobar") resp <- curl::curl_fetch_memory(url) headers <- curl::parse_headers_list(resp$headers) expect_equal(resp$status_code, 200) expect_equal(headers$etag, "foobar") handle <- curl::new_handle() curl::handle_setheaders(handle, "If-None-Match" = "\"foobar\"") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 304) expect_true(length(resp$content) == 0) handle <- curl::new_handle() curl::handle_setheaders(handle, "If-None-Match" = "\"not-foobar\"") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200) expect_true(length(resp$content) > 0) handle <- curl::new_handle() curl::handle_setheaders(handle, "If-Match" = "\"foobar\"") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200) expect_true(length(resp$content) > 0) handle <- curl::new_handle() curl::handle_setheaders(handle, "If-Match" = "\"not-foobar\"") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 412) }) test_that("/response-headers", { url <- httpbin$url("/response-headers") resp <- curl::curl_fetch_memory(url) expect_equal(rawToChar(resp$content), "{}") url2 <- httpbin$url("/response-headers", c(foo = "bar")) resp2 <- curl::curl_fetch_memory(url2) expect_equal( jsonlite::fromJSON(rawToChar(resp2$content)), list(foo = "bar") ) headers <- curl::parse_headers_list(resp2$headers) expect_equal(headers[["foo"]], "bar") url3 <- httpbin$url("/response-headers", c(foo = "bar", foobar = "baz")) resp3 <- curl::curl_fetch_memory(url3) expect_equal( jsonlite::fromJSON(rawToChar(resp3$content)), list(foo = "bar", foobar = "baz") ) headers <- curl::parse_headers_list(resp3$headers) expect_equal(headers[["foo"]], "bar") expect_equal(headers[["foobar"]], "baz") handle <- curl::new_handle() data <- charToRaw("{}") curl::handle_setheaders( handle, "content-type" = "application/json" ) curl::handle_setopt( handle, customrequest = "POST", postfieldsize = length(data), postfields = data ) resp31 <- curl::curl_fetch_memory(url3, handle = handle) expect_equal( jsonlite::fromJSON(rawToChar(resp31$content)), list(foo = "bar", foobar = "baz") ) headers <- curl::parse_headers_list(resp3$headers) expect_equal(headers[["foo"]], "bar") expect_equal(headers[["foobar"]], "baz") url4 <- httpbin$url("/response-headers", c(foo = "bar", foo = "bar2")) resp4 <- curl::curl_fetch_memory(url4) expect_equal( jsonlite::fromJSON(rawToChar(resp4$content)), list(foo = c("bar", "bar2")) ) headers <- curl::parse_headers_list(resp4$headers) expect_equal( headers[names(headers) == "foo"], list(foo = "bar", foo = "bar2") ) }) test_that("/cache", { url <- httpbin$url("/cache") resp <- curl::curl_fetch_memory(url) headers <- curl::parse_headers_list(resp$headers) expect_true("last-modified" %in% tolower(names(headers))) handle <- curl::new_handle() curl::handle_setheaders( handle, "If-Modified-Since" = http_time_stamp( Sys.time() - as.difftime(5, units = "mins") ) ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 304L) handle <- curl::new_handle() curl::handle_setheaders( handle, "If-None-Match" = "some-etag" ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 304L) }) test_that("/cache/:value", { url <- httpbin$url("/cache/10") resp <- curl::curl_fetch_memory(url) headers <- curl::parse_headers_list(resp$headers) expect_equal( headers[["cache-control"]], "public, max-age=10" ) }) # Response formats ===================================================== test_that("/deny", { url <- httpbin$url("/deny") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200L) path <- system.file( package = "webfakes", "examples", "httpbin", "data", "deny.txt" ) expect_equal(resp$content, read_bin(path)) }) test_that("/gzip", { # curl seems to ungzip automatically, so we use url() url <- httpbin$url("/gzip") con <- url(url, open = "rb") on.exit(close(con), add = TRUE) echo <- readBin(con, "raw", 10000) expect_equal(echo[1:2], charToRaw("\x1f\x8b")) json <- readChar(gzcon(rawConnection(echo)), 10000) obj <- jsonlite::fromJSON(json, simplifyVector = FALSE) expect_equal(obj$path, "/gzip") }) test_that("/deflate", { url <- httpbin$url("/deflate") con <- url(url, open = "rb") on.exit(close(con), add = TRUE) echo <- readBin(con, "raw", 10000) data <- jsonlite::fromJSON(rawToChar(zip::inflate(echo)$output)) expect_true(data$deflated) }) test_that("/brotli", { url <- httpbin$url("/brotli") con <- url(url, open = "rb") on.exit(close(con), add = TRUE) echo <- readBin(con, "raw", 10000) data <- jsonlite::fromJSON(rawToChar(brotli::brotli_decompress(echo))) expect_true(data$brotli) }) test_that("/encoding/utf8", { url <- httpbin$url("/encoding/utf8") resp <- curl::curl_fetch_memory(url) expect_equal(resp$type, "text/html; charset=utf-8") ptrn <- as.raw(c( 0xe1, 0x8c, 0x8c, 0xe1, 0x8c, 0xa5, 0x20, 0xe1, 0x8b, 0xab, 0xe1, 0x88, 0x88, 0xe1, 0x89, 0xa4, 0xe1, 0x89, 0xb1 )) # On windows end of line is converted to \r\n expect_true(grepRaw(ptrn, resp$content, fixed = TRUE) %in% c(9085, 9233)) }) test_that("/html", { url <- httpbin$url("/html") resp <- curl::curl_fetch_memory(url) expect_match(resp$type, "^text/html") expect_match(rawToChar(resp$content), "", fixed = TRUE) }) test_that("/json", { url <- httpbin$url("/json") resp <- curl::curl_fetch_memory(url) expect_equal(resp$type, "application/json") path <- system.file( package = "webfakes", "examples", "httpbin", "data", "example.json" ) expect_equal(resp$content, read_bin(path)) }) test_that("/robots.txt", { url <- httpbin$url("/robots.txt") resp <- curl::curl_fetch_memory(url) expect_equal(resp$type, "text/plain") path <- system.file( package = "webfakes", "examples", "httpbin", "data", "robots.txt" ) expect_equal(resp$content, read_bin(path)) }) test_that("/xml", { url <- httpbin$url("/xml") resp <- curl::curl_fetch_memory(url) expect_equal(resp$type, "application/xml") path <- system.file( package = "webfakes", "examples", "httpbin", "data", "example.xml" ) expect_equal(resp$content, read_bin(path)) }) # Dynamic data ========================================================= test_that("/base64/", { url <- httpbin$url("/base64") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200L) expect_equal(rawToChar(resp$content), "Everything is Rsome") value <- base64_encode("hello there!") url <- httpbin$url(paste0("/base64/", value)) resp <- curl::curl_fetch_memory(url) expect_equal(resp$type, "application/octet-stream") expect_equal(rawToChar(resp$content), "hello there!") }) test_that("/bytes", { url <- httpbin$url("/bytes/foo") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 404L) url <- httpbin$url("/bytes/1000") resp <- curl::curl_fetch_memory(url) expect_equal(resp$type, "application/octet-stream") headers <- curl::parse_headers_list(resp$headers) expect_equal(headers[["content-length"]], "1000") expect_equal(length(resp$content), 1000) }) test_that("/delay", { url <- httpbin$url("/delay/foo") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 404L) url <- httpbin$url("/delay/0.2") st <- system.time(resp <- curl::curl_fetch_memory(url)) expect_true(st[["elapsed"]] >= 0.1) expect_equal(resp$status_code, 200L) expect_equal(resp$type, "application/json") echo <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_equal(echo$path, "/delay/0.2") }) test_that("/stream-bytes", { url <- httpbin$url("/stream-bytes/100") resp <- curl::curl_fetch_memory(url) headers <- curl:::parse_headers_list(resp$headers) expect_equal(resp$status_code, 200) expect_equal(headers[["transfer-encoding"]], "chunked") expect_equal(length(resp$content), 100) ## seed works url2 <- httpbin$url("/stream-bytes/10", c(seed = 100)) resp2 <- curl::curl_fetch_memory(url2) expect_false(identical(resp$content, resp2$content)) resp3 <- curl::curl_fetch_memory(url2) expect_identical(resp2$content, resp3$content) ## chunk_size works url <- httpbin$url("/stream-bytes/100", c(chunk_size = 30)) resp <- curl::curl_fetch_memory(url) headers <- curl:::parse_headers_list(resp$headers) expect_equal(resp$status_code, 200) expect_equal(headers[["transfer-encoding"]], "chunked") expect_equal(length(resp$content), 100) }) test_that("/range", { url <- httpbin$url("/range/100") # HEAD handle <- curl::new_handle() curl::handle_setopt(handle, customrequest = "HEAD") resp <- curl::curl_fetch_memory(handle = handle, url) headers <- curl:::parse_headers_list(resp$headers) expect_equal(resp$status_code, 200L) expect_equal(headers$`accept-ranges`, "bytes") expect_equal(headers$`etag`, "range100") abc <- function(n) { l <- paste(letters, collapse = "") substr(strrep(l, n / nchar(l) + 1), 1, n) } # No range header handle <- curl::new_handle() resp <- curl::curl_fetch_memory(handle = handle, url) headers <- curl:::parse_headers_list(resp$headers) expect_equal(resp$status_code, 200L) expect_equal(headers$`accept-ranges`, "bytes") expect_equal(headers$`etag`, "range100") expect_equal(resp$content, charToRaw(abc(100))) # Illegal range headers handle <- curl::new_handle() curl::handle_setheaders(handle, Range = "bytes=20-30, 25-35") resp <- curl::curl_fetch_memory(handle = handle, url) headers <- curl:::parse_headers_list(resp$headers) expect_equal(resp$status_code, 200L) expect_equal(headers$`accept-ranges`, "bytes") expect_equal(headers$`etag`, "range100") expect_equal(resp$content, charToRaw(abc(100))) # Legal header handle <- curl::new_handle() curl::handle_setheaders(handle, Range = "bytes=20-29") resp <- curl::curl_fetch_memory(handle = handle, url) headers <- curl:::parse_headers_list(resp$headers) expect_equal(resp$status_code, 206L) expect_equal(headers$`accept-ranges`, "bytes") expect_equal(headers$`etag`, "range100") expect_equal(resp$content, charToRaw(substr(abc(30), 21, 30))) # In pieces, duration is for the full response url <- httpbin$url("/range/100?chunk_size=1&duration=10") handle <- curl::new_handle() curl::handle_setheaders(handle, Range = "bytes=20-29") resp <- curl::curl_fetch_memory(handle = handle, url) headers <- curl:::parse_headers_list(resp$headers) expect_equal(resp$status_code, 206L) expect_equal(headers$`accept-ranges`, "bytes") expect_equal(headers$`etag`, "range100") expect_equal(resp$content, charToRaw(substr(abc(30), 21, 30))) expect_true(resp$times[["total"]] > 0.5) }) test_that("/uuid", { url <- httpbin$url("/uuid") resp <- curl::curl_fetch_memory(url) echo <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_match(echo$uuid, "^[-0-9a-z]+$") expect_equal(nchar(echo$uuid), 36) }) test_that("/stream", { url <- httpbin$url("/stream/10") resp <- curl::curl_fetch_memory(url) headers <- curl:::parse_headers_list(resp$headers) expect_equal(resp$status_code, 200) expect_equal(headers[["transfer-encoding"]], "chunked") lines <- strsplit(rawToChar(resp$content), "\n", fixed = TRUE)[[1]] json <- lapply(lines, jsonlite::fromJSON, simplifyVector = TRUE) expect_equal(vapply(json, "[[", integer(1), "id"), 0:9) }) # Cookies ============================================================== test_that("/cookies", { url <- httpbin$url("/cookies") handle <- curl::new_handle() curl::handle_setheaders(handle, Cookie = "foo=bar; bar=baz") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) data <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = TRUE) expect_equal(data, list(cookies = list(foo = "bar", bar = "baz"))) }) test_that("/cookies/set/:name/:value", { url <- httpbin$url("/cookies/set/foo/bar") handle <- curl::new_handle() resp <- curl::curl_fetch_memory(url, handle = handle) headers <- curl::parse_headers(resp$headers, multiple = TRUE) expect_true("HTTP/1.1 302 Found" %in% headers[[1]]) expect_true("Set-Cookie: foo=bar; Path=/" %in% headers[[1]]) expect_true("HTTP/1.1 200 OK" %in% headers[[2]]) expect_equal(resp$status_code, 200L) data <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = TRUE) expect_equal(data, list(cookies = list(foo = "bar"))) expect_snapshot(curl::handle_cookies(handle), variant = r_variant()) }) test_that("/cookies/set", { url <- httpbin$url("/cookies/set?foo=bar&bar=baz") handle <- curl::new_handle() resp <- curl::curl_fetch_memory(url, handle = handle) headers <- curl::parse_headers(resp$headers, multiple = TRUE) expect_true("HTTP/1.1 302 Found" %in% headers[[1]]) expect_true("Set-Cookie: foo=bar; Path=/" %in% headers[[1]]) expect_true("Set-Cookie: bar=baz; Path=/" %in% headers[[1]]) expect_true("HTTP/1.1 200 OK" %in% headers[[2]]) expect_equal(resp$status_code, 200L) data <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = TRUE) expect_equal(data, list(cookies = list(bar = "baz", foo = "bar"))) expect_snapshot(curl::handle_cookies(handle), variant = r_variant()) }) test_that("/cookies/delete", { handle <- curl::new_handle() url1 <- httpbin$url("/cookies/set?foo=bar&bar=baz") resp1 <- curl::curl_fetch_memory(url1, handle = handle) url <- httpbin$url("/cookies/delete?foo") resp <- curl::curl_fetch_memory(url, handle = handle) headers <- curl::parse_headers(resp$headers, multiple = TRUE) expect_true("HTTP/1.1 302 Found" %in% headers[[1]]) expect_true( "Set-Cookie: foo=; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/" %in% headers[[1]] ) expect_true("HTTP/1.1 200 OK" %in% headers[[2]]) expect_equal(resp$status_code, 200L) data <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = TRUE) expect_equal(data, list(cookies = list(bar = "baz"))) expect_snapshot(curl::handle_cookies(handle), variant = r_variant()) }) # Images =============================================================== test_that("/image", { url <- httpbin$url("/image") types <- c("image/webp", "image/svg+xml", "image/jpeg", "image/png") for (type in types) { handle <- curl::new_handle() curl::handle_setheaders(handle, accept = type) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(resp$type, type) } handle <- curl::new_handle() curl::handle_setheaders(handle, accept = "image/*") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(resp$type, "image/png") handle <- curl::new_handle() curl::handle_setheaders(handle, accept = "application/json") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 406L) exts <- c("jpeg", "png", "svg", "webp") for (ext in exts) { handle <- curl::new_handle() url <- httpbin$url(paste0("/image/", ext)) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(resp$type, unname(mime_find(ext))) } }) # Redirects ============================================================ test_that("absolute-redirect", { url <- httpbin$url("/absolute-redirect/4") handle <- curl::new_handle() curl::handle_setopt(handle, followlocation = FALSE) resp <- curl::curl_fetch_memory(url, handle = handle) headers <- curl::parse_headers_list(resp$headers) expect_equal(resp$status_code, 302L) expect_equal(headers$location, httpbin$url("/absolute-redirect/3")) url <- httpbin$url("/absolute-redirect/2") handle <- curl::new_handle() curl::handle_setopt(handle, followlocation = TRUE) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(resp$url, httpbin$url("/get")) url <- httpbin$url("/absolute-redirect/foo") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 404L) }) test_that("redirect", { url <- httpbin$url("/redirect/4") handle <- curl::new_handle() curl::handle_setopt(handle, followlocation = FALSE) resp <- curl::curl_fetch_memory(url, handle = handle) headers <- curl::parse_headers_list(resp$headers) expect_equal(resp$status_code, 302L) expect_equal(headers$location, "/redirect/3") url <- httpbin$url("/redirect/2") handle <- curl::new_handle() curl::handle_setopt(handle, followlocation = TRUE) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(resp$url, httpbin$url("/get")) url <- httpbin$url("/redirect/foo") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 404L) }) test_that("/redirect-to", { # default status is 302 handle <- curl::new_handle() curl::handle_setopt(handle, followlocation = FALSE) url <- httpbin$url("/redirect-to", query = list(url = "/get")) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 302L) expect_equal(resp$type, "text/plain") expect_equal(curl::parse_headers_list(resp$headers)$location, "/get") expect_equal(rawToChar(resp$content), "302 Found. Redirecting to /get") # can specify status handle <- curl::new_handle() curl::handle_setopt(handle, followlocation = FALSE) url <- httpbin$url( "/redirect-to", query = list(url = "/status/200", status_code = 301) ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 301L) expect_equal(resp$type, "text/plain") expect_equal(curl::parse_headers_list(resp$headers)$location, "/status/200") expect_equal( rawToChar(resp$content), "301 Moved Permanently. Redirecting to /status/200" ) }) # Anything ============================================================= webfakes/tests/testthat/test-git-app.R0000644000176200001440000000061714740243712017514 0ustar liggesuserstest_that("git_app", { skip_on_cran() dir.create(tmp <- tempfile()) on.exit(unlink(tmp, recursive = TRUE), add = TRUE) untar(testthat::test_path("fixtures/git-repo.tar.gz"), exdir = tmp) app <- git_app(file.path(tmp, "repo")) git <- webfakes::local_app_process(app) expect_snapshot( system( paste("git ls-remote", git$url("/pak-test.git")), intern = TRUE ) ) }) webfakes/tests/testthat/test-http-methods.R0000644000176200001440000000337515026556433020604 0ustar liggesuserstest_that("get", { url <- httpbin$url("/get") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200L) data <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = FALSE) expect_equal(data$path, "/get") }) test_that("post", { url <- httpbin$url("/post") data <- charToRaw(jsonlite::toJSON(list(foo = "bar", foobar = 1:3))) handle <- curl::new_handle() curl::handle_setheaders(handle, "Content-Type" = "application/json") curl::handle_setopt( handle, customrequest = "POST", postfieldsize = length(data), postfields = data ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) data <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = TRUE) expect_equal( data$json, list(foo = "bar", foobar = 1:3) ) expect_equal(data$path, "/post") }) test_methods <- c( "connect", "delete", "head", "mkcol", "options", "patch", "propfind", "put", "report" ) app <- new_app() handler <- function(req, res) res$send_json(list(method = req$method)) for (method in test_methods) { app[[method]](paste0("/", method), handler) } web2 <- local_app_process(app, port = NA) test_that("the rest", { for (method in test_methods) { url <- web2$url(paste0("/", method)) handle <- curl::new_handle() curl::handle_setheaders(handle, "content-type" = "application/json") curl::handle_setopt(handle, customrequest = toupper(method)) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status, 200) if (method == "head") { expect_equal(length(resp$content), 0) } else { echo <- jsonlite::fromJSON(rawToChar(resp$content), simplifyVector = TRUE) expect_equal(echo$method, method) } } }) webfakes/tests/testthat/test-tmpl-glue.R0000644000176200001440000000075215026556433020066 0ustar liggesusersapp <- new_app() app$engine("html", tmpl_glue()) app$set_config("views", test_path("fixtures", "views")) app$get("/hello/:user", function(req, res) { locals <- c(as.list(req$params), greeting = "hello") html <- res$render("test-view", locals = locals) res$set_type("text/html")$send(html) }) web <- local_app_process(app) test_that("glue templating", { url <- web$url("/hello/gabor") resp <- curl::curl_fetch_memory(url) expect_match(rawToChar(resp$content), "hello gabor") }) webfakes/tests/testthat/helper.R0000644000176200001440000000512215026556433016456 0ustar liggesuserstest_response_app <- function() { app <- new_app() `%||%` <- function(l, r) if (is.null(l)) r else l app$locals$applocal <- "foo" app$engine("txt", tmpl_glue()) app$get("/local", function(req, res) { res$locals$reslocal <- "bar" "next" }) app$get("/local", function(req, res) { res$send(paste(res$locals$applocal, res$locals$reslocal)) }) app$get("/badengine", function(req, res) { txt <- res$render("foobar") res$send(txt) }) app$get("/badjson", function(req, res) { res$send_json(1:3, text = "foo") }) app$get("/file", function(req, res) { res$send_file( root = system.file(package = "webfakes"), file.path("examples", "static", "public", "foo", "bar.json") ) }) app$get("/type", function(req, res) { res$set_type("json") res$send("{ \"foo\": 1 }") }) app$get("/write", function(req, res) { res$write("hello ")$write("world!") }) app$get("/write-header", function(req, res) { res$set_header("foo", "bar")$write("hello ")$write("world!") }) app$get("/write-wait", function(req, res) { res$locals$turn <- (res$locals$turn %||% 0) + 1L if (res$locals$turn == 1) { res$set_header("content-length", nchar("hello world!"))$write( "hell" )$delay(0.01) } else if (res$locals$turn == 2) { res$write("o world")$delay(0.01) } else { res$send("!") } }) app$get("/send-chunk", function(req, res) { res$locals$turn <- (res$locals$turn %||% 0) + 1L if (res$locals$turn == 1) { res$set_header("Content-Type", "text/plain")$send_chunk( "first chunk\n" )$delay(0.01) } else if (res$locals$turn == 2) { res$send_chunk("second chunk\n")$delay(0.01) } else { res$send_chunk("third and final chunk\n") } }) app$get("/add-header", function(req, res) { res$add_header("foo", "bar") res$add_header("foo", "bar2") res$add_header("foobar", "baz") res$send("ready") }) app } httpbin <- local_app_process(httpbin_app(), opts = server_opts(num_threads = 6)) httpbin$local_env(c(FOO = "{url}xxx")) r_variant <- function() { if (getRversion() < "4.2.0") { "old-r" } else { "new-r" } } callr_curl <- function(url, options = list()) { callr::r( function(url, options) { h <- curl::new_handle() curl::handle_setopt(h, .list = options) curl::curl_fetch_memory(url, handle = h) }, list(url = url, options = options), env = c( callr::rcmd_safe_env(), CURL_SSL_BACKEND = "openssl", CURL_CA_BUNDLE = if ("cainfo" %in% names(options)) options$cainfo ) ) } webfakes/tests/testthat/test-mw-etag.R0000644000176200001440000000237015026556433017517 0ustar liggesusersapp <- new_app()$use(mw_etag())$get("/txt", function(req, res) { res$set_type("text/plain")$send("textual") })$get("/txt-empty", function(req, res) { res$set_type("text/plain")$send("") })$get("/raw", function(req, res) { res$set_type("applicartion/octet-stream")$send(charToRaw("textual")) })$get("/raw-empty", function(req, res) { res$set_type("applicartion/octet-stream")$send(raw(0)) }) web <- local_app_process(app) test_that("text/plain response", { url <- web$url("/txt") resp <- curl::curl_fetch_memory(url) headers <- curl::parse_headers_list(resp$headers) expect_true("etag" %in% names(headers)) expect_match(headers$etag, "\"[-a-zA-Z0-9]+\"") }) test_that("raw response", { txt <- curl::curl_fetch_memory(web$url("/txt")) raw <- curl::curl_fetch_memory(web$url("/raw")) htxt <- curl::parse_headers_list(txt$headers) hraw <- curl::parse_headers_list(raw$headers) expect_equal(htxt$etag, hraw$etag) }) test_that("etag for empty response", { txt <- curl::curl_fetch_memory(web$url("/txt-empty")) raw <- curl::curl_fetch_memory(web$url("/raw-empty")) htxt <- curl::parse_headers_list(txt$headers) hraw <- curl::parse_headers_list(raw$headers) expect_equal(htxt$etag, "\"00000000\"") expect_equal(htxt$etag, hraw$etag) }) webfakes/tests/testthat/test-mw-log.R0000644000176200001440000000244315026556433017361 0ustar liggesusersapp <- new_app()$use(mw_log())$get("/txt", function(req, res) { res$set_type("text/plain")$send("textual") })$get("/html", function(req, res) { res$set_type("text/html")$send("hello") })$get("/raw", function(req, res) { res$set_type("applicartion/octet-stream")$send(charToRaw("raw")) }) web <- local_app_process(app, callr_opts = list(stdout = "|")) test_that("text/plain response", { url <- web$url("/txt") resp <- curl::curl_fetch_memory(url) plr <- web$.process$poll_io(1000) expect_equal(plr[["output"]], "ready") log <- web$.process$read_output_lines() expect_match(log, "GET http://127\\.0\\.0\\.1:[0-9]*/txt 200 [0-9]+ ms - 7") }) test_that("text/html response", { url <- web$url("/html") resp <- curl::curl_fetch_memory(url) plr <- web$.process$poll_io(1000) expect_equal(plr[["output"]], "ready") log <- web$.process$read_output_lines() expect_match(log, "GET http://127\\.0\\.0\\.1:[0-9]+/html 200 [0-9]+ ms - 44") }) test_that("application/octet-stream response", { url <- web$url("/raw") resp <- curl::curl_fetch_memory(url) plr <- web$.process$poll_io(1000) expect_equal(plr[["output"]], "ready") log <- web$.process$read_output_lines() expect_match(log, "GET http://127\\.0\\.0\\.1:[0-9]+/raw 200 [0-9]+ ms - 3") }) webfakes/tests/testthat/test-path-matching.R0000644000176200001440000000564215026556433020707 0ustar liggesuserstest_that("middleware", { expect_true(path_match("foobar", "foobar2", list(method = "use"))) }) test_that("string", { good <- list( list("/foo", "/foo"), list("/", "/"), list("/***", "/***") ) for (x in good) { expect_true(path_match("get", x[[1]], list(method = "get", path = x[[2]]))) } bad <- list( list("/foo", "/bar"), list("/foo", "foo") ) for (x in bad) { expect_false(path_match("get", x[[1]], list(method = "get", path = x[[2]]))) } }) test_that("character vector or list", { good <- list( list("/foo", c("/foo2", "/foo")), list("/", list("notthis", "/")) ) for (x in good) { expect_true(path_match("get", x[[1]], list(method = "get", path = x[[2]]))) } bad <- list( list("/foo", list()) ) for (x in bad) { expect_false(path_match("get", x[[1]], list(method = "get", path = x[[2]]))) } }) named_list <- function() structure(list(), names = character()) test_that("regexp", { good <- list( list("/foo", new_regexp("^/fo+$"), list(params = named_list())), list( "/", list(new_regexp("/foobar"), new_regexp("^/$")), list(params = named_list()) ) ) for (x in good) { expect_equal( path_match("get", x[[1]], list(method = "get", path = x[[2]])), x[[3]] ) } bad <- list( list("/foo", list("/foobar")) ) for (x in bad) { expect_false(path_match("get", x[[1]], list(method = "get", path = x[[2]]))) } }) test_that("list of things", { good <- list( list( "/foo", list("/foo2", new_regexp("/foo")), list(params = named_list()) ), list("/", list(new_regexp("notthis"), "/"), TRUE) ) for (x in good) { expect_equal( path_match("get", x[[1]], list(method = "get", path = x[[2]])), x[[3]] ) } bad <- list( list("/foo", list()) ) for (x in bad) { expect_false(path_match("get", x[[1]], list(method = "get", path = x[[2]]))) } }) test_that("regexp with capture groups", { good <- list( list( "/foo/bar", new_regexp("^/foo/([a-z]+)/?$"), list(params = structure(list("bar"), names = "")) ), list( "/foo/bar", new_regexp("^/(?f.*)/(?[a-z]+)/?$"), list(params = structure(list("foo", "bar"), names = c("x", "y"))) ) ) for (x in good) { expect_equal( path_match("get", x[[1]], list(method = "get", path = x[[2]])), x[[3]] ) } bad <- list( list("/foo/bar", new_regexp("/foox/([a-z]+)/?$")) ) for (x in bad) { expect_false(path_match("get", x[[1]], list(method = "get", path = x[[2]]))) } }) test_that("tokens", { good <- list( list( "/foo", "/:x", list(params = list(x = "foo")) ), list( "/foo/bar", "/:x/:y", list(params = list(x = "foo", y = "bar")) ) ) for (x in good) { expect_equal( path_match("get", x[[1]], list(method = "get", path = x[[2]])), x[[3]] ) } }) webfakes/tests/testthat/test-mw-static.R0000644000176200001440000000472515026556433020074 0ustar liggesusersapp <- new_app() app$use(mw_etag()) app$use(mw_static(root = test_path("fixtures", "static"))) set_headers <- function(req, res) { res$set_header("foo", "bar") } app$use(mw_static( root = test_path("fixtures", "static2"), set_headers = set_headers )) app$get("/static.html", function(req, res) { res$send("this is never reached") }) app$get("/fallback", function(req, res) { res$send("this is the fallback") }) web <- local_app_process(app) test_that("static file", { url <- web$url("/static.html") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200L) # type is set from the file extension expect_equal(resp$type, "text/html") expect_equal( rawToChar(resp$content), read_char(test_path("fixtures", "static", "static.html")) ) }) test_that("static file in subdirectory", { url <- web$url("/subdir/static.json") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200L) # type is set from the file extension expect_equal(resp$type, "application/json") expect_equal( rawToChar(resp$content), read_char(test_path("fixtures", "static", "subdir", "static.json")) ) }) test_that("file not found", { url <- web$url("/notfound") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 404L) }) test_that("file not found falls back", { url <- web$url("/fallback") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200L) expect_equal(resp$type, "text/plain") expect_equal( rawToChar(resp$content), "this is the fallback" ) }) test_that("directory is 404", { url <- web$url("/subdir") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 404L) }) test_that("set_headers callback", { url <- web$url("/static.tar.gz") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200L) expect_equal(resp$type, "application/gzip") headers <- curl::parse_headers_list(resp$headers) expect_equal(headers$foo, "bar") expect_equal( resp$content, read_bin(test_path("fixtures", "static2", "static.tar.gz")) ) }) test_that("if-none-match is respected", { url <- web$url("/static.html") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200L) etag <- curl::parse_headers_list(resp$headers)$etag h <- curl::new_handle() curl::handle_setheaders(h, "If-None-Match" = etag) resp2 <- curl::curl_fetch_memory(url, handle = h) expect_equal(resp2$status_code, 304L) expect_equal(resp2$content, raw(0)) }) webfakes/tests/testthat/test-https.R0000644000176200001440000000462215026556433017322 0ustar liggesuserstest_that("HTTPS", { skip_on_cran() app <- new_app() app$get("/hello", function(req, res) { res$send("Hello there!") }) http <- local_app_process(app, port = "0s") cainfo <- system.file("cert/localhost/ca.crt", package = "webfakes") resp <- if (.Platform$OS.type == "windows") { callr_curl(http$url("/hello"), list(cainfo = cainfo)) } else { curl::curl_fetch_memory( http$url("/hello"), handle = curl::new_handle(cainfo = cainfo) ) } expect_equal(resp$status_code, 200L) expect_equal(tolower(resp$scheme), "https") }) test_that("HTTP + HTTPS", { skip_on_cran() app <- new_app() app$get("/hello", function(req, res) { res$send("Hello there!") }) http <- local_app_process(app, port = c("0", "0s")) cainfo <- system.file("cert/localhost/ca.crt", package = "webfakes") resp1 <- if (.Platform$OS.type == "windows") { callr_curl(http$url("/hello"), list(cainfo = cainfo)) } else { curl::curl_fetch_memory( http$url("/hello"), handle = curl::new_handle(cainfo = cainfo) ) } expect_equal(resp1$status_code, 200L) expect_equal(tolower(resp1$scheme), "http") resp2 <- if (.Platform$OS.type == "windows") { callr_curl(http$url("/hello", https = TRUE), list(cainfo = cainfo)) } else { curl::curl_fetch_memory( http$url("/hello", https = TRUE), handle = curl::new_handle(cainfo = cainfo) ) } expect_equal(resp2$status_code, 200L) expect_equal(tolower(resp2$scheme), "https") }) test_that("Redirect HTTP to HTTPS", { skip_on_cran() app <- new_app() app$get("/hello", function(req, res) { res$send("Hello there!") }) http <- local_app_process(app, port = c("0r", "0s")) cainfo <- system.file("cert/localhost/ca.crt", package = "webfakes") resp1 <- if (.Platform$OS.type == "windows") { callr_curl(http$url("/hello"), list(cainfo = cainfo)) } else { curl::curl_fetch_memory( http$url("/hello"), handle = curl::new_handle(cainfo = cainfo) ) } expect_equal(resp1$status_code, 200L) expect_equal(tolower(resp1$scheme), "https") resp2 <- if (.Platform$OS.type == "windows") { callr_curl(http$url("/hello", https = TRUE), list(cainfo = cainfo)) } else { curl::curl_fetch_memory( http$url("/hello", https = TRUE), handle = curl::new_handle(cainfo = cainfo) ) } expect_equal(resp2$status_code, 200L) expect_equal(tolower(resp2$scheme), "https") }) webfakes/tests/testthat/test-uuid.R0000644000176200001440000000111115026556433017114 0ustar liggesuserstest_that("uuid_random() format", { uu <- replicate(1000, uuid_random()) # format is right regex <- paste0( "^[0-9a-f]{8}-", "[0-9a-f]{4}-", "4[0-9a-f]{3}-", "[89ab][0-9a-f]{3}-", "[0-9a-f]{12}$" ) expect_true(all(grepl(regex, uu, perl = TRUE))) # all bits are used, except for the dashes and M and N pos <- setdiff(1:36, c(9, 14, 19, 24, 15, 20)) xd <- format(as.hexmode(0:15)) for (p in pos) { expect_true(all(xd %in% substr(uu, p, p))) } # all bits are used for N expect_true(all(c("8", "9", "a", "b") %in% substr(uu, 20, 20))) }) webfakes/tests/testthat/test-decode-url.R0000644000176200001440000000171415026556433020202 0ustar liggesuserstest_that("decode_url option", { app <- webfakes::new_app() app$get( webfakes::new_regexp("^/hello/(?.*)$"), function(req, res) { res$send(paste0("Return content of ", req$params$path, "!")) } ) web <- webfakes::local_app_process(app) resp <- curl::curl_fetch_memory(web$url("/hello/foo%2fbar/suffix")) expect_equal(resp$status_code, 200L) expect_equal( rawToChar(resp$content), "Return content of foo/bar/suffix!" ) app <- webfakes::new_app() app$get( webfakes::new_regexp("^/hello/(?.*)$"), function(req, res) { res$send(paste0("Return content of ", req$params$path, "!")) } ) web <- webfakes::local_app_process( app, opts = server_opts(remote = TRUE, decode_url = FALSE) ) resp <- curl::curl_fetch_memory(web$url("/hello/foo%2fbar/suffix")) expect_equal(resp$status_code, 200L) expect_equal( rawToChar(resp$content), "Return content of foo%2fbar/suffix!" ) }) webfakes/tests/testthat/test-local.R0000644000176200001440000000046515026556433017253 0ustar liggesuserstest_that("app from setup", { # This app was created in setup.R url <- httpbin2$url("/get", query = c(q1 = "one", q2 = "two")) handle <- curl::new_handle() curl::handle_setheaders(handle, "foo" = "bar") resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) }) webfakes/tests/testthat/test-mw-urlencoded.R0000644000176200001440000000141615026556433020723 0ustar liggesusersapp <- new_app() app$use(mw_urlencoded()) app$post("/form", function(req, res) { ret <- list( form = req$form ) res$send_json(ret, pretty = TRUE, auto_unbox = TRUE) }) web <- local_app_process(app) test_that("mw-urlencoded", { url <- web$url("/form") handle <- curl::new_handle() data <- charToRaw("foo=bar&foobar=100") curl::handle_setheaders( handle, "content-type" = "application/x-www-form-urlencoded" ) curl::handle_setopt( handle, customrequest = "POST", postfieldsize = length(data), postfields = data ) resp <- curl::curl_fetch_memory(url, handle = handle) echo <- jsonlite::fromJSON( rawToChar(resp$content), simplifyVector = FALSE ) expect_equal(echo, list(form = list("foo" = "bar", "foobar" = "100"))) }) webfakes/tests/testthat/_snaps/0000755000176200001440000000000015026556433016337 5ustar liggesuserswebfakes/tests/testthat/_snaps/git-app.md0000644000176200001440000000061615003631107020210 0ustar liggesusers# git_app Code system(paste("git ls-remote", git$url("/pak-test.git")), intern = TRUE) Output [1] "3f3b0b4ee8a0ff4563073924e5fe069da67a6d8b\tHEAD" [2] "3f3b0b4ee8a0ff4563073924e5fe069da67a6d8b\trefs/heads/main" [3] "cefdc0eebcd7f757efb9a80652fd8aaf1a87508e\trefs/heads/subdir" [4] "cefdc0eebcd7f757efb9a80652fd8aaf1a87508e\trefs/tags/v1" webfakes/tests/testthat/_snaps/app-process.md0000644000176200001440000000105615003631106021101 0ustar liggesusers# error if cannot start Code new_app_process(app, process_timeout = 100, start = TRUE) Condition Error in `self$start()`: ! webfakes app subprocess did not start :( --- Code new_app_process(app, start = TRUE) Condition Error: ! failed to start webfakes app process: in callr subprocess. Caused by error: ! oops --- Code new_app_process(app, start = TRUE) Condition Error in `self$start()`: ! Unexpected message from webfakes app subprocess. Report a bug please. webfakes/tests/testthat/_snaps/old-r/0000755000176200001440000000000014740243712017347 5ustar liggesuserswebfakes/tests/testthat/_snaps/old-r/httpbin.md0000644000176200001440000000117614740243712021346 0ustar liggesusers# /cookies/set/:name/:value Code curl::handle_cookies(handle) Output domain flag path secure expiration name value 1 127.0.0.1 FALSE / FALSE foo bar # /cookies/set Code curl::handle_cookies(handle) Output domain flag path secure expiration name value 1 127.0.0.1 FALSE / FALSE foo bar 2 127.0.0.1 FALSE / FALSE bar baz # /cookies/delete Code curl::handle_cookies(handle) Output domain flag path secure expiration name value 1 127.0.0.1 FALSE / FALSE bar baz webfakes/tests/testthat/_snaps/print.md0000644000176200001440000000135615003627403020011 0ustar liggesusers# webfakes_app_process Code proc Output state: not running auto_start: TRUE process id: none http url: NA fields and methods: get_app() # get the app object get_port() # query (first) port of the app get_ports() # query all ports of the app get_state() # query web server process state local_env(envvars) # set temporary environment variables start() # start the app url(path, query) # query url for an api path stop() # stop web server process # see ?webfakes_app_process for details webfakes/tests/testthat/_snaps/request.md0000644000176200001440000000062015003627403020336 0ustar liggesusers# parse_query Code parse_query("foo") Output $foo [1] "" Code parse_query("?foo") Output $foo [1] "" Code parse_query("?foo&bar") Output $foo [1] "" $bar [1] "" Code parse_query("?foo&bar=baz") Output $foo [1] "" $bar [1] "baz" webfakes/tests/testthat/_snaps/new-r/0000755000176200001440000000000014740243712017362 5ustar liggesuserswebfakes/tests/testthat/_snaps/new-r/httpbin.md0000644000176200001440000000117615003627372021362 0ustar liggesusers# /cookies/set/:name/:value Code curl::handle_cookies(handle) Output domain flag path secure expiration name value 1 127.0.0.1 FALSE / FALSE Inf foo bar # /cookies/set Code curl::handle_cookies(handle) Output domain flag path secure expiration name value 1 127.0.0.1 FALSE / FALSE Inf foo bar 2 127.0.0.1 FALSE / FALSE Inf bar baz # /cookies/delete Code curl::handle_cookies(handle) Output domain flag path secure expiration name value 1 127.0.0.1 FALSE / FALSE Inf bar baz webfakes/tests/testthat/_snaps/app.md0000644000176200001440000000037715026556433017450 0ustar liggesusers# invalid handler Code app$use("foobar") Condition Error in `parse_handlers()`: ! Invalid webfakes handler Code app$get("/foo", 1:100) Condition Error in `parse_handlers()`: ! Invalid webfakes handler webfakes/tests/testthat/_snaps/mw-range-parser.md0000644000176200001440000000145315003627371021666 0ustar liggesusers# parse_range Code parse_range("foobar=1-100") Output NULL Code parse_range("bytes=0-100, 50-150") Output NULL Code parse_range("bytes=200-100") Output NULL Code parse_range("bytes=x-100") Output NULL Code parse_range("bytes=1-100") Output [,1] [,2] [1,] 1 100 Code parse_range("bytes=1-") Output [,1] [,2] [1,] 1 Inf Code parse_range("bytes=-100") Output [,1] [,2] [1,] 0 -100 Code parse_range("bytes=0-100, 200-") Output [,1] [,2] [1,] 0 100 [2,] 200 Inf Code parse_range("bytes=200-300, 0-100") Output [,1] [,2] [1,] 0 100 [2,] 200 300 webfakes/tests/testthat/test-request.R0000644000176200001440000000024215026556433017642 0ustar liggesuserstest_that("parse_query", { expect_snapshot({ parse_query("foo") parse_query("?foo") parse_query("?foo&bar") parse_query("?foo&bar=baz") }) }) webfakes/tests/testthat/test-response.R0000644000176200001440000000464315026556433020021 0ustar liggesusersweb <- local_app_process(test_response_app()) test_that("response locals", { url <- web$url("/local") resp <- curl::curl_fetch_memory(url) expect_equal(rawToChar(resp$content), "foo bar") }) # on_response is tested via mw_log() test_that("render", { # if the template or engine does not exist url <- web$url("/badengine") resp <- curl::curl_fetch_memory(url) expect_match( rawToChar(resp$content), "Cannot find template engine for view" ) }) test_that("send_json", { url <- web$url("/badjson") resp <- curl::curl_fetch_memory(url) expect_match( rawToChar(resp$content), "Specify only one of" ) }) test_that("send_file", { url <- web$url("/file") resp <- curl::curl_fetch_memory(url) path <- system.file( package = "webfakes", "examples", "static", "public", "foo", "bar.json" ) expect_equal(resp$content, read_bin(path)) }) test_that("set_type", { url <- web$url("/type") resp <- curl::curl_fetch_memory(url) headers <- curl::parse_headers_list(resp$headers) expect_equal(headers$`content-type`, "application/json") }) test_that("write", { url <- web$url("/write") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200) expect_equal(rawToChar(resp$content), "hello world!") # header can be set url <- web$url("/write-header") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200) expect_equal(rawToChar(resp$content), "hello world!") headers <- curl::parse_headers_list(resp$headers) expect_equal(headers$`foo`, "bar") }) test_that("write-wait", { url <- web$url("/write-wait") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200) expect_equal(rawToChar(resp$content), "hello world!") }) test_that("send_chunk", { url <- web$url("/send-chunk") resp <- curl::curl_fetch_memory(url) expect_equal(resp$status_code, 200) expect_equal( rawToChar(resp$content), "first chunk\nsecond chunk\nthird and final chunk\n" ) headers <- curl::parse_headers_list(resp$headers) expect_equal(headers[["content-type"]], "text/plain") expect_equal(headers[["transfer-encoding"]], "chunked") }) test_that("add_header", { url <- web$url("/add-header") resp <- curl::curl_fetch_memory(url) headers <- curl::parse_headers_list(resp$headers) expect_equal( headers[names(headers) == "foo"], list(foo = "bar", foo = "bar2") ) expect_equal(headers[["foobar"]], "baz") }) webfakes/tests/testthat/test-base64.R0000644000176200001440000000076215026556433017245 0ustar liggesuserstest_that("base64_decode", { decode_tests <- c( 'YWE=' = 'aa', ' YWE=' = 'aa', 'Y WE=' = 'aa', 'YWE= ' = 'aa', "Y\nW\r\nE=" = 'aa', 'YWE=====' = 'aa', # extra padding 'YWE' = 'aa', # missing padding 'YWFh====' = 'aaa', 'YQ' = 'a', 'Y' = '', 'x==' = '' ) for (i in seq_along(decode_tests)) { encoded <- names(decode_tests)[[i]] expected <- decode_tests[[i]] decoded <- base64_decode(encoded) expect_equal(decoded, expected) } }) webfakes/tests/testthat/test-delay.R0000644000176200001440000000204215026556433017250 0ustar liggesusersapp <- new_app() app$get("/delay", function(req, res) { if (is.null(res$locals$seen)) { res$locals$seen <- TRUE res$delay(.5) } else { res$send_json( list(message = "Sorry, running late..."), auto_unbox = TRUE ) } }) app$get("/nodelay", function(req, res) { res$send_json( list(message = "I am fast, aren't I?"), auto_unbox = TRUE ) }) web <- local_app_process(app, opts = server_opts(num_threads = 3)) test_that("delay", { p <- curl::new_pool(multiplex = FALSE) h1 <- curl::new_handle(url = web$url("/delay")) h2 <- curl::new_handle(url = web$url("/nodelay")) resp1 <- resp2 <- NULL curl::multi_add(h1, done = function(x) resp1 <<- x, fail = stop, pool = p) curl::multi_add(h2, done = function(x) resp2 <<- x, fail = stop, pool = p) curl::multi_run(timeout = 2, pool = p) curl::multi_cancel(h1) curl::multi_cancel(h2) expect_false(is.null(resp1)) expect_false(is.null(resp2)) expect_true(resp1$times[["total"]] > 0.5) expect_true(resp2$times[["total"]] < resp1$times[["total"]]) }) webfakes/tests/testthat/test-app.R0000644000176200001440000000021515026556433016732 0ustar liggesuserstest_that("invalid handler", { app <- new_app() expect_snapshot(error = TRUE, { app$use("foobar") app$get("/foo", 1:100) }) }) webfakes/tests/testthat/test-mw-raw.R0000644000176200001440000000214015026556433017363 0ustar liggesusersapp <- new_app() app$use(mw_raw()) app$post("/raw", function(req, res) { res$set_type("application/octet-stream")$send(req$raw) }) web <- local_app_process(app) test_that("raw body parser", { url <- web$url("/raw") data <- charToRaw(jsonlite::toJSON(list(foo = "bar", foobar = 1:3))) handle <- curl::new_handle() curl::handle_setheaders(handle, "content-type" = "application/octet-stream") curl::handle_setopt( handle, customrequest = "POST", postfieldsize = length(data), postfields = data ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 200L) expect_equal(data, resp$content) }) test_that("non-matching content-type", { url <- web$url("/raw") data <- charToRaw(jsonlite::toJSON(list(foo = "bar", foobar = 1:3))) handle <- curl::new_handle() curl::handle_setheaders(handle, "content-type" = "application/json") curl::handle_setopt( handle, customrequest = "POST", postfieldsize = length(data), postfields = data ) resp <- curl::curl_fetch_memory(url, handle = handle) expect_equal(resp$status_code, 404L) }) webfakes/tests/testthat/setup.R0000644000176200001440000000013415026556433016335 0ustar liggesusershttpbin2 <- local_app_process( httpbin_app(), .local_envir = testthat::teardown_env() ) webfakes/tests/testthat.R0000644000176200001440000000012314740243712015166 0ustar liggesuserslibrary(testthat) library(webfakes) test_check("webfakes", reporter = "progress") webfakes/MD50000644000176200001440000007064415026575142012373 0ustar liggesusers3b4f45ffc4f1ab495bd519eab90aaec5 *DESCRIPTION 243b8973dd82789d581d71c17342d095 *LICENSE de4abb60cda1343e55e18ed08d50161e *NAMESPACE 96f13b1d7d3774fac0087028e031b385 *NEWS.md b0406e7bbcf6486efbcf625dda8cff7d *R/app-process.R 2298661a8407cad8e7f289c7a9ae116d *R/app.R d4d96f360bda96823dfc0b0910b3607c *R/base64.R 3bcb7be75dc7f4fab1993b79ceedf67f *R/cleancall.R e168305c9de7501a42b34cb5758509fe *R/compat-defer.R 9d1449e18f3df57a6cc249bc104e02a6 *R/digest.R e70cad741d2fdfd06890197bc9086b81 *R/docs.R b7eace8a5dbdf06df5980ecc2549311d *R/git-app.R c0500eb3b83330aa91aabb1419bae9b4 *R/httpbin.R d329f909e36a7680cc2ab224ff93ae5d *R/local-app-process.R ed1f9f1de8f3217336e4698a46c78bc7 *R/mime.R 1248fc8f65e3ca8a18844d2ffa4d1a39 *R/mw-authorization.R ce722450099a981bfbd8ff0a36a6c50c *R/mw-cgi.R 9488d780dbc0e2e35216b8b1f17f1d57 *R/mw-cookie-parser.R ad792e25984581d10660d1782c13113e *R/mw-etag.R 0489134a714c8be47d4616ba799027f1 *R/mw-json.R d03c37847f6fa495aba8ae4bd171a893 *R/mw-log.R 3f40ad979b2ea236622bd10fc2682ba9 *R/mw-multipart.R 039090f440dafefdde4f166d379cf23b *R/mw-range-parser.R b9db445ec7ff3d3aa5e375fd2ad010e5 *R/mw-raw.R cafe28fcbfcea295d42da3d265dc7c37 *R/mw-static.R 40591601657b3aa85d478ba1bf583175 *R/mw-text.R 2092a41f887ab1c07efc901292cffd77 *R/mw-urlencoded.R 78db5c33af4f6c65b17ed4476c16861b *R/oauth.R a56907880d6cfc1353815bd535b5e4e0 *R/package.R 0931b64a48880da2e46b3c7e38c4a099 *R/path.R c1ff47aa20e8b745708503b955bab7b9 *R/print.R 003a5386f09b0d7c8f73d74f7855866f *R/rematch2.R 63e53ab1a5f5d3a07db9a8b316fa1b5c *R/request.R a073a97ad752a1f32099bb1851b97c74 *R/response.R 1d86ccef4d0aa48697d1dfcaeeff4ecc *R/server.R 3e9f600b7430c70d98109017bfb90afa *R/status.R 19233a1248b7bc5194071e5d6d595a34 *R/tmpl-glue.R 88a25069c7488ac2aece3eec311d9770 *R/utils.R 08a7ffe644a834a5e0b037db7b931939 *R/uuid.R df6cc46bc7fae1a55b713f3d5065b35a *R/webfakes-package.R 26e980ec2ff221569e64b2e2077be010 *README.md 2dbc57bfe4d83311ba9cb7e9e4fe042b *cleanup 1a1ca4afc707aea4998667641d8f92f7 *configure 757ef8281ef2a1ebcbcc8235aeee2d0e *configure.win f5f50d443f7fc44c764532a768e04955 *inst/cert/localhost/ca.crt 83462bda9cbcaefb9e26081d1f34f98e *inst/cert/localhost/ca.key ba1d9210d923084170ff806c5f21c5e7 *inst/cert/localhost/generate.sh 988eb6c719bdf59a2e3ad2d427f8ba66 *inst/cert/localhost/server.crt 81cbad7a4951dcc2b920e278686b0ad2 *inst/cert/localhost/server.csr f105f1766292c51c42f1ce80bf425f58 *inst/cert/localhost/server.key 5e3c3e26178f2235e2c388d1f50b87fa *inst/cert/localhost/server.pem d3943445ebf976356df3874cc85c2f43 *inst/credits/ciwetweb.md bb9faae548cd71cee0803bd99f1df5da *inst/credits/redoc.md cf6083f352e5cebbe33711691c337364 *inst/examples/hello/app.R c5a7448fdb6c04af06978c875f979b84 *inst/examples/hello/views/test.txt be6d0df1f6b5a19ace207e47dbf5cb05 *inst/examples/httpbin/app.R a3cd10015af1713b5d09017677552f51 *inst/examples/httpbin/assets/forms-post.html 548ccf782a4c899f10512a8609cda28e *inst/examples/httpbin/assets/httpbin.html d439215e6d34774c286caeaa5dddb2d0 *inst/examples/httpbin/data/deny.txt 49b221c274d8d1545e577538278e25f9 *inst/examples/httpbin/data/example.html 302c1d78011b9926fcf3e6a5e556e7a1 *inst/examples/httpbin/data/example.json a88c5078ffed61c2fff326de48cdb740 *inst/examples/httpbin/data/example.xml 46fd03688e49c6b6b0a2b7d3553c1e42 *inst/examples/httpbin/data/robots.txt c159c6400f3b55c71740339832e11795 *inst/examples/httpbin/data/utf8.html e1f9ee4cf1f2be1c1d3d824ba25133b4 *inst/examples/httpbin/doc-template.hbs d67bd2c5bff4abba2bd11fb0ab07d404 *inst/examples/httpbin/images/Rlogo.jpeg 7381224c65138a2acdf3a8346f8275c4 *inst/examples/httpbin/images/Rlogo.png 2b5719958c377e203c20463e340671f3 *inst/examples/httpbin/images/Rlogo.svg 1a5760d159f118ba8d495ce2c7e082d7 *inst/examples/httpbin/images/Rlogo.webp 949c4429bb552dea6c3534e9e6e5132f *inst/examples/httpbin/openapi.yaml 7381224c65138a2acdf3a8346f8275c4 *inst/examples/send-file/Rlogo.png 0bab4a75927477300f58de9a049b93b9 *inst/examples/send-file/app.R 20f6490d34d33f9c6a4cbc96e7d41246 *inst/examples/static/app.R b264e4c43787cb81e7d4c5eb4b006427 *inst/examples/static/public/bar/foo.txt 5186b0805ea39b8efd70a1d3c85f7a89 *inst/examples/static/public/foo/bar.html 7c2c080a60bdbcf4ebe6de2a4c27f8ac *inst/examples/static/public/foo/bar.json a163d4f17cf2ccba7498236176e9e87e *inst/views/authorize.html 2f092ec4e63649645669691390894dd9 *man/git_app.Rd 5cb19c23320fd60635e35f5bede220c7 *man/glossary.Rd 153bc6e6aa05b683b0c0fa0bda2e15fc *man/how-to.Rd 652a6e30f94da913587b158101070471 *man/http_time_stamp.Rd e02aba10f335675508df8bb61428c8bb *man/httpbin_app.Rd 4f7640fd9eab26b582bc53dcd8b86596 *man/introduction.Rd 2f72d34848cd14a4608038f081957a8d *man/local_app_process.Rd a0f6148cbb31e2f899d367ed5c5f0acc *man/mw_cgi.Rd 3aa272e5a02594021c1364746741b6d4 *man/mw_cookie_parser.Rd 537037de324e27bcd83b8d4d8f5c38a7 *man/mw_etag.Rd 9391c960878a639563f83fb7fb3a8b05 *man/mw_json.Rd 603cba68c57fb0982111b0989b40e626 *man/mw_log.Rd b4d013720e940067ce0473ef60cfda89 *man/mw_multipart.Rd 9951893b045f59572b0d03f33067fc24 *man/mw_range_parser.Rd 4997517a159351ce37a12b71324a1adb *man/mw_raw.Rd ff63aa18cb775898ffcc419e96f7c80a *man/mw_static.Rd ea7f0595779b547e3b68cd14ea5e9813 *man/mw_text.Rd f34fcdb907ddd8792c41460b366acfd8 *man/mw_urlencoded.Rd d03b59917475c7275422c3cebca7d46e *man/new_app.Rd 0275915fc76e3e6ce2bf60e4edf40545 *man/new_app_process.Rd a00ceeb3738efcbcf68322a7c5e3574a *man/new_regexp.Rd 4c1a98cec2cdc8aada531b85a4cced94 *man/oauth2_httr_login.Rd 39313747ae2fd30159e298a56ca9f36d *man/oauth2_login.Rd 2e27ada1a5090d77cc05ed77f78ad232 *man/oauth2_resource_app.Rd e82f9b5f0a5fb5730d5e8ae36c7b563d *man/oauth2_third_party_app.Rd 9a855c74792013bd993bea790d7e8682 *man/rmd-fragments/oauth2.Rmd 7192a84667fec902e37d958b6cbb1f7e *man/server_opts.Rd 3acb0a67e7b026f6517ff82c6020d515 *man/tmpl_glue.Rd b5310016f9da78308973815d3979b51e *man/webfakes-package.Rd 517c71d331371eb9c1a5ed4ecc52fffd *man/webfakes_request.Rd 2214a9b6c75ec38ed5afc67cb85d0ece *man/webfakes_response.Rd 6d4b1259cbffc81bf77c847504e86e22 *src/Makevars.in a859cc88011bbc572c99ae061f3000b5 *src/civetweb.c a96adb23ce8a048124f001a96e49354f *src/civetweb.h 2db4898abcab6bce2d202f0fdc371fee *src/cleancall.c 3cedbcdfb4d38768d2765d57a891eee1 *src/cleancall.h b935423483e3a08ab1dcc620c752d195 *src/crc32.c 9f1ee6d9b40e7a78246c6b6ffcfdfbc2 *src/errors.c 1ac3a7b49282794e006a1715f6ccf8af *src/errors.h 09c2fab815099e1a898120f6aa44c316 *src/handle_form.h de6cdab982e6dacaff9ea12e0bad607b *src/http2.h 8dab28a3e111536d33d68a56ca33869e *src/match.h 58a4e8641939d48dc23ed0bc55fcc590 *src/mbedtls/include/CMakeLists.txt 8617dc7b625a8ea943c6f392bad96dd7 *src/mbedtls/include/mbedtls/aes.h 5433c9d7be48397b569b4f6e96320c61 *src/mbedtls/include/mbedtls/aria.h 0e1565a05081821ccc9bb77e9c666235 *src/mbedtls/include/mbedtls/asn1.h 10fc9825a119dcb5a45753918595f374 *src/mbedtls/include/mbedtls/asn1write.h 419ab22b364b2c7cb087f6a0e7ff5a35 *src/mbedtls/include/mbedtls/base64.h 189127f372111b1f90d09d1360ed04ad *src/mbedtls/include/mbedtls/bignum.h 35d79710bff44331d7d1cca8d2ea2458 *src/mbedtls/include/mbedtls/block_cipher.h e907336f67d667eaed085c309979e0a3 *src/mbedtls/include/mbedtls/build_info.h 2d32b08a9d0c7e21a2c5d6b0ba850f49 *src/mbedtls/include/mbedtls/camellia.h ee86e03d5bf910c320e99dcdde7ed63b *src/mbedtls/include/mbedtls/ccm.h ea8c79b03fc33921d125ca0ce9840b0b *src/mbedtls/include/mbedtls/chacha20.h 3b2ff5108a921f23a1107e09ed43dab0 *src/mbedtls/include/mbedtls/chachapoly.h c133259da725b81dfce696917b530767 *src/mbedtls/include/mbedtls/check_config.h 3e8871f22d09b4fa85bf9a780405d7f4 *src/mbedtls/include/mbedtls/cipher.h 379c2d3cbe89d4a5a39b034bf2994c25 *src/mbedtls/include/mbedtls/cmac.h d7e4e0646043d451829fcfe3474e7fee *src/mbedtls/include/mbedtls/compat-2.x.h 96d065c813c332feb4ae30e4f1fbd140 *src/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h fda298303a7f4ae6262149e2eab14f9a *src/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h 55109ef14d61bda74c41f542021ed429 *src/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h f5f0ce3f11ab592d4553bd98d364af41 *src/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h d55e8abd1e9f5dee0756fdc893361746 *src/mbedtls/include/mbedtls/config_adjust_ssl.h 97c6c6b993ac01fbf899d4d9cbec7148 *src/mbedtls/include/mbedtls/config_adjust_x509.h db9a3262fcd2c94920c53d652cd14d55 *src/mbedtls/include/mbedtls/config_psa.h 625e6bce6539127420c06cbcba88ea76 *src/mbedtls/include/mbedtls/constant_time.h b830cb7f7585ae0bc1eb7d209314685b *src/mbedtls/include/mbedtls/ctr_drbg.h 489d10c0b5c5cfe6281447a450814e45 *src/mbedtls/include/mbedtls/debug.h f8191aa4b37c6562acf0e8d286594857 *src/mbedtls/include/mbedtls/des.h 945e3e437cd04f929455e0c28cecdffa *src/mbedtls/include/mbedtls/dhm.h 66a0ab70e5cc749a2c265044a1cedc4c *src/mbedtls/include/mbedtls/ecdh.h ccc1cb449b175bdcde0c415962b59765 *src/mbedtls/include/mbedtls/ecdsa.h f1b62dfab177f8344b9dd467ba66f88c *src/mbedtls/include/mbedtls/ecjpake.h 14d8429c208f49f011d985258a3a15a0 *src/mbedtls/include/mbedtls/ecp.h 1f823c5934c27dc5a716a35afece1524 *src/mbedtls/include/mbedtls/entropy.h a07d5294c24c19f983b228bb1a99ea39 *src/mbedtls/include/mbedtls/error.h b7eb3bebe595f83436e9beef71ab8836 *src/mbedtls/include/mbedtls/gcm.h 1c665933f0f04ca615d7a4230a304565 *src/mbedtls/include/mbedtls/hkdf.h 4c4f2ec8b2b92ff547897c5b80bc5f35 *src/mbedtls/include/mbedtls/hmac_drbg.h 58fa9eb54ea6177593d948efaa9354b8 *src/mbedtls/include/mbedtls/lms.h 42a508fedf1cd5a59ae90b125b8511e5 *src/mbedtls/include/mbedtls/mbedtls_config.h a17830bde6e81de262475533c8f0f1f1 *src/mbedtls/include/mbedtls/md.h 0557b42d6fa17f81d6134a00367e3f32 *src/mbedtls/include/mbedtls/md5.h d94aa14a9cd8ceff61e37c39cafe64d1 *src/mbedtls/include/mbedtls/memory_buffer_alloc.h 42f56fc4fab7d74bda774617fb6cb21b *src/mbedtls/include/mbedtls/net_sockets.h 1a19ebba5fd64045805d44b6c295cdd3 *src/mbedtls/include/mbedtls/nist_kw.h 2c69529b5f129c3c408eb8df35d94f7a *src/mbedtls/include/mbedtls/oid.h 789ff2a1e42ddde8964d63cef5b09d31 *src/mbedtls/include/mbedtls/pem.h f880c3b6a596ab4034ee2ca90e762932 *src/mbedtls/include/mbedtls/pk.h 3eb676756cbf8bbd2a586b85bc9a640c *src/mbedtls/include/mbedtls/pkcs12.h 3806323cee53d048e9bb29eb04116d7f *src/mbedtls/include/mbedtls/pkcs5.h 9ed288185111b15c48ad1c00539d4afa *src/mbedtls/include/mbedtls/pkcs7.h b7901761628c61dc50b6da7c75572ccb *src/mbedtls/include/mbedtls/platform.h adcbaa9c2a681987100f09cd6618661e *src/mbedtls/include/mbedtls/platform_time.h 522965d123d0375a487af672a15a5542 *src/mbedtls/include/mbedtls/platform_util.h e367188381498db9e021818d1a6349b4 *src/mbedtls/include/mbedtls/poly1305.h b9aaa3ed4a926da96cae29cb1764377f *src/mbedtls/include/mbedtls/private_access.h 84ab5b00f3aab299ee0b5ed9448ccd83 *src/mbedtls/include/mbedtls/psa_util.h 701730d284a1023fdbcd0f71d79288d1 *src/mbedtls/include/mbedtls/ripemd160.h 938fe03f30bc3b624e25a5b0e10771f2 *src/mbedtls/include/mbedtls/rsa.h 066bd2819b35e2f40b61b130ada577fd *src/mbedtls/include/mbedtls/sha1.h 4e3bdedcf4abf4b0c8fd89b1c068e001 *src/mbedtls/include/mbedtls/sha256.h ee2a4994abbe59a7790bfeda5a24a24f *src/mbedtls/include/mbedtls/sha3.h dced1d3d168d5b74c955c79da4357327 *src/mbedtls/include/mbedtls/sha512.h 1629911a9c8182eaf790f5883a268ea7 *src/mbedtls/include/mbedtls/ssl.h 3c1c5975f6900361eaa494e1b5ba99ad *src/mbedtls/include/mbedtls/ssl_cache.h 87f825feec357a92f8fe2401dfa31228 *src/mbedtls/include/mbedtls/ssl_ciphersuites.h c655f469448ce66054b343bea698b0f1 *src/mbedtls/include/mbedtls/ssl_cookie.h 5f519e56885fcb3842b243ba3df989cd *src/mbedtls/include/mbedtls/ssl_ticket.h c31f5921e4d528aee7bbc4e1080a052a *src/mbedtls/include/mbedtls/threading.h 12c91e3df28823885a69a3db69e68c21 *src/mbedtls/include/mbedtls/timing.h 07530945ae8e7516098a5297475d324b *src/mbedtls/include/mbedtls/version.h 9627c3d35e33913d87d37e6b21672d5b *src/mbedtls/include/mbedtls/x509.h e777d73bcb20f913372faf6b887458a9 *src/mbedtls/include/mbedtls/x509_crl.h 9f60e6bab368ad96513e7b4d8f99b2c1 *src/mbedtls/include/mbedtls/x509_crt.h af2db81a9aeafbe431ce83e478d52c4c *src/mbedtls/include/mbedtls/x509_csr.h aa41141932ee675112265cbdc966ab22 *src/mbedtls/include/psa/build_info.h d0f6ce88312102dee3b5871b68894bfb *src/mbedtls/include/psa/crypto.h 64102db00bf218f87c3c23922fe0695c *src/mbedtls/include/psa/crypto_adjust_auto_enabled.h 2f41d7100d8b549b5b80e2f1be498f0d *src/mbedtls/include/psa/crypto_adjust_config_dependencies.h dcdf99ac83263ab20d38837a00e9abd2 *src/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h 956cb2b4cc4de1ad0182fa6340c6970b *src/mbedtls/include/psa/crypto_adjust_config_synonyms.h b778fee3d247e9ba1f4c0d3a81aa38b5 *src/mbedtls/include/psa/crypto_builtin_composites.h 8235bd97389e0af2fb380d7fda5a100d *src/mbedtls/include/psa/crypto_builtin_key_derivation.h c5de961e6aa96bb80afa4d09cfeb9035 *src/mbedtls/include/psa/crypto_builtin_primitives.h 73e963bcff326879aae1660f82f6466d *src/mbedtls/include/psa/crypto_compat.h 6349ce32db72ab6603d42b2379418bf6 *src/mbedtls/include/psa/crypto_config.h f33e6db3e230050e46d3327801188376 *src/mbedtls/include/psa/crypto_driver_common.h d5f97dc0efac3961afa2cdaab9f7537c *src/mbedtls/include/psa/crypto_driver_contexts_composites.h 165245e9bc3e0d16cd76a60c75ec956c *src/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h 7028843942f0e2b95e92d401944c47a0 *src/mbedtls/include/psa/crypto_driver_contexts_primitives.h 3af7a0c0f10cb7e12cd297e6fdf78489 *src/mbedtls/include/psa/crypto_extra.h 667c8b49b0342f33e09a132ce0eb939b *src/mbedtls/include/psa/crypto_legacy.h b322c290bb44e55dd6d2430aa20dae76 *src/mbedtls/include/psa/crypto_platform.h 14685cdb70fafbb5204e7c4c1356fb13 *src/mbedtls/include/psa/crypto_se_driver.h acb96d425b065233b5fdf35f2d23270e *src/mbedtls/include/psa/crypto_sizes.h 29bd472af26d15379210235487bc5173 *src/mbedtls/include/psa/crypto_struct.h 4413373d77e69870e1744f351cf5c7a0 *src/mbedtls/include/psa/crypto_types.h 7030603fdb3a4e83a384014b457fea3a *src/mbedtls/include/psa/crypto_values.h 4a679ad98bb1ee21e845e8e442fc049f *src/mbedtls/library/CMakeLists.txt f7afd4a2677107ddb7edcdc58f4a6e27 *src/mbedtls/library/aes.c 1296dda9c08b1a35b0f1dac196af9e94 *src/mbedtls/library/aesce.c f3de68c3debfae18925fd91a85ed259c *src/mbedtls/library/aesce.h 26924c8aa674ee54c03778267c01b178 *src/mbedtls/library/aesni.c 5e5485ee98abe59ff74442975be7953b *src/mbedtls/library/aesni.h 5645ae5375aa572237e77fe2c37ea7d5 *src/mbedtls/library/alignment.h 66c2c26b21b6360d25633a605686a0af *src/mbedtls/library/aria.c a59ccb71a514050d47ef7d6896a63c52 *src/mbedtls/library/asn1parse.c b3e11c75d306ce35ccae355c70e56ffb *src/mbedtls/library/asn1write.c dc2ca6504777d21d19ab5d4ef5b6207a *src/mbedtls/library/base64.c 2b53b2316b1c76081730ef2e87d8699f *src/mbedtls/library/base64_internal.h f0ed14f83b6b0b258960b6e847a6b264 *src/mbedtls/library/bignum.c c4b8b18d222a6585571fd5ae5ebce5bb *src/mbedtls/library/bignum_core.c d4584d304070e2747cb723444079e48c *src/mbedtls/library/bignum_core.h e5244cebfc6ca91c9a84e6d96bc24694 *src/mbedtls/library/bignum_internal.h 35cc9dfa0c3f22231bf7a665cf12f6eb *src/mbedtls/library/bignum_mod.c c59b41e2c62e3445d65232dd43a7a3de *src/mbedtls/library/bignum_mod.h 40cf3aaf23fe09ba4d15015e6451e6c8 *src/mbedtls/library/bignum_mod_raw.c 7ad6c21ea4a3ceb75e560191e4ed893e *src/mbedtls/library/bignum_mod_raw.h 7fdc27be5eee668f60401534a97edd1c *src/mbedtls/library/bignum_mod_raw_invasive.h 7a07d6dcd26982bf44a423b65207e48c *src/mbedtls/library/block_cipher.c ec5cd9160166c80b8875972436773413 *src/mbedtls/library/block_cipher_internal.h 30bd64dc864e1851ae220a6f1a459726 *src/mbedtls/library/bn_mul.h 0a63ebab532da3d8d37be7a7806166c5 *src/mbedtls/library/camellia.c c0565d8316fc5483eb10bc270d514e3d *src/mbedtls/library/ccm.c d87481fbed9f51a895e0f71198213dc7 *src/mbedtls/library/chacha20.c d3caa7c8766a37b8fcf5fc6f09a8eba2 *src/mbedtls/library/chachapoly.c 21414bce9628869b0ce65fbb8c6f2ae7 *src/mbedtls/library/check_crypto_config.h 1c7a62464e9f07b921750169a6fe452d *src/mbedtls/library/cipher.c 3209f8f44a562dc96564e51aae1667f0 *src/mbedtls/library/cipher_wrap.c 277029bba1a00204e143b0f23647dff3 *src/mbedtls/library/cipher_wrap.h 9df7a86c29ce174cc43ac07719810ca9 *src/mbedtls/library/cmac.c 1974938c777c1254ccdada064544a4f2 *src/mbedtls/library/common.h 7358b1b175ace456f71eedae1034bbf9 *src/mbedtls/library/constant_time.c 6feb403167a15c14a38129e68d5666a8 *src/mbedtls/library/constant_time_impl.h dd4ae6aceaa72478fa3626c3de47849c *src/mbedtls/library/constant_time_internal.h 6bbd6e24f3c1d6dba7ce479d1b02699c *src/mbedtls/library/ctr.h ebc41b6bdecd48789b18baef49a4935d *src/mbedtls/library/ctr_drbg.c 06a13c26188d718000f90eaa5291c2c1 *src/mbedtls/library/debug.c df28fa03bbc0dd273f27ae5cc23d7c1e *src/mbedtls/library/debug_internal.h 0c524be6d5442734e4e984a31ea19a84 *src/mbedtls/library/des.c df7e63e4966868b14a4d81859b1d97d8 *src/mbedtls/library/dhm.c e69de8f6b1c986d06137871f07a7e423 *src/mbedtls/library/ecdh.c 78744c406bd4a8f0627d7a7dba56bbae *src/mbedtls/library/ecdsa.c 77f6dd7c6440196997b258499d14436c *src/mbedtls/library/ecjpake.c ec443a32d21b293e3db55167009593ab *src/mbedtls/library/ecp.c e7acaa9c9e1c81940e25817202a81363 *src/mbedtls/library/ecp_curves.c b5facccf902aa5145cc81dbed24ea0b3 *src/mbedtls/library/ecp_curves_new.c 32feb27d2a78e875f30d299486068045 *src/mbedtls/library/ecp_internal_alt.h 2addeb16ba4b0df41f5a5fe1ea1b0597 *src/mbedtls/library/ecp_invasive.h ba8ba81674ce14dbbb63d39672fa4606 *src/mbedtls/library/entropy.c a975d03c9ab1cdc46b6eb76e314dd67f *src/mbedtls/library/entropy_poll.c 63a2f01e8f40eeaa61612d90dd9ba34a *src/mbedtls/library/entropy_poll.h 569a68f290b7982a7c625e2253978085 *src/mbedtls/library/error.c 9a40557b856330baad1ca78d737cffeb *src/mbedtls/library/gcm.c 2b6b66a734f5019dca4e8cde14d6e1a6 *src/mbedtls/library/hkdf.c 673c8e4dded92e7efa60e1d2c1f0ff44 *src/mbedtls/library/hmac_drbg.c acf00acc0c6603ffcc3d44424207ede4 *src/mbedtls/library/lmots.c 5539b2a73a6482598f480e5d6de2cb1c *src/mbedtls/library/lmots.h f7daea415089bb5790be7689df3a8bc8 *src/mbedtls/library/lms.c f798acadd31bc3a7625436a47fc1aa5f *src/mbedtls/library/md.c 1a3fc6588d2efd1ce0bb0874aede7629 *src/mbedtls/library/md5.c 50b8e2613bab6db81d0e7af17a9a763a *src/mbedtls/library/md_psa.h 4e6d1cb2bd632bdd683415ce937ed887 *src/mbedtls/library/md_wrap.h 494133b757b818374fd60a8c97d21d2a *src/mbedtls/library/memory_buffer_alloc.c e1177a39acb077ffa3f239acf0aa87a0 *src/mbedtls/library/mps_common.h dbeb2c62199b14504adc5f478f22f3ff *src/mbedtls/library/mps_error.h 9cb8650af8890ae9b50d9051fceac04f *src/mbedtls/library/mps_reader.c 3110e3ab31d1ba4078710757dc76e5ed *src/mbedtls/library/mps_reader.h 31d74a08c01ff84db611d8e2bb58e0cf *src/mbedtls/library/mps_trace.c d893378f65146d7d413c16fae5b05e58 *src/mbedtls/library/mps_trace.h 51d34bc0c787718519d341e488a50433 *src/mbedtls/library/net_sockets.c a825e72db3453ab1f87fa1abdc1d5035 *src/mbedtls/library/nist_kw.c 52feec7b42dc5bbc2b0cc72a652e35b9 *src/mbedtls/library/oid.c c4cca2aea3b9c00b3ccdaf205e49a5ed *src/mbedtls/library/padlock.c 1f53b8e25ca0327c65b0c0a66fe2a171 *src/mbedtls/library/padlock.h f452e813fe12e7bee49759cc0306cee4 *src/mbedtls/library/pem.c 294737a4bd5d5afea8474a3a3552d6f6 *src/mbedtls/library/pk.c d8e0506cb6a92f5eea6ef9d0631fd06f *src/mbedtls/library/pk_ecc.c 352e9db45272c67da83095f8b93961a6 *src/mbedtls/library/pk_internal.h 462fd65506a6d7ea3d3a20eb310f6d88 *src/mbedtls/library/pk_wrap.c ad01e332f13f2506efddbd3f0c2a1646 *src/mbedtls/library/pk_wrap.h 3cdcd9cff01f205b8cdbf74c5eaad2a0 *src/mbedtls/library/pkcs12.c dba1fd218275b04cf7e494fc0806b01b *src/mbedtls/library/pkcs5.c 32dd3db581a5624b4a846f7923c663c3 *src/mbedtls/library/pkcs7.c 5b0c3def4be665e60d79296a0be96f46 *src/mbedtls/library/pkparse.c 352ae84716052db40d28ab038926d30b *src/mbedtls/library/pkwrite.c b5167e08d7dbd1394b2ea82643660e64 *src/mbedtls/library/pkwrite.h 154cd901f4d70d162e4b0dc93b94986b *src/mbedtls/library/platform.c e16df9793d55ea84eaa2588cccc83208 *src/mbedtls/library/platform_util.c 7edd72c0544b59c0680c8d13a3e30af3 *src/mbedtls/library/poly1305.c 122109a3477d1849b4ffa676beb86124 *src/mbedtls/library/psa_crypto.c 73e5803f90401876c6eafe289e3b8750 *src/mbedtls/library/psa_crypto_aead.c 70dbc5fd1c866d4c5f6bf93fac82fef2 *src/mbedtls/library/psa_crypto_aead.h 74a9c05fbd5f00fdb48d800b8b6dd3e7 *src/mbedtls/library/psa_crypto_cipher.c 902169817bd72337cf8a80031d257725 *src/mbedtls/library/psa_crypto_cipher.h 9724dee92498a83e4d9446d902d9b9cf *src/mbedtls/library/psa_crypto_client.c 6f894f45594f470c686d65510cbf3e5a *src/mbedtls/library/psa_crypto_core.h 7429e7d5d618acb749aa560fa7880635 *src/mbedtls/library/psa_crypto_core_common.h d9c2b6a2c73b04450c0b832e8520f80b *src/mbedtls/library/psa_crypto_driver_wrappers.h 14a20857edc184935a240fe57449a824 *src/mbedtls/library/psa_crypto_driver_wrappers_no_static.c 997e30da7ba58555b32876f06870691a *src/mbedtls/library/psa_crypto_driver_wrappers_no_static.h 17b6d860213c7f166d2bd2bb2248f8af *src/mbedtls/library/psa_crypto_ecp.c 1f6de18b64f66be73ca81ab80ffba8f9 *src/mbedtls/library/psa_crypto_ecp.h c7f6e234576f1717d0c07fcd95338494 *src/mbedtls/library/psa_crypto_ffdh.c 54d8669618b6c22e47d918c0dc501270 *src/mbedtls/library/psa_crypto_ffdh.h aba7616df2b3a5202c0677589cbab029 *src/mbedtls/library/psa_crypto_hash.c 906139405fd554c1189743325505c4e5 *src/mbedtls/library/psa_crypto_hash.h 45955d609aea859a6b36285d4e8c691c *src/mbedtls/library/psa_crypto_invasive.h 51aadf034ac2fcf4b3d749d6e7aaad06 *src/mbedtls/library/psa_crypto_its.h 647d935c584b0efcec179f04d026046a *src/mbedtls/library/psa_crypto_mac.c c3044cd709056387a37f67ac04f7ee61 *src/mbedtls/library/psa_crypto_mac.h 55b4ac01880a6859ebc018488d40d743 *src/mbedtls/library/psa_crypto_pake.c cf4d3c90eb09b908f072490f17f9eb98 *src/mbedtls/library/psa_crypto_pake.h 899db462685c90d834e75cbe61e0911f *src/mbedtls/library/psa_crypto_random_impl.h 42552e62462b9abb3aea8a2a8a9c84d6 *src/mbedtls/library/psa_crypto_rsa.c 6341169fc09352e122d4d02ed461e9d0 *src/mbedtls/library/psa_crypto_rsa.h 1ea85c377bd2c8d2f245c98deb2d7b1f *src/mbedtls/library/psa_crypto_se.c 89f1746ca6a3479f989bec07931de1c1 *src/mbedtls/library/psa_crypto_se.h 520b6ffad83535535680039ce6244049 *src/mbedtls/library/psa_crypto_slot_management.c 27263c073a00d82f18986f8c4e546bd6 *src/mbedtls/library/psa_crypto_slot_management.h f016a6efeef04905a30fb1f4b729fd72 *src/mbedtls/library/psa_crypto_storage.c 856dcec5915bd27451d37c2c46056b8d *src/mbedtls/library/psa_crypto_storage.h 020c06d9a1a3702984d61260a8bfbe13 *src/mbedtls/library/psa_its_file.c a1e29337cac656a8d715baba457e3456 *src/mbedtls/library/psa_util.c 533834d86f4b27c88f3fb5ecc0baaa52 *src/mbedtls/library/psa_util_internal.h c31bcc08232f0534d66af2e4a9951c03 *src/mbedtls/library/ripemd160.c 7eb16518c89aa799e334c71ec6d2338f *src/mbedtls/library/rsa.c 7828cfec072083f8a855f58dbd7896af *src/mbedtls/library/rsa_alt_helpers.c d1657e23a23e5ac51f2ea76c9c8d5085 *src/mbedtls/library/rsa_alt_helpers.h 6dcf197693db8698cbc32a5e39846bf5 *src/mbedtls/library/rsa_internal.h 67ef04a344c2635937c07b7f78e7f096 *src/mbedtls/library/sha1.c bd22f9051193261c961df0e798a8c03c *src/mbedtls/library/sha256.c 1382580d36f700f70f917f792d6de827 *src/mbedtls/library/sha3.c d63c8065562fe7b58ff52e2b80ca8c80 *src/mbedtls/library/sha512.c 10c3b2e4f879cdcfaf6e3da59c82aaeb *src/mbedtls/library/ssl_cache.c 03911fdeb3340dedd6ce9337782f701a *src/mbedtls/library/ssl_ciphersuites.c af41fe7ef3cb534ad0a2933416dfc0b8 *src/mbedtls/library/ssl_ciphersuites_internal.h a961587934f1ffd1353585cab74a292c *src/mbedtls/library/ssl_client.c afc50b6a4aad9d365f9b0daed1513ed8 *src/mbedtls/library/ssl_client.h d4f9b6b85f4ad0e30173ab8d371f187f *src/mbedtls/library/ssl_cookie.c 72b27c2d34204d5940606eb9cb249e69 *src/mbedtls/library/ssl_debug_helpers.h fe8e2079153258d723ec1f4a1a421f73 *src/mbedtls/library/ssl_debug_helpers_generated.c 9c97215021f4fa5c9a855cd4a3814b84 *src/mbedtls/library/ssl_misc.h eb440d93aeee339b5fbd7456b5c7ad50 *src/mbedtls/library/ssl_msg.c d75f519478da94440f593eaf2505bda8 *src/mbedtls/library/ssl_ticket.c 284a2a8d91be0232f8193571b6a2a541 *src/mbedtls/library/ssl_tls.c 70a65529acee2f7c2d7fce85a3a1e9b4 *src/mbedtls/library/ssl_tls12_client.c 094ba1c7a35f24461fcf5ae8be5e0f2e *src/mbedtls/library/ssl_tls12_server.c 4a67aee73f7327371a4b62a50e6efc08 *src/mbedtls/library/ssl_tls13_client.c e75b26bb04f57ef69ee78f314dbb966e *src/mbedtls/library/ssl_tls13_generic.c d3b3979a9dd1fc5d8ef575b6460cb418 *src/mbedtls/library/ssl_tls13_invasive.h 1972e6d5464c97c8f1665986e0c6c87f *src/mbedtls/library/ssl_tls13_keys.c cb722df0d2e2ad901139f826ddb0dd5b *src/mbedtls/library/ssl_tls13_keys.h 107acb31901d7ded5717eb7a2c5cfaf3 *src/mbedtls/library/ssl_tls13_server.c d1d49b8280dc08fe9214788a94ad28b1 *src/mbedtls/library/threading.c d219ace4e7eae2304cb1230310c09c4a *src/mbedtls/library/timing.c 96616cda5a27db82ef4dd6a607e5c0f2 *src/mbedtls/library/version.c 8344679f94f7b02eac3b1c23c77e1d4d *src/mbedtls/library/version_features.c 8a6ff8e73a0d62448428807d1102c5d2 *src/mbedtls/library/x509.c 362a65b79187aec695ed4bc645904c05 *src/mbedtls/library/x509_create.c 6cffd94a633207116d5918e3ec53f79f *src/mbedtls/library/x509_crl.c 73e17a076c11a6114922cc987ca441ce *src/mbedtls/library/x509_crt.c b841b478d4be79656abe9f043f64fdf9 *src/mbedtls/library/x509_csr.c ac7d86332773b8fa18ad091587a8c5f6 *src/mbedtls/library/x509_internal.h d3c9d3dcb6bb3f2817f97722f2c21f76 *src/mbedtls/library/x509write.c 0e4a25189b7a6e70430ac85630a0791b *src/mbedtls/library/x509write_crt.c 88053ff3d688d359e5c9c632cc8c5c4c *src/mbedtls/library/x509write_csr.c 004860b6c1cbf57de18d0a88f34adc19 *src/md5.h 313790b5e6faeb60fc0e7fafe40106f8 *src/mod_mbedtls.h 4c574178c50497bd958db412e8c44ef3 *src/response.h df8c12b6ac0ea7fb58e5eaf3b7961ec4 *src/rweb.c 282f9fcb2cb68ea168890f69fb2289c6 *src/sha1.h 3ceaa481066c12c0c733bb5a1d68d504 *src/sort.h 6232fe0e510463a3c35df3c3f64dffd3 *src/timer.h 6e2ee64196e5ba2eeb232d96f1f6da19 *tests/testthat.R 88f382b4fd4e87309b385a6f4a0cac22 *tests/testthat/_snaps/app-process.md edaf4b6cdf67263c768b2c44c3686028 *tests/testthat/_snaps/app.md 8dcc806ca4302ee3a8dbac408c2ef01b *tests/testthat/_snaps/git-app.md a830d7ad09a1b2af0bf8245db3f5c04a *tests/testthat/_snaps/mw-range-parser.md c6810546c0f7ec95048df89cca621938 *tests/testthat/_snaps/new-r/httpbin.md 39952e9ac2d30ff27ac6b26ac0fe5f8f *tests/testthat/_snaps/old-r/httpbin.md da6db0967dffac1d7f16354ab0f1a2ae *tests/testthat/_snaps/print.md 7bfb591d347f562480da0a047fd99572 *tests/testthat/_snaps/request.md 63fc9d71fd241752113aca48b7a36039 *tests/testthat/fixtures/git-repo.tar.gz 53eab8f2e4faa72bc61706f266402a3a *tests/testthat/fixtures/output/webfakes_app.txt 3eb28c5bbcf1b7012d10f79b344a2359 *tests/testthat/fixtures/output/webfakes_regexp.txt d454a35a5b8574d65605720fefffca34 *tests/testthat/fixtures/output/webfakes_request.txt 6e5e7fe88bfaa3a0a7b1249a330708be *tests/testthat/fixtures/output/webfakes_response.txt 5186b0805ea39b8efd70a1d3c85f7a89 *tests/testthat/fixtures/static/static.html cef8a5c5d7fcfb9cf601bf3a146a47e7 *tests/testthat/fixtures/static/subdir/static.json 5186b0805ea39b8efd70a1d3c85f7a89 *tests/testthat/fixtures/static2/static.html f6b1e97351bf27f84ff66285cfd3e033 *tests/testthat/fixtures/static2/static.tar.gz cef8a5c5d7fcfb9cf601bf3a146a47e7 *tests/testthat/fixtures/static2/subdir/static.json 01d5c74047c909bf938df6556a623e39 *tests/testthat/fixtures/views/test-view.html b8e828087bd8032c1c42a4163a87f6a1 *tests/testthat/helper.R f08d3dfde88afd104c84f429acc4ff7a *tests/testthat/setup.R 4a90a5419e30251902f66b8a1dbba76f *tests/testthat/teardown.R 3dfaec68e74e6642759cc898d61e99d5 *tests/testthat/test-app-process.R d18488c32bbc060957ceed73093a3410 *tests/testthat/test-app.R 513554bcb884628a9e386050f8085710 *tests/testthat/test-base64.R c4baeb676aa34c3883cbebb4163ba607 *tests/testthat/test-decode-url.R 0f8e02b1ffa6d10eb989d82958db9fc4 *tests/testthat/test-delay.R 6d602c878020448f07f814c870bb6b64 *tests/testthat/test-git-app.R 80c63c728c4d38a36c548ce4d15a66c5 *tests/testthat/test-http-methods.R ee516f16bc49bd2bdf71945dd42720e3 *tests/testthat/test-httpbin.R d293d42c2bf542a106b696901ff9eb0a *tests/testthat/test-https.R 6ca49aa9c7c2fea91e2c7787b2d54565 *tests/testthat/test-local.R 98dfd987e8fc8e0a328a24642e8b3b71 *tests/testthat/test-mime.R 0bd2645106533076e869f5ea1d7e07cb *tests/testthat/test-mw-etag.R 47da98af7a0ae25a6c9664b227ac2fc6 *tests/testthat/test-mw-log.R 6a614f072892ba3179bf91a04ac43abc *tests/testthat/test-mw-multipart.R 27c6340acadf379eee905a505aad39b1 *tests/testthat/test-mw-range-parser.R aa5f04f960b7065411ce48f3c0019790 *tests/testthat/test-mw-raw.R 809ffefce8355c37ea7011223f231e8f *tests/testthat/test-mw-static.R 9d40db2a25917e51c46694a516e38509 *tests/testthat/test-mw-urlencoded.R 7810b7fb7ad5738876cf97eeb9f381ee *tests/testthat/test-oauth.R 61d1656362498f96af20ad9d6d24eb48 *tests/testthat/test-path-matching.R d1920237b703b22014880cfcf03e2ac7 *tests/testthat/test-print.R f7a0b8332fdce52ab9eaec84afb0e6dd *tests/testthat/test-request.R 3242a959dd0b9b83f7aa609ce0b944ac *tests/testthat/test-response.R 10518bd5e2c32d54c5236e1587820961 *tests/testthat/test-threads.R d2c961ae63f037df07a14a1ad68ec7df *tests/testthat/test-tmpl-glue.R e73f6eff44d25373f9a5995f35edf1ef *tests/testthat/test-uuid.R webfakes/configure.win0000755000176200001440000000004314740737023014550 0ustar liggesusers#! /usr/bin/env sh sh ./configure webfakes/R/0000755000176200001440000000000015026556433012253 5ustar liggesuserswebfakes/R/uuid.R0000644000176200001440000000101015026556433013334 0ustar liggesusersuuid_random <- function() { # These uuids are pseudo-random, they are not secure! # xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx (8-4-4-4-12) # The 4 bits of digit M are the UUID version, # and the 1 to 3 most significant bits of digit N code the UUID variant. digits <- floor(stats::runif(32, 0, 16)) digits[13] <- 0x4 digits[17] <- bitwOr(bitwAnd(digits[17], 0x3), 0x8) x <- format(as.hexmode(digits)) paste( collapse = "", c(x[1:8], "-", x[9:12], "-", x[13:16], "-", x[17:20], "-", x[21:32]) ) } webfakes/R/digest.R0000644000176200001440000000021415026556433013652 0ustar liggesuserscrc32 <- function(x) { if (is.character(x)) { x <- charToRaw(x) } stopifnot(is.raw(x)) call_with_cleanup(c_webfakes_crc32, x) } webfakes/R/mw-range-parser.R0000644000176200001440000000437715026556433015420 0ustar liggesusers#' Middleware to parse a Range header #' #' Adds the requested ranges to the `ranges` element of the request #' object. `request$ranges` is a data frame with two columns, `from` and #' `to`. Each row corresponds one requested interval. #' #' When the last `n` bytes of the file are requested, the matrix row is set #' to `c(0, -n)`. When all bytes after a `p` position are requested, the #' matrix row is set to `c(p, Inf)`. #' #' If the intervals overlap, then `ranges` is not set, i.e. the `Range` #' header is ignored. #' #' If its syntax is invalid or the unit is not `bytes`, then the #' `Range` header is ignored. #' #' @return Handler function. #' #' @family middleware #' @export mw_range_parser <- function() { function(req, res) { rh <- req$get_header("Range") if (length(rh) == 0) { return("next") } req$ranges <- parse_range(rh) "next" } } parse_range <- function(rh) { rh <- trimws(rh) if (length(rh) == 0 || !startsWith(rh, "bytes=")) { return() } rh <- sub("^bytes=[ ]*", "", rh) rngs <- trimws(strsplit(rh, ",", fixed = TRUE)[[1]]) res <- matrix(integer(1), nrow = length(rngs), ncol = 2) for (i in seq_along(rngs)) { rng <- strsplit(rngs[i], "-")[[1]] if (length(rng) < 1 || length(rng) > 3) { return() } else if (length(rng) == 1) { res[i, 1] <- parse_int(rng[1]) res[i, 2] <- Inf if (is.na(res[i, 1]) || res[i, 1] < 0) return() } else if (rng[1] == "") { res[i, 1] <- 0 res[i, 2] <- -parse_int(rng[2]) if (is.na(res[i, 2]) || res[i, 2] > 0) return() } else { res[i, 1] <- parse_int(rng[1]) res[i, 2] <- parse_int(rng[2]) if ( is.na(res[i, 1]) || is.na(res[i, 2]) || res[i, 1] < 0 || res[i, 2] < 0 || res[i, 1] > res[i, 2] ) { return() } } } res <- res[order(res[, 1]), , drop = FALSE] # check for overlapping intervals if (intervals_overlap(res)) { return() } res } parse_int <- function(x) { suppressWarnings(as.integer(x)) } intervals_overlap <- function(x) { # assume that it is sorted on first column # then every interval needs to finish before the next one starts if (nrow(x) <= 1) { return(FALSE) } any(x[, 2][-nrow(x)] >= x[, 1][-1]) } webfakes/R/httpbin.R0000644000176200001440000007122015026556433014050 0ustar liggesusers#' Generic web app for testing HTTP clients #' #' A web app similar to `https://httpbin.org`. #' See [its specific docs](https://webfakes.r-lib.org/httpbin.html). #' You can also see these docs locally, by starting the app: #' ```r #' httpbin <- new_app_process(httpbin_app()) #' browseURL(httpbin$url()) #' ``` #' #' @param log Whether to log requests to the standard output. #' @return A `webfakes_app`. #' #' @export #' @examples #' app <- httpbin_app() #' proc <- new_app_process(app) #' url <- proc$url("/get") #' resp <- curl::curl_fetch_memory(url) #' curl::parse_headers_list(resp$headers) #' cat(rawToChar(resp$content)) #' proc$stop() httpbin_app <- function(log = interactive()) { encode_files <- function(files) { for (i in seq_along(files)) { files[[i]]$value <- paste0( "data:application/octet-stream;base64,", base64_encode(files[[i]]$value) ) } files } app <- new_app() # Log requests by default if (log) { app$use("logger" = mw_log()) } # Parse all kinds of bodies app$use("json body parser" = mw_json()) app$use( "text body parser" = mw_text(type = c("text/plain", "application/json")) ) app$use("multipart body parser" = mw_multipart()) app$use("URL encoded body parser" = mw_urlencoded()) app$use("cookie parser" = mw_cookie_parser()) # Add etags by default app$use("add etag" = mw_etag()) # Add date by default app$use("add date" = function(req, res) { res$set_header("Date", http_time_stamp()) "next" }) make_common_response <- function(req, res) { ret <- list( args = as.list(req$query), data = req$text, files = encode_files(req$files), form = req$form, headers = req$headers, json = req$json, method = req$method, path = req$path, origin = req$remote_addr, url = req$url ) } common_response <- function(req, res) { ret <- make_common_response(req, res) res$send_json(object = ret, auto_unbox = TRUE, pretty = TRUE) } # Main page app$get("/", function(req, res) { res$send_file( root = system.file(package = "webfakes", "examples", "httpbin", "assets"), "httpbin.html" ) }) # HTTP methods ========================================================= common_get <- function(req, res) { ret <- list( args = as.list(req$query), headers = req$headers, origin = req$remote_addr, path = req$path, url = req$url ) res$send_json(object = ret, auto_unbox = TRUE, pretty = TRUE) } app$get("/get", common_get) app$delete("/delete", common_response) app$patch("/patch", common_response) app$post("/post", common_response) app$put("/put", common_response) app$get("/forms/post", function(req, res) { res$send_file( root = system.file(package = "webfakes", "examples", "httpbin", "assets"), "forms-post.html" ) }) # Auth ================================================================= basic_auth <- function(req, res, error_status = 401L) { exp <- paste( "Basic", base64_encode(paste0(req$params$user, ":", req$params$passwd)) ) hdr <- req$get_header("Authorization") %||% "" if (exp == hdr) { res$send_json(list( authenticated = jsonlite::unbox(TRUE), user = jsonlite::unbox(req$params$user) )) } else { if (error_status == 401L) { res$set_header( "WWW-Authenticate", "Basic realm=\"Fake Realm\"" )$send_status(error_status) } else { res$send_status(error_status) } } } app$get("/basic-auth/:user/:passwd", function(req, res) { basic_auth(req, res, error_status = 401L) }) app$get("/hidden-basic-auth/:user/:passwd", function(req, res) { basic_auth(req, res, error_status = 404L) }) app$get("/bearer", function(req, res) { auth <- req$get_header("Authorization") %||% "" if (!grepl("^Bearer ", auth)) { res$set_header("WWW-Authenticate", "bearer")$send_status(401L) } else { token <- sub("^Bearer ", "", auth) res$send_json( list(authenticated = TRUE, token = token), auto_unbox = TRUE, pretty = TRUE ) } }) hash <- function(str, algorithm) { algo <- tolower(algorithm %||% "md5") algo <- c("md5" = "md5", "sha-256" = "sha256", "sha-512" = "sha512")[algo] if (is.na(algo)) { stop("Unknown hash algorithm for digest auth: ", algorithm) } digest::digest(str, algo = algo, serialize = FALSE) } hash1 <- function(realm, username, password, algorithm) { realm <- realm %||% "" hash( paste( collapse = ":", c( username, realm, password ) ), algorithm ) } hash2 <- function(credentials, req, algorithm) { qop <- credentials[["qop"]] %||% "auth" query <- if (nchar(req$query_string %||% "")) paste0("?", req$query_string) req_uri <- paste0(req$path, query) if (qop == "auth") { hash( paste( collapse = ":", c( toupper(req[["method"]]), req_uri ) ), algorithm ) } else { hash( paste0( collapse = ":", c( toupper(req[["method"]]), req_uri, hash(req$.body %||% "", algorithm) ) ), algorithm ) } } digest_challenge_response <- function(req, qop, algorithm, stale = FALSE) { nonce <- hash( paste0(req$remote_addr, ":", unclass(Sys.time()), ":", random_id(10)), algorithm ) opaque <- hash(random_id(10), algorithm) realm <- "webfakes.r-lib.org" qop <- qop %||% "auth,auth-int" wwwauth <- paste0( "Digest ", "realm=\"", realm, "\", ", "qop=\"", qop, "\", ", "nonce=\"", nonce, "\", ", "opaque=\"", opaque, "\", ", "algorithm=", algorithm, ", ", "stale=", stale ) wwwauth } next_stale_after_value <- function(x) { x <- suppressWarnings(as.integer(x)) if (is.na(x)) "never" else as.character(x - 1L) } check_digest_auth <- function(req, credentials, user, passwd) { if (is.null(credentials)) { return(FALSE) } algorithm <- credentials[["algorithm"]] HA1_value <- hash1( credentials[["realm"]], credentials[["username"]], passwd, algorithm ) HA2_value <- hash2(credentials, req, algorithm) qop <- credentials[["qop"]] %||% "compat" if (!qop %in% c("compat", "auth", "auth-int")) { return(FALSE) } response_hash <- if (qop == "compat") { hash( paste0( c( HA1_value, credentials[["nonce"]] %||% "", HA2_value ), collapse = ":" ), algorithm ) } else { if (any(!c("nonce", "nc", "cnonce", "qop") %in% names(credentials))) { return(FALSE) } hash( paste0( c( HA1_value, credentials[["nonce"]], credentials[["nc"]], credentials[["cnonce"]], credentials[["qop"]], HA2_value ), collapse = ":" ), algorithm ) } (credentials[["response"]] %||% "") == response_hash } digest_auth <- function(req, res, qop, user, passwd, algorithm, stale_after) { require_cookie_handling <- tolower(req$query$`require-cookie` %||% "") %in% c("1", "t", "true") if (!algorithm %in% c("MD5", "SHA-256", "SHA-512")) { algorithm <- "MD5" } if (!qop %in% c("auth", "auth-int")) { qop <- NULL } authorization <- req$get_header("Authorization") credentials <- if (!is.null(authorization)) { parse_authorization_header(authorization) } if ( is.null(authorization) || is.null(credentials) || tolower(credentials$scheme) != "digest" || (require_cookie_handling && is.null(req$get_header("Cookie"))) ) { wwwauth <- digest_challenge_response(req, qop, algorithm) res$set_status(401L)$add_cookie("stale_after", stale_after)$add_cookie( "fake", "fake_value" )$set_header("WWW-Authenticate", wwwauth)$send("") return() } if ( require_cookie_handling && (req$cookies[["fake"]] %||% "") != "fake_value" ) { res$add_cookie("fake", "fake_value")$add_status(403L)$send_json( list(errors = "missing cookie set on challenge"), pretty = TRUE ) return() } current_nonce <- credentials$nonce stale_after_value <- req$cookies$stale_after %||% "" if ( identical(current_nonce, req$cookies[["last_nonce"]] %||% "") || stale_after_value == "0" ) { wwwauth <- digest_challenge_response(req, qop, algorithm, TRUE) res$set_status(401L)$add_cookie("stale_after", stale_after)$add_cookie( "last_nonce", current_nonce )$add_cookie("fake", "fake_value")$set_header( "WWW-Authenticate", wwwauth )$send("") return() } if (!check_digest_auth(req, credentials, user, passwd)) { wwwauth <- digest_challenge_response(req, qop, algorithm, FALSE) res$set_status(401L)$add_cookie("stale_after", stale_after)$add_cookie( "last_nonce", current_nonce )$add_cookie("fake", "fake_value")$set_header( "WWW-Authenticate", wwwauth )$send("") return() } res$add_cookie("fake", "fake_value") if (!is.null(stale_after_value)) { res$add_cookie( "stale_after", next_stale_after_value(stale_after_value) ) } res$send_json( list(authentication = TRUE, user = user), pretty = TRUE, auto_unbox = TRUE ) } app$get("/digest-auth/:qop/:user/:passwd", function(req, res) { qop <- req$params$qop user <- req$params$user passwd <- req$params$passwd digest_auth(req, res, qop, user, passwd, "MD5", "never") }) app$get("/digest-auth/:qop/:user/:passwd/:algorithm", function(req, res) { qop <- req$params$qop user <- req$params$user passwd <- req$params$passwd algorithm <- req$params$algorithm digest_auth(req, res, qop, user, passwd, algorithm, "never") }) app$get( "/digest-auth/:qop/:user/:passwd/:algorithm/:stale_after", function(req, res) { qop <- req$params$qop user <- req$params$user passwd <- req$params$passwd algorithm <- req$params$algorithm stale_after <- req$params$stale_after digest_auth(req, res, qop, user, passwd, algorithm, stale_after) } ) # Status codes ========================================================= app$all( new_regexp("^/status/(?[0-9][0-9][0-9])$"), function(req, res) { status <- req$params$status res$set_status(status) if (status == "418") { res$send(paste( sep = "\n", "", " -=[ teapot ]=-", "", " _...._", " .' _ _ `.", " | .\"` ^ `\". _,", " \\_;`\"---\"`|//", " | ;/", " \\_ _/", " `\"\"\"`", "" )) } else { res$send("") } } ) # Request inspection =================================================== app$get("/headers", function(req, res) { ret <- list(headers = req$headers) res$send_json(ret, auto_unbox = TRUE, pretty = TRUE) }) app$get("/ip", function(req, res) { ret <- list(origin = req$remote_addr) res$send_json(ret, auto_unbox = TRUE, pretty = TRUE) }) app$get("/user-agent", function(req, res) { ret <- list("user-agent" = req$get_header("User-Agent")) res$send_json(ret, auto_unbox = TRUE, pretty = TRUE) }) # Response inspection ================================================== app$get("/etag/:etag", function(req, res) { etag <- req$params$etag # The mw_etag() middleware is active, so we need to do this after that res_etag <- NULL res$on_response(function(req, res) { if (!is.null(res_etag)) res$set_header("ETag", res_etag) }) parse <- function(x) { x <- strsplit(x, ",", fixed = TRUE)[[1]] re_match(x, '\\s*(W/)?"?([^"]*)"?\\s*')$groups[, 2] } if_none_match <- parse(req$get_header("If-None-Match") %||% "") if_match <- parse(req$get_header("If-Match") %||% "") if (length(if_none_match) > 0) { if (etag %in% if_none_match || "*" %in% if_none_match) { res$send_status(304) res_etag <- "etag" return() } } else if (length(if_match) > 0) { if ((!etag %in% if_match) && (!"*" %in% if_match)) { res$send_status(412) return() } } res_etag <- etag common_get(req, res) }) rsp_hdrs <- function(req, res) { obj <- structure(list(), names = character()) for (i in seq_along(req$query)) { key <- names(req$query)[i] res$add_header(key, req$query[[i]]) obj[[key]] <- c(obj[[key]], req$query[[i]]) } res$send_json(object = obj, auto_unbox = TRUE) } app$get("/response-headers", rsp_hdrs) app$post("/response-headers", rsp_hdrs) app$get("/cache", function(req, res) { if ( is.null(req$get_header("If-Modified-Since")) && is.null(req$get_header("If-None-Match")) ) { res$set_header("Last-Modified", http_time_stamp()) # etag is added by default common_response(req, res) } else { res$send_status(304) } }) app$get("/cache/:value", function(req, res) { value <- suppressWarnings(as.integer(req$params$value)) if (is.na(value)) { "next" } else { res$set_header( "Cache-Control", sprintf("public, max-age=%d", value) ) common_response(req, res) } }) # Response formats ===================================================== app$get("/deny", function(req, res) { res$set_type("text/plain")$send_file( root = system.file(package = "webfakes"), file.path("examples", "httpbin", "data", "deny.txt") ) }) app$get("/brotli", function(req, res) { ret <- make_common_response(req, res) ret$brotli <- TRUE json <- jsonlite::toJSON(ret, auto_unbox = TRUE, pretty = TRUE) data <- charToRaw(json) datax <- brotli::brotli_compress(data) res$set_type("application/json")$set_header( "Content-Encoding", "brotli" )$send(datax) }) app$get("/gzip", function(req, res) { ret <- make_common_response(req, res) ret$gzipped <- TRUE json <- jsonlite::toJSON(ret, auto_unbox = TRUE, pretty = TRUE) tmp <- tempfile() on.exit(unlink(tmp), add = TRUE) con <- file(tmp, open = "wb") con2 <- gzcon(con) writeBin(charToRaw(json), con2) flush(con2) close(con2) gzipped <- readBin(tmp, "raw", file.info(tmp)$size) res$set_type("application/json")$set_header( "Content-Encoding", "gzip" )$send(gzipped) }) app$get("/deflate", function(req, res) { ret <- make_common_response(req, res) ret$deflated <- TRUE json <- jsonlite::toJSON(ret, auto_unbox = TRUE, pretty = TRUE) data <- charToRaw(json) datax <- zip::deflate(data) res$set_type("application/json")$set_header( "Content-Encoding", "deflate" )$send(datax$output) }) app$get("/encoding/utf8", function(req, res) { res$set_type("text/html; charset=utf-8")$send_file( root = system.file(package = "webfakes"), file.path("examples", "httpbin", "data", "utf8.html") ) }) app$get("/html", function(req, res) { res$send_file( root = system.file(package = "webfakes"), file.path("examples", "httpbin", "data", "example.html") ) }) app$get("/json", function(req, res) { res$send_file( root = system.file(package = "webfakes"), file.path("examples", "httpbin", "data", "example.json") ) }) app$get("/robots.txt", function(req, res) { res$send_file( root = system.file(package = "webfakes"), file.path("examples", "httpbin", "data", "robots.txt") ) }) app$get("/xml", function(req, res) { res$send_file( root = system.file(package = "webfakes"), file.path("examples", "httpbin", "data", "example.xml") ) }) # Dynamic data ========================================================= app$get( list("/base64", new_regexp("/base64/(?[\\+/=a-zA-Z0-9]*)")), function(req, res) { value <- req$params$value %||% "" if (value == "") { value <- "RXZlcnl0aGluZyBpcyBSc29tZQ==" } plain <- charToRaw(base64_decode(value)) res$set_type("application/octet-stream")$send(plain) } ) app$get("/bytes/:n", function(req, res) { n <- suppressWarnings(as.integer(req$params$n)) if (is.na(n)) { return("next") } else { n <- min(n, 10000) bytes <- as.raw(as.integer(floor(stats::runif(n, min = 0, max = 256)))) res$set_type("application/octet-stream")$send(bytes) } }) app$all(new_regexp("/delay/(?[0-9\\.]+)$"), function(req, res) { delay <- suppressWarnings(as.numeric(req$params$delay)) if (is.na(delay)) { return("next") } else if (is.null(res$locals$seen)) { res$locals$seen <- TRUE # we need to send the headers early, to work around # https://github.com/r-lib/webfakes/issues/108 # but then if we want to send content-length and etag, we # need to calculate the response here and save it res$locals$response <- jsonlite::toJSON( make_common_response(req, res), auto_unbox = TRUE, pretty = TRUE ) content_length <- nchar(res$locals$response, type = "bytes") res$set_header('Content-Length', content_length) etag <- paste0("\"", crc32(res$locals$response), "\"") res$set_header("ETag", etag) # this actually cannot happen, because the ETag header is also # part of the response, so it is included in the ETag calculation # So there is no ETag that could ever match here. Nevertheless we # check for it, for future reference. req_etag <- req$get_header("If-None-Match") if (!is.null(req_etag) && req_etag == etag) { res$locals$response <- NULL res$set_status(304) } else { res$set_status(200) } res$set_type("application/json") res$write(raw(0)) delay <- min(delay, 10) res$delay(delay) } else if (req$method == "head") { res$send_status(200L) } else { res$send(res$locals$response) } }) app$get("/drip", function(req, res) { # First time? if (is.null(res$locals$drip)) { duration <- as.double(req$query$duration %||% 2) numbytes <- as.integer(req$query$numbytes %||% 10) code <- as.integer(req$query$code %||% 200L) delay <- as.double(req$query$delay %||% 0) # how much to wait between messages, at least 10ms pause <- max(duration / numbytes, 0.01) # how many messages nummsg <- duration / pause + 1 # how big is a message, at least a byte msgsize <- max(floor(numbytes / nummsg), 1) res$locals$drip <- list( tosend = numbytes, msgsize = msgsize, pause = pause ) res$set_header("Content-Length", numbytes)$set_header( "Content-Type", "application/octet-stream" )$set_status(code) if (delay > 0) return(res$delay(delay)) } len <- min(res$locals$drip$tosend, res$locals$drip$msgsize) res$write(strrep("*", len)) res$locals$drip$tosend <- res$locals$drip$tosend - len if (res$locals$drip$tosend == 0) { res$send("") } else { res$delay(res$locals$drip$pause) } }) app$get(new_regexp("^/stream/(?[0-9]+)$"), function(req, res) { n <- suppressWarnings(as.integer(req$params$n)) n <- min(n, 100) if (length(n) == 0 || is.na(n)) { return("next") } msg <- make_common_response(req, res)[c("url", "args", "headers", "origin")] res$set_type("application/json") for (i in seq_len(n)) { msg$id <- i - 1L txt <- paste0(jsonlite::toJSON(msg, auto_unbox = TRUE), "\n") res$send_chunk(charToRaw(txt)) } }) app$get(new_regexp("^/stream-bytes/(?[0-9]+)$"), function(req, res) { n <- suppressWarnings(as.integer(req$params$n)) n <- min(n, 100 * 1024) seed <- suppressWarnings(as.integer(req$query$seed %||% 42)) chunk_size <- suppressWarnings(as.integer(req$query$chunk_size %||% 10240)) if ( length(n) == 0 || is.na(n) || length(seed) == 0 || is.na(seed) || length(chunk_size) == 0 || is.na(chunk_size) ) { return("next") } oldseed <- .GlobalEnv$.Random.seed on.exit(set.seed(oldseed)) set.seed(seed) bytes <- as.raw(as.integer(floor(stats::runif(n, min = 0, max = 256)))) nc <- ceiling(n / chunk_size) for (i in seq_len(nc)) { from <- (i - 1) * chunk_size + 1 to <- min(length(bytes), i * chunk_size) res$send_chunk(bytes[from:to]) } }) re_range <- new_regexp("^/range/(?[0-9]+)$") # This is not in httpbin, but it is handy to get the size of the # response, and to see whether the server supports ranges app$head(re_range, function(req, res) { numbytes <- suppressWarnings(as.integer(req$params$n)) if (length(numbytes) == 0 || is.na(numbytes)) { return("next") } res$set_header("ETag", paste0("range", numbytes))$set_header( "Accept-Ranges", "bytes" )$set_header("Content-Length", numbytes)$send_status(200L) }) app$get(re_range, function(req, res) { if (is.null(res$locals$range)) { numbytes <- suppressWarnings(as.integer(req$params$n)) if (length(numbytes) == 0 || is.na(numbytes)) { return("next") } if (numbytes < 0 || numbytes > 100 * 1024) { res$set_header("ETag", paste0("range", numbytes))$set_header( "Accept-Ranges", "bytes" )$set_status(404L)$send( "number of bytes must be in the range (0, 102400]." ) return() } chunk_size <- max(1, as.integer(req$query$chunk_size %||% (10 * 1024))) duration <- as.integer(req$query$duration %||% 0) pause_per_byte <- duration / numbytes if (duration == 0) { chunk_size <- numbytes } ranges <- parse_range(req$get_header("Range")) # just like httpbin, we do not support multiple ranges if (NROW(ranges) != 1) { ranges <- NULL } # This is not exactly the same as httpbin, but rather follows # https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests # and also how web servers seem to behave. # # In particular, in these cases we return the full response: # - no Range header, # - invalid Range header syntax, # - overlapping Range header ranges # # Otherwise, if a range is outside of the size of the response, we # return a 416 response. if (!is.null(ranges)) { ranges[ranges == Inf] <- numbytes if (any(ranges[, 2] >= numbytes)) { res$set_header("ETag", paste0("range", numbytes))$set_header( "Accept-Ranges", "bytes" )$set_header( "Content-Range", paste0("bytes */", numbytes) )$set_header("Content-Length", 0L)$send_status(416L) return() } } # we need the response for sure abc <- paste(letters, collapse = "") bytes <- substr(strrep(abc, numbytes / nchar(abc) + 1), 1, numbytes) res$locals$range <- list( bytes = bytes, chunk_size = chunk_size, pause_per_byte = pause_per_byte ) # First part, so send status and headers if (is.null(ranges)) { res$set_header("ETag", paste0("range", numbytes))$set_header( "Accept-Ranges", "bytes" )$set_header("Content-Length", numbytes)$set_status(200L) } else if (nrow(ranges) == 1) { # A single range res$set_header("ETag", paste0("range", numbytes))$set_header( "Accept-Ranges", "bytes" )$set_header( "Content-Range", sprintf("bytes=%d-%d/%d", ranges[1, 1], ranges[1, 2], numbytes) )$set_header( "Content-Length", ranges[1, 2] - ranges[1, 1] + 1L )$set_status(206L) # This is all we need to send res$locals$range$bytes <- substr( bytes, ranges[1, 1] + 1, ranges[1, 2] + 1L ) } else { # This cannot happen now, we do not support multiple ranges # Maybe later } } # send a part chunk_size <- res$locals$range$chunk_size pause <- res$locals$range$pause_per_byte tosend <- substr(res$locals$range$bytes, 1, chunk_size) res$locals$range$bytes <- substr( res$locals$range$bytes, chunk_size + 1L, nchar(res$locals$range$bytes) ) res$write(tosend) if (pause * nchar(tosend) > 0) { res$delay(pause * nchar(tosend)) } }) app$get("/uuid", function(req, res) { ret <- list(uuid = uuid_random()) res$send_json(ret, auto_unbox = TRUE, pretty = TRUE) }) app$get( new_regexp("^/links/(?[0-9]+)(/(?[0-9]+))?$"), function(req, res) { n <- suppressWarnings(as.integer(req$params$n)) o <- suppressWarnings(as.integer(req$params$offset)) if (length(o) == 0 || is.na(o)) { o <- 1 } if (length(n) == 0 || is.na(n)) { return("next") } n <- min(max(1, n), 200) o <- min(max(1, o), n) links <- sprintf("%d", n, 1:n, 1:n) links[o] <- o html <- paste0( "Links", paste(links, collapse = " "), "" ) res$set_type("html")$send(html) } ) # Cookies ============================================================== app$get("/cookies", function(req, res) { cks <- req$cookies res$send_json( object = list(cookies = cks), auto_unbox = TRUE, pretty = TRUE ) }) app$get("/cookies/set/:name/:value", function(req, res) { res$add_cookie(req$params$name, req$params$value) res$redirect("/cookies", 302L) }) app$get("/cookies/set", function(req, res) { for (n in names(req$query)) { res$add_cookie(n, req$query[[n]]) } res$redirect("/cookies", 302L) }) app$get("/cookies/delete", function(req, res) { for (n in names(req$query)) { res$clear_cookie(n) } res$redirect("/cookies", 302L) }) # Images =============================================================== app$get("/image", function(req, res) { act <- req$get_header("Accept") ok <- c( "image/webp", "image/svg+xml", "image/jpeg", "image/png", "image/*" ) msg <- list( message = "Client did not request a supported media type.", accept = ok ) if (is.null(act) || !act %in% ok) { res$set_status(406)$set_type("application/json")$send_json(msg) } else { fls <- c( "image/webp" = "Rlogo.webp", "image/svg+xml" = "Rlogo.svg", "image/jpeg" = "Rlogo.jpeg", "image/png" = "Rlogo.png", "image/*" = "Rlogo.png" ) res$send_file( root = system.file(package = "webfakes"), file.path("examples", "httpbin", "images", fls[act]) ) } }) app$get( new_regexp("/image/(?jpeg|png|svg|webp)"), function(req, res) { filename <- paste0("Rlogo.", req$params$format) res$send_file( root = system.file(package = "webfakes"), file.path("examples", "httpbin", "images", filename) ) } ) # Redirects ============================================================ app$get("/absolute-redirect/:n", function(req, res) { n <- suppressWarnings(as.integer(req$params$n)) if (is.na(n)) { return("next") } else { if (n == 1) { url <- sub("/absolute-redirect/[0-9]+$", "/get", req$url) } else { n <- min(n, 5) url <- paste0(sub("/[0-9]+$", "/", req$url), n - 1) } res$redirect(url, 302L) } }) app$get(c("/redirect/:n", "/relative-redirect/:n"), function(req, res) { n <- suppressWarnings(as.integer(req$params$n)) if (is.na(n)) { return("next") } else { if (n == 1) { url <- sub("/redirect/[0-9]+$", "/get", req$path) url <- sub("/relative-redirect/[0-9]+$", "/get", url) } else { n <- min(n, 5) url <- paste0(sub("/[0-9]+$", "/", req$path), n - 1) } res$redirect(url, 302L) } }) app$all("/redirect-to", function(req, res) { res$redirect(req$query$url, req$query$status_code %||% 302) }) # Anything ============================================================= app$all(new_regexp("^/anything"), common_response) app } webfakes/R/print.R0000644000176200001440000001220615026556433013533 0ustar liggesusersformat_named_list <- function(name, data) { c(paste0(name, ":"), if (length(data)) paste0(" ", names(data), ": ", data)) } format_path <- function(patterns) { # Make sure patterns is a list if (inherits(patterns, "webfakes_regexp")) { patterns <- list(patterns) } else if (is.character(patterns)) { patterns <- as.list(patterns) } paste(collapse = ", ", vapply(patterns, format, character(1))) } #' @export format.webfakes_app <- function(x, ...) { header <- "" data <- vapply(x$.stack, FUN.VALUE = character(1), function(x) { name <- if (nchar(x$name %||% "")) paste0(" # ", x$name) paste0(" ", x$method, " ", format_path(x$path), name) }) methods <- c( " all(path, ...) # add route for *all* HTTP methods", " delete(path, ...) # add route for DELETE", " engine(ext, engine) # add template engine for file extension", " head(path, ...) # add route for HEAD", " listen(port) # start web app on port", " patch(path, ...) # add route for PATCH", " post(path, ...) # add route for POST", " put(path, ...) # add route for PUT", " use(...) # add middleware", " locals # app-wide shared data" ) help <- "# see ?webfakes_app for all methods" c(header, "routes:", data, "fields and methods:", methods, help) } #' @export print.webfakes_app <- function(x, ...) { cat(format(x, ...), sep = "\n") invisible(x) } #' @export format.webfakes_request <- function(x, ...) { header <- "" data <- c( "method:", paste0(" ", x$method), "url:", paste0(" ", x$url), "client:", paste0(" ", x$remote_addr), format_named_list("query", x$query), format_named_list("headers", x$headers) ) methods <- c( " app # the webfakes_app the request belongs to", " headers # HTTP request headers", " hostname # server hostname, the Host header", " method # HTTP method of request (lowercase)", " path # server path", " protocol # http or https", " query_string # raw query string without '?'", " query # named list of query parameters", " remote_addr # IP address of the client", " url # full URL of the request", " get_header(field) # get a request header" ) help <- " # see ?webfakes_request for details" c(header, data, "fields and methods:", methods, help) } #' @export print.webfakes_request <- function(x, ...) { cat(format(x, ...), sep = "\n") invisible(x) } #' @export format.webfakes_response <- function(x, ...) { header <- "" methods <- c( " app # the webfakes_app the response belongs to", " locals # response-wide shared data", " get_header(field) # query response header", " on_response(fun) # call handler function for complete response", " redirect(path, status) # send redirect response", " render(view, locals) # render template", " send(body) # send text or raw data", " send_file(path, root) # send a file (automatic Content-Type)", " send_json(object, text, ...)", " # send JSON data", " send_status(status) # send HTTP status and empty body", " set_header(field, value) # set a response header", " set_status(status) # set response status code", " set_type(type) # set Content-Type" ) help <- " # see ?webfakes_response for details" c(header, "fields and methods:", methods, help) } #' @export print.webfakes_response <- function(x, ...) { cat(format(x, ...), sep = "\n") invisible(x) } #' @export format.webfakes_regexp <- function(x, ...) { paste0(" ", encodeString(x, quote = "\"")) } #' @export print.webfakes_regexp <- function(x, ...) { cat(format(x, ...), sep = "\n") invisible(x) } #' @export format.webfakes_app_process <- function(x, ...) { header <- "" state <- x$get_state() data <- c( "state:", paste0(" ", state), "auto_start:", paste0(" ", x$.auto_start), "process id:", paste0(" ", if (state == "not running") "none" else x$.process$get_pid()), "http url:", paste0(" ", if (state == "live") x$url() else "NA") ) methods <- c( " get_app() # get the app object", " get_port() # query (first) port of the app", " get_ports() # query all ports of the app", " get_state() # query web server process state", " local_env(envvars) # set temporary environment variables", " start() # start the app", " url(path, query) # query url for an api path", " stop() # stop web server process" ) help <- "# see ?webfakes_app_process for details" c(header, data, "fields and methods:", methods, help) } #' @export print.webfakes_app_process <- function(x, ...) { cat(format(x, ...), sep = "\n") invisible(x) } webfakes/R/local-app-process.R0000644000176200001440000000121615026556433015722 0ustar liggesusers#' App process that is cleaned up automatically #' #' You can start the process with an explicit `$start()` call. #' Alternatively it starts up at the first `$url()` or `$get_port()` #' call. #' #' @inheritParams new_app_process #' @param ... Passed to [new_app_process()]. #' @param .local_envir The environment to attach the process cleanup to. #' Typically a frame. When this frame finishes, the process is stopped. #' #' @export #' @seealso [new_app_process()] for more details. local_app_process <- function(app, ..., .local_envir = parent.frame()) { proc <- new_app_process(app, ...) withr::defer(proc$stop(), envir = .local_envir) proc } webfakes/R/rematch2.R0000644000176200001440000000170115026556433014102 0ustar liggesusersre_match <- function(text, pattern, perl = TRUE, ...) { stopifnot(is.character(pattern), length(pattern) == 1, !is.na(pattern)) text <- as.character(text) match <- regexpr(pattern, text, perl = perl, ...) start <- as.vector(match) length <- attr(match, "match.length") end <- start + length - 1L matchstr <- substring(text, start, end) matchstr[start == -1] <- NA_character_ empty <- data.frame(stringsAsFactors = FALSE, .text = text)[, numeric()] res <- list(match = !is.na(matchstr), groups = empty) if (!is.null(attr(match, "capture.start"))) { gstart <- attr(match, "capture.start") glength <- attr(match, "capture.length") gend <- gstart + glength - 1L groupstr <- substring(text, gstart, gend) groupstr[gstart == -1] <- NA_character_ dim(groupstr) <- dim(gstart) res$groups <- cbind(groupstr, res$groups, stringsAsFactors = FALSE) names(res$groups) <- attr(match, "capture.names") } res } webfakes/R/cleancall.R0000644000176200001440000000015215026556433014312 0ustar liggesuserscall_with_cleanup <- function(ptr, ...) { .Call(c_cleancall_call, pairlist(ptr, ...), parent.frame()) } webfakes/R/server.R0000644000176200001440000001456615026556433013720 0ustar liggesusersparse_ports <- function(opts = server_opts()) { paste0( if (!is.null(opts$interfaces)) paste0(opts$interfaces, ":"), opts$port %||% "0", collapse = "," ) } server_start <- function(opts = server_opts()) { ports <- parse_ports(opts) if (!is.na(opts$access_log_file)) { mkdirp(dirname(opts$access_log_file)) file.create(opts$access_log_file) } if (!is.na(opts$error_log_file)) { mkdirp(dirname(opts$error_log_file)) file.create(opts$error_log_file) } throttle <- paste0( "*=", if (opts$throttle == Inf) "0" else opts$throttle ) options <- c( "listening_ports" = ports, "num_threads" = opts$num_threads, "enable_keep_alive" = c("no", "yes")[[opts$enable_keep_alive + 1]], "access_log_file" = opts$access_log_file %|NA|% "", "error_log_file" = opts$error_log_file %|NA|% "", "tcp_nodelay" = c("0", "1")[[opts$tcp_nodelay + 1]], "throttle" = throttle, # These are not configurable currently "request_timeout_ms" = "100000", "enable_auth_domain_check" = "no", "decode_url" = if (opts$decode_url) "yes" else "no", "ssl_certificate" = if (!is.null(opts$ssl_certificate)) opts$ssl_certificate ) srv <- call_with_cleanup(c_server_start, options) attr(srv, "options") <- opts srv } #' Webfakes web server options #' #' @param remote Meta-option. If set to `TRUE`, webfakes uses slightly #' different defaults, that are more appropriate for a background #' server process. #' @param port Port to start the web server on. Defaults to a randomly #' chosen port. #' @param num_threads Number of request handler threads to use. Typically #' you don't need more than one thread, unless you run test cases in #' parallel or you make concurrent HTTP requests. #' @param interfaces The network interfaces to listen on. Being a test #' web server, it defaults to the localhost. Only bind to a public #' interface if you know what you are doing. webfakes was not designed #' to serve public web pages. #' @param enable_keep_alive Whether the server keeps connections alive. #' @param access_log_file `TRUE`, `FALSE`, or a path. See 'Logging' #' below. #' @param error_log_file `TRUE`, `FALSE`, or a path. See 'Logging' #' below. #' @param tcp_nodelay if `TRUE` then packages will be sent as soon as #' possible, instead of waiting for a full buffer or timeout to occur. #' @param throttle Limit download speed for clients. If not `Inf`, #' then it is the maximum number of bytes per second, that is sent to #' as connection. #' @param decode_url Whether the server should automatically decode #' URL-encodded URLs. If `TRUE` (the default), `/foo%2fbar` will be #' converted to `/foo/bar` automatically. If `FALSE`, URLs as not #' URL-decoded. #' @param ssl_certificate Path to the SSL certificate of the server, #' needed if you want to server HTTPS requests. #' @return List of options that can be passed to `webfakes_app$listen()` #' (see [new_app()]), and [new_app_process()]. #' #' @section Logging: #' #' * For `access_log_file`, `TRUE` means `/access.log`. #' * For `error_log_file`, `TRUE` means `/error.log`. #' #' `` is set to the contents of the `WEBFAKES_LOG_DIR` #' environment variable, if it is set. Otherwise it is set to #' `/webfakes` for local apps and `//webfakes` for #' remote apps (started with `new_app_procss()`). #' #' `` is the session temporary directory of the _main process_. #' #' `` is the process id of the subprocess. #' #' @export #' @examples #' # See the defaults #' server_opts() server_opts <- function( remote = FALSE, port = NULL, num_threads = 1, interfaces = "127.0.0.1", enable_keep_alive = FALSE, access_log_file = remote, error_log_file = TRUE, tcp_nodelay = FALSE, throttle = Inf, decode_url = TRUE, ssl_certificate = NULL ) { log_dir <- Sys.getenv("WEBFAKES_LOG_DIR", file.path(tempdir(), "webfakes")) if (isTRUE(access_log_file)) { if (remote) { access_log_file <- file.path(log_dir, "%p", "access.log") } else { access_log_file <- file.path(log_dir, "access.log") } } else if (isFALSE(access_log_file)) { access_log_file <- NA_character_ } if (isTRUE(error_log_file)) { if (remote) { error_log_file <- file.path(log_dir, "%p", "error.log") } else { error_log_file <- file.path(log_dir, "error.log") } } else if (isFALSE(error_log_file)) { error_log_file <- NA_character_ } rm(log_dir) ssl_certificate <- ssl_certificate %||% system.file("cert/localhost/server.pem", package = "webfakes") as.list(environment()) } server_get_ports <- function(srv) { as.data.frame(call_with_cleanup(c_server_get_ports, srv)) } server_stop <- function(srv) { invisible(call_with_cleanup(c_server_stop, srv)) } server_poll <- function(srv, cleanup = TRUE) { while (TRUE) { tryCatch( return(call_with_cleanup(c_server_poll, srv, cleanup)), error = function(err) { cat(as.character(err), file = stderr()) stop(new_webfakes_error()) } ) } } response_send <- function(req) { tryCatch( call_with_cleanup(c_response_send, req), error = function(err) { cat(as.character(err), file = stderr()) stop(new_webfakes_error()) } ) invisible(NULL) } response_send_chunk <- function(req, data) { tryCatch( call_with_cleanup(c_response_send_chunk, req, data), error = function(err) { cat(as.character(err), file = stderr()) stop(new_webfakes_error()) } ) invisible(NULL) } response_send_error <- function(req, msg, status) { tryCatch( call_with_cleanup(c_response_send_error, req, msg, status), error = function(err) { cat(as.character(err), file = stderr()) stop(new_webfakes_error()) } ) invisible(NULL) } response_delay <- function(req, secs) { tryCatch( call_with_cleanup(c_response_delay, req, secs), error = function(err) { cat(as.character(err), file = stderr()) stop(new_webfakes_error()) } ) invisible(NULL) } response_write <- function(req, data) { tryCatch( call_with_cleanup(c_response_write, req, data), error = function(err) { cat(as.character(err), file = stderr()) stop(new_webfakes_error()) } ) invisible(NULL) } new_webfakes_error <- function(...) { structure( list(message = "error in webfakes connection", ...), class = c("webfakes_error", "error", "condition") ) } webfakes/R/app-process.R0000644000176200001440000001770215026556433014641 0ustar liggesusers#' Run a webfakes app in another process #' #' Runs an app in a subprocess, using [callr::r_session]. #' #' @param app `webfakes_app` object, the web app to run. #' @param port Port(s) to use. By default the OS assigns a port. #' Add an `"s"` suffix to the port to use HTTPS. Use `"0s"` to #' use an OS assigned port with HTTPS. See the [how-to] on how #' to run the web server on multiple ports. #' @param opts Server options. See [server_opts()] for the defaults. #' @param start Whether to start the web server immediately. If this is #' `FALSE`, and `auto_start` is `TRUE`, then it is started as neeed. #' @param auto_start Whether to start the web server process automatically. #' If `TRUE` and the process is not running, then `$start()`, #' `$get_port()`, `$get_ports()` and `$url()` start the process. #' @param process_timeout How long to wait for the subprocess to start, in #' milliseconds. #' @param callr_opts Options to pass to [callr::r_session_options()] #' when setting up the subprocess. #' @return A `webfakes_app_process` object. #' #' ## Methods #' #' The `webfakes_app_process` class has the following methods: #' #' ```r #' get_app() #' get_port() #' get_ports() #' stop() #' get_state() #' local_env(envvars) #' url(path = "/", query = NULL) #' ``` #' #' * `envvars`: Named list of environment variables. The `{url}` substring #' is replaced by the URL of the app. #' * `path`: Path to return the URL for. #' * `query`: Additional query parameters, a named list, to add to the URL. #' #' `get_app()` returns the app object. #' #' `get_port()` returns the (first) port the web server is running on. #' #' `get_ports()` returns all ports the web server is running on, and #' whether it uses SSL on those ports, in a data frame with columns #' `ipv4`, `ipv6`, `port` and `ssl`. #' #' `stop()` stops the web server, and also the subprocess. If the error #' log file is not empty, then it dumps its contents to the screen. #' #' `get_state()` returns a string, the state of the web server: #' * `"not running"` the server is not running (because it was stopped #' already). #' * `"live"` means that the server is running. #' * `"dead"` means that the subprocess has quit or crashed. #' #' `local_env()` sets the given environment variables for the duration of #' the app process. It resets them in `$stop()`. Webfakes replaces `{url}` #' in the value of the environment variables with the app URL, so you can #' set environment variables that point to the app. #' #' `url()` returns the URL of the web app. You can use the `path` #' parameter to return a specific path. #' #' @aliases webfakes_app_process #' @seealso [local_app_process()] for automatically cleaning up the #' subprocess. #' @export #' @examples #' app <- new_app() #' app$get("/foo", function(req, res) { #' res$send("Hello world!") #' }) #' #' proc <- new_app_process(app) #' url <- proc$url("/foo") #' resp <- curl::curl_fetch_memory(url) #' cat(rawToChar(resp$content)) #' #' proc$stop() new_app_process <- function( app, port = NULL, opts = server_opts(remote = TRUE), start = FALSE, auto_start = TRUE, process_timeout = NULL, callr_opts = NULL ) { app port opts start auto_start process_timeout callr_opts # WTF tmp <- tempfile() sink(tmp) print(app$.stack) sink(NULL) unlink(tmp) process_timeout <- process_timeout %||% as.integer(Sys.getenv( "R_WEBFAKES_PROCESS_TIMEOUT", if (Sys.getenv("R_COVR") == "true") 600000 else 5000 )) self <- new_object( "webfakes_app_process", start = function() { self$.app <- app callr_opts <- do.call(callr::r_session_options, as.list(callr_opts)) self$.process <- callr::r_session$new(callr_opts, wait = TRUE) self$.process$call( args = list(app, port, opts), function(app, port, opts) { library(webfakes) .GlobalEnv$app <- app app$listen(port = port, opts = opts) } ) if (self$.process$poll_process(process_timeout) != "ready") { self$.process$kill() stop("webfakes app subprocess did not start :(") } msg <- self$.process$read() if (msg$code == 200 && !is.null(msg$error)) { msg$error$message <- paste0( "failed to start webfakes app process: ", msg$error$message ) stop(msg$error) } if (msg$code != 301) { stop( "Unexpected message from webfakes app subprocess. ", "Report a bug please." ) } self$.ports <- msg$message$ports self$.port <- msg$message$ports$port[1] self$.access_log <- msg$message$access_log self$.error_log <- msg$message$error_log self$.set_env() invisible(self) }, get_app = function() self$.app, get_port = function() { if (self$get_state() == "not running" && auto_start) { self$start() } self[[".port"]] }, get_ports = function() { if (self$get_state() == "not running" && auto_start) { self$start() } self[[".ports"]] }, stop = function() { self$.reset_env() if (is.null(self$.process)) { return(invisible(self)) } if (!self$.process$is_alive()) { status <- self$.process$get_exit_status() out <- err <- NULL try_silently(out <- self$.process$read_output()) try_silently(err <- self$.process$read_error()) cat0("webfakes process dead, exit code: ", status, "\n") if (!is.null(out)) { cat0("stdout:", out, "\n") } if (!is.null(err)) cat0("stderr:", err, "\n") } try_silently(self$.process$close(grace = 0)) try_silently(self$.process$read()) self$.print_errors() self$.process <- NULL invisible(self) }, get_state = function() { if (is.null(self$.process)) { "not running" } else if (self$.process$is_alive()) { "live" } else { "dead" } }, local_env = function(envvars) { if (!is.null(self$.process)) { local <- unlist(envvars) local[] <- gsub("{url}", self$url(), local, fixed = TRUE) self$.old_env <- c(self$.old_env, set_envvar(local)) } else { self$.local_env <- utils::modifyList( as.list(self$.local_env), as.list(envvars) ) } invisible(self) }, .set_env = function() { local <- unlist(self$.local_env) local[] <- gsub("{url}", self$url(), local, fixed = TRUE) self$.old_env <- set_envvar(local) invisible(self) }, .reset_env = function() { if (!is.null(self$.old_env)) { set_envvar(self$.old_env) self$.old_env <- NULL } }, url = function( path = "/", query = NULL, https = FALSE, domain = "127.0.0.1" ) { if (self$get_state() == "not running" && auto_start) { self$start() } if (!is.null(query)) { query <- paste0("?", paste0(names(query), "=", query, collapse = "&")) } port <- if (https) { if (!any(self$.ports$ssl)) { stop("Web server does support HTTPS") } self$.ports$port[self$.ports$ssl][1] } else { self$.port } proto <- if (self$.ports$ssl[match(port, self$.ports$port)]) { "https" } else { "http" } paste0(proto, "://", domain, ":", port, path, query) }, .process = NULL, .app = NULL, .ports = NULL, .port = NULL, .old_env = NULL, .access_log = NA_character_, .error_log = NA_character_, .auto_start = auto_start, .print_errors = function() { if ( !is.na(self$.error_log) && file.exists(self$.error_log) && file.info(self$.error_log)$size > 0 ) { err <- readLines(self$.error_log, warn = FALSE) cat("webfakes web server errors:\n") cat(err, sep = "\n") } } ) reg.finalizer(self, function(x) x$.reset_env()) if (start) { self$start() } self } webfakes/R/mw-cookie-parser.R0000644000176200001440000000154115026556433015563 0ustar liggesusers#' Middleware to parse Cookies #' #' Adds the cookies as the `cookies` element of the request object. #' #' It ignores cookies in an invalid format. It ignores duplicate cookies: #' if two cookies have the same name, only the first one is included. #' #' @return Handler function. #' #' @family middleware #' @export mw_cookie_parser <- function() { function(req, res) { ch <- req$get_header("Cookie") %||% "" req$cookies <- parse_cookies(ch) "next" } } parse_cookies <- function(x) { parts <- strsplit(x, ";", fixed = TRUE)[[1]] dict <- structure(list(), names = character()) lapply(parts, function(ck) { ck <- trimws(ck) key <- sub("^([^=]+)=.*$", "\\1", ck) if (key == ck) { return() } if (!is.null(dict[[key]])) { return() } value <- sub("^[^=]+=", "", ck) dict[[key]] <<- value }) dict } webfakes/R/path.R0000644000176200001440000000333315026556433013334 0ustar liggesusers#' Create a new regular expression to use in webfakes routes #' #' Note that webfakes uses PERL regular expressions. #' #' @details #' As R does not have data type or class for regular expressions, #' you can use `new_regexp()` to mark a string as a regular expression, #' when adding routes. #' #' @param x String scalar containing a regular expression. #' @return String with class `webfakes_regexp`. #' #' @aliases webfakes_regexp #' @seealso The 'Path specification' and 'Path parameters' chapters #' of the manual of [new_app()]. #' @export #' @examples #' new_regexp("^/api/match/(?.*)$") new_regexp <- function(x) structure(x, class = "webfakes_regexp") path_match <- function(method, path, handler) { if (handler$method == "use") { return(TRUE) } if ( (!handler$method %in% c("all", method)) && !(handler$method == "get" && method == "head") ) { return(FALSE) } pattern_match(path, handler$path) } pattern_match <- function(path, patterns) { # Make sure patterns is a list if (inherits(patterns, "webfakes_regexp")) { patterns <- list(patterns) } else if (is.character(patterns)) { patterns <- as.list(patterns) } for (p in patterns) { if (!inherits(p, "webfakes_regexp") && grepl(":", p)) { p <- path_to_regexp(p) } if (inherits(p, "webfakes_regexp")) { m <- re_match(path, p) if (m$match) return(list(params = as.list(m$groups))) } else { if (path == p) return(TRUE) } } FALSE } path_to_regexp <- function(path) { tokens <- strsplit(path, "/")[[1]] keys <- grep("^:", tokens) reg <- tokens reg[keys] <- paste0("(?<", substring(tokens[keys], 2), ">[-A-Za-z0-9_]+)") new_regexp(paste0("^", paste(reg, collapse = "/"), "$")) } webfakes/R/mw-etag.R0000644000176200001440000000214715026556433013743 0ustar liggesusers#' Middleware that add an `ETag` header to the response #' #' If the response already has an `ETag` header, then it is kept. #' #' This middleware handles the `If-None-Match` headers, and it sets the #' status code of the response to 304 if `If-None-Match` matches the #' `ETag`. It also removes the response body in this case. #' #' @param algorithm Checksum algorithm to use. Only `"crc32"` is #' implemented currently. #' #' @return Handler function. #' #' @family middleware #' @export #' @examples #' app <- new_app() #' app$use(mw_etag()) #' app mw_etag <- function(algorithm = "crc32") { if (algorithm != "crc32") { stop("Only the 'crc32' algorithm is implemented in `mw_etag()`") } function(req, res) { do <- function(req, res) { etag <- res$get_header("ETag") if (is.null(etag)) { etag <- paste0("\"", crc32(res$.body), "\"") res$set_header("ETag", etag) } req_etag <- req$get_header("If-None-Match") if (!is.null(req_etag) && req_etag == etag) { res$.body <- NULL res$set_status(304) } } res$on_response(do) "next" } } webfakes/R/base64.R0000644000176200001440000001015115026556433013460 0ustar liggesusersXX <- 255L EQ <- 254L INVALID <- XX index_64 <- as.integer(c( XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, 62, XX, XX, XX, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, XX, XX, XX, EQ, XX, XX, XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, XX, XX, XX, XX, XX, XX, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX )) base64_decode <- function(x) { if (is.character(x)) { x <- charToRaw(x) } len <- length(x) idx <- 1 c <- integer(4) out <- raw() while (idx <= len) { i <- 1 while (i <= 4) { uc <- index_64[[as.integer(x[[idx]]) + 1L]] idx <- idx + 1 if (uc != INVALID) { c[[i]] <- uc i <- i + 1 } if (idx > len) { if (i <= 4) { if (i <= 2) { return(rawToChar(out)) } if (i == 3) { c[[3]] <- EQ c[[4]] <- EQ } break } } } if (c[[1]] == EQ || c[[2]] == EQ) { break } #print(sprintf("c1=%d,c2=%d,c3=%d,c4=%d\n", c[1],c[2],c[3],c[4])) out[[length(out) + 1]] <- as.raw(bitwOr( bitwShiftL(c[[1]], 2L), bitwShiftR(bitwAnd(c[[2]], 0x30), 4L) )) if (c[[3]] == EQ) { break } out[[length(out) + 1]] <- as.raw(bitwOr( bitwShiftL(bitwAnd(c[[2]], 0x0F), 4L), bitwShiftR(bitwAnd(c[[3]], 0x3C), 2L) )) if (c[[4]] == EQ) { break } out[[length(out) + 1]] <- as.raw(bitwOr( bitwShiftL(bitwAnd(c[[3]], 0x03), 6L), c[[4]] )) } rawToChar(out) } basis64 <- charToRaw(paste(c(LETTERS, letters, 0:9, "+", "/"), collapse = "")) base64_encode <- function(x) { if (is.character(x)) { x <- charToRaw(x) } len <- length(x) rlen <- floor((len + 2L) / 3L) * 4L out <- raw(rlen) ip <- op <- 1L c <- integer(4) while (len > 0L) { c[[1]] <- as.integer(x[[ip]]) ip <- ip + 1L if (len > 1L) { c[[2]] <- as.integer(x[ip]) ip <- ip + 1L } else { c[[2]] <- 0L } out[op] <- basis64[1 + bitwShiftR(c[[1]], 2L)] op <- op + 1L out[op] <- basis64[ 1 + bitwOr( bitwShiftL(bitwAnd(c[[1]], 3L), 4L), bitwShiftR(bitwAnd(c[[2]], 240L), 4L) ) ] op <- op + 1L if (len > 2) { c[[3]] <- as.integer(x[ip]) ip <- ip + 1L out[op] <- basis64[ 1 + bitwOr( bitwShiftL(bitwAnd(c[[2]], 15L), 2L), bitwShiftR(bitwAnd(c[[3]], 192L), 6L) ) ] op <- op + 1L out[op] <- basis64[1 + bitwAnd(c[[3]], 63)] op <- op + 1L } else if (len == 2) { out[op] <- basis64[1 + bitwShiftL(bitwAnd(c[[2]], 15L), 2L)] op <- op + 1L out[op] <- charToRaw("=") op <- op + 1L } else { ## len == 1 out[op] <- charToRaw("=") op <- op + 1L out[op] <- charToRaw("=") op <- op + 1L } len <- len - 3L } rawToChar(out) } webfakes/R/compat-defer.R0000644000176200001440000000406515026556433014751 0ustar liggesusers# nocov start --- compat-defer --- 2020-06-16 # This drop-in file implements withr::defer(). Please find the most # recent version in withr's repository. defer <- function( expr, envir = parent.frame(), priority = c("first", "last") ) {} local({ defer <<- defer <- function( expr, envir = parent.frame(), priority = c("first", "last") ) { priority <- match.arg(priority) if (identical(envir, .GlobalEnv) && is.null(get_handlers(envir))) { message( "Setting deferred event(s) on global environment.\n", " * Execute (and clear) with `withr::deferred_run()`.\n", " * Clear (without executing) with `withr::deferred_clear()`." ) } invisible( add_handler( envir, handler = list(expr = substitute(expr), envir = parent.frame()), front = priority == "first" ) ) } get_handlers <- function(envir) { attr(envir, "handlers") } set_handlers <- function(envir, handlers) { has_handlers <- "handlers" %in% names(attributes(envir)) attr(envir, "handlers") <- handlers if (!has_handlers) { call <- make_call(execute_handlers, envir) # We have to use do.call here instead of eval because of the way on.exit # determines its evaluation context # (https://stat.ethz.ch/pipermail/r-devel/2013-November/067867.html) do.call(base::on.exit, list(call, TRUE), envir = envir) } } execute_handlers <- function(envir) { handlers <- get_handlers(envir) errors <- list() for (handler in handlers) { tryCatch(eval(handler$expr, handler$envir), error = function(e) { errors[[length(errors) + 1]] <<- e }) } for (error in errors) { stop(error) } } add_handler <- function(envir, handler, front) { if (front) { handlers <- c(list(handler), get_handlers(envir)) } else { handlers <- c(get_handlers(envir), list(handler)) } set_handlers(envir, handlers) handler } make_call <- function(...) { as.call(list(...)) } }) # defer() namespace # nocov end webfakes/R/mw-multipart.R0000644000176200001440000000742015026556433015043 0ustar liggesusers#' Parse a multipart HTTP request body #' #' Adds the parsed form fields in the `form` element of the request and #' the parsed files to the `files` element. #' #' @param type Content type to match before parsing. If it does not #' match, then the request object is not modified. #' @return Handler function. #' #' @family middleware #' @export #' @examples #' app <- new_app() #' app$use(mw_multipart()) #' app mw_multipart <- function(type = "multipart/form-data") { type function(req, res) { ct <- req$get_header("Content-Type") %||% "" if ( !any(vapply( paste0("^", type), function(x) grepl(x, ct), logical(1) )) ) { return("next") } parts <- str_trim(strsplit(ct, ";", fixed = TRUE)[[1]]) bnd <- grep("boundary=", parts, value = TRUE)[1] if (is.na(bnd)) { return("next") } bnd <- sub("^boundary=", "", bnd) tryCatch( { mp <- parse_multipart(req$.body, bnd) req$form <- list() req$files <- list() for (p in mp) { if (is.null(p$filename)) { req$form[[p$name]] <- rawToChar(p$value) } else { req$files[[p$name]] <- list(filename = p$filename, value = p$value) } } }, error = function(err) NULL ) "next" } } parse_multipart <- function(body, boundary) { boundary <- paste0("--", boundary) boundary_length <- nchar(boundary) # Find the locations of the boundary string indexes <- grepRaw(boundary, body, fixed = TRUE, all = TRUE) if (!length(indexes)) { stop("Boundary was not found in the body.") } if (length(indexes) == 1) { if (length(body) < (boundary_length + 5)) { # Empty HTML5 FormData object return(list()) } else { # Something went wrong stop( "The 'boundary' was only found once in the ", "multipart/form-data message. It should appear at ", "least twice. The request-body might be truncated." ) } } parts <- list() for (i in seq_along(utils::head(indexes, -1))) { from <- indexes[i] + boundary_length to <- indexes[i + 1] - 1 parts[[i]] <- body[from:to] } out <- lapply(parts, multipart_sub) names(out) <- vapply( out, function(x) as.character(x$name), character(1) ) out } multipart_sub <- function(bodydata) { splitchar <- grepRaw("\\r\\n\\r\\n|\\n\\n|\\r\\r", bodydata) if (!length(splitchar)) { stop("Invalid multipart subpart:\n\n", rawToChar(bodydata)) } headers <- bodydata[1:(splitchar - 1)] headers <- str_trim(rawToChar(headers)) headers <- gsub("\r\n", "\n", headers) headers <- gsub("\r", "\n", headers) headerlist <- unlist(lapply(strsplit(headers, "\n")[[1]], str_trim)) dispindex <- grep("^Content-Disposition:", headerlist) if (!length(dispindex)) { stop("Content-Disposition header not found:", headers) } dispheader <- headerlist[dispindex] #get parameter name m <- regexpr("; name=\\\"(.*?)\\\"", dispheader) if (m < 0) { stop('failed to find the name="..." header') } namefield <- unquote(sub( "; name=", "", regmatches(dispheader, m), fixed = TRUE )) #test for file upload m <- regexpr("; filename=\\\"(.*?)\\\"", dispheader) if (m < 0) { filenamefield = NULL } else { filenamefield <- unquote(sub( "; filename=", "", regmatches(dispheader, m), fixed = TRUE )) } #filedata splitval <- grepRaw("\\r\\n\\r\\n|\\n\\n|\\r\\r", bodydata, value = TRUE) start <- splitchar + length(splitval) if (identical(utils::tail(bodydata, 2), charToRaw("\r\n"))) { end <- length(bodydata) - 2 } else { end <- length(bodydata) - 1 } #the actual fields list( name = namefield, value = bodydata[start:end], filename = filenamefield ) } webfakes/R/tmpl-glue.R0000644000176200001440000000343115026556433014305 0ustar liggesusers#' glue based template engine #' #' Use this template engine to create pages with glue templates. #' See [glue::glue()] for the syntax. #' #' @param sep Separator used to separate elements. #' @param open The opening delimiter. Doubling the full delimiter escapes #' it. #' @param close The closing delimiter. Doubling the full delimiter escapes #' it. #' @param na Value to replace NA values with. If `NULL` missing values are #' propagated, that is an `NA` result will cause `NA` output. #' Otherwise the value is replaced by the value of `na`. #' @param transformer A function taking three parameters `code`, `envir` #' and `data` used to transform the output of each block before during or #' after evaluation. #' @param trim Whether to trim the input template with [glue::trim()] or not. #' @return Template function. #' #' @export #' @examples #' # See th 'hello' app at #' hello_root <- system.file(package = "webfakes", "examples", "hello") #' hello_root #' #' app <- new_app() #' app$engine("txt", tmpl_glue()) #' app$use(mw_log()) #' #' #' app$get("/view", function(req, res) { #' txt <- res$render("test") #' res$ #' set_type("text/plain")$ #' send(txt) #' }) #' #' # Switch to the app's root: setwd(hello_root) #' # Now start the app with: app$listen(3000L) #' # Or start it in another process: new_process(app) tmpl_glue <- function( sep = "", open = "{", close = "}", na = "NA", transformer = NULL, trim = TRUE ) { sep open close na transformer trim function(path, locals) { txt <- readChar(path, nchars = file.size(path)) glue::glue_data( locals, txt, .sep = sep, .open = open, .close = close, .na = na, .transformer = transformer %||% glue::identity_transformer, .trim = trim ) } } webfakes/R/webfakes-package.R0000644000176200001440000000013514370706367015561 0ustar liggesusers#' @keywords internal "_PACKAGE" ## usethis namespace: start ## usethis namespace: end NULL webfakes/R/mw-json.R0000644000176200001440000000173515026556433013776 0ustar liggesusers#' Middleware to parse a JSON body #' #' Adds the parsed object as the `json` element of the request object. #' #' @param type Content type to match before parsing. If it does not #' match, then the request object is not modified. #' @param simplifyVector Whether to simplify lists to vectors, passed to #' [jsonlite::fromJSON()]. #' @param ... Arguments to pass to [jsonlite::fromJSON()], that performs #' the JSON parsing. #' @return Handler function. #' #' @family middleware #' @export #' @examples #' app <- new_app() #' app$use(mw_json()) #' app mw_json <- function(type = "application/json", simplifyVector = FALSE, ...) { type simplifyVector list(...) function(req, res) { ct <- req$get_header("Content-Type") %||% "" if (!ct %in% tolower(type)) { return("next") } if (!is.null(req$.body)) { req$json <- jsonlite::fromJSON( rawToChar(req$.body), simplifyVector = simplifyVector, ... ) } "next" } } webfakes/R/mw-static.R0000644000176200001440000000244215026556433014310 0ustar liggesusers#' Middleware function to serve static files #' #' The content type of the response is set automatically from the #' extension of the file. Note that this is a terminal middleware #' handler function. If a file is served, then the rest of the handler #' functions will not be called. If a file was not found, however, #' the rest of the handlers are still called. #' #' @param root Root path of the served files. Everything under this #' directory is served automatically. Directory lists are not currently #' supports. #' @param set_headers Callback function to call before a file is served. #' @return Handler function. #' #' @family middleware #' @export #' @examples #' root <- system.file(package = "webfakes", "examples", "static", "public") #' app <- new_app() #' app$use(mw_static(root = root)) #' app mw_static <- function(root, set_headers = NULL) { root set_headers function(req, res) { path <- file.path(root, sub("^/", "", req$path)) if (!file.exists(path)) { return("next") } if (file.info(path)$isdir) { return("next") } ext <- tools::file_ext(basename(path)) ct <- mime_find(ext) if (!is.na(ct)) { res$set_header("Content-Type", ct) } if (!is.null(set_headers)) { set_headers(req, res) } res$send(read_bin(path)) } } webfakes/R/package.R0000644000176200001440000000010115026556433013761 0ustar liggesusers#' @useDynLib webfakes, .registration = TRUE, .fixes = "c_" NULL webfakes/R/mw-raw.R0000644000176200001440000000111515026556433013606 0ustar liggesusers#' Middleware to read the raw body of a request #' #' Adds the raw body, as a raw object to the `raw` field of the request. #' #' @param type Content type to match. If it does not match, then the #' request object is not modified. #' @return Handler function. #' #' @family middleware #' @export #' @examples #' app <- new_app() #' app$use(mw_raw()) #' app mw_raw <- function(type = "application/octet-stream") { function(req, res) { ct <- req$get_header("Content-Type") %||% "" if (!ct %in% tolower(type)) { return("next") } req$raw <- req$.body "next" } } webfakes/R/mw-text.R0000644000176200001440000000136515026556433014010 0ustar liggesusers#' Middleware to parse a plain text body #' #' Adds the parsed object as the `text` element of the request object. #' #' @param default_charset Encoding to set on the text. #' @param type Content type to match before parsing. If it does not #' match, then the request object is not modified. #' @return Handler function. #' #' @family middleware #' @export #' @examples #' app <- new_app() #' app$use(mw_text()) #' app mw_text <- function(default_charset = "utf-8", type = "text/plain") { default_charset type function(req, res) { ct <- req$get_header("Content-Type") %||% "" if (!ct %in% tolower(type)) { return("next") } req$text <- rawToChar(req$.body %||% raw()) Encoding(req$text) <- default_charset "next" } } webfakes/R/mw-log.R0000644000176200001440000000333015026556433013577 0ustar liggesusers#' Log requests to the standard output or other connection #' #' A one line log entry for every request. The output looks like this: #' ``` #' GET http://127.0.0.1:3000/image 200 3 ms - 4742 #' ``` #' and contains #' * the HTTP method, #' * the full request URL, #' * the HTTP status code of the response, #' * how long it took to process the response, in ms, #' * and the size of the response body, in bytes. #' #' @param format Log format. Not implemented currently. #' @param stream R connection to log to. `"stdout"` means the standard #' output, `"stderr"` is the standard error. You can also supply a #' connection object, but then you need to be sure that it will be #' valid when the app is actually running. #' @return Handler function. #' #' @family middleware #' @export #' @examples #' app <- new_app() #' app$use(mw_log()) #' app mw_log <- function(format = "dev", stream = "stdout") { format stream function(req, res) { start <- Sys.time() fmt <- function(req, res) { if (identical(stream, "stdout")) { stream <- stdout() } if (identical(stream, "stderr")) { stream <- stderr() } len <- if (is.null(res$.body)) { 0L # nocov } else if (is.raw(res$.body)) { length(res$.body) } else if (is_string(res$.body)) { nchar(res$.body, type = "bytes") } else { "??" # nocov } t <- as.integer(round((Sys.time() - start) * 1000)) msg <- sprintf( "%s %s %s %s ms - %s\n", toupper(req$method), req$url, res$.status, t, len ) cat0(msg, file = stream) if (inherits(stream, "connection")) flush(stream) } res$on_response(fmt) "next" } } webfakes/R/utils.R0000644000176200001440000000751415026556433013545 0ustar liggesusers`%||%` <- function(l, r) if (is.null(l)) r else l `%|NA|%` <- function(l, r) if (is_na_scalar(l)) r else l new_object <- function(class_name, ...) { structure(as.environment(list(...)), class = class_name) } is_string <- function(x) { is.character(x) && length(x) == 1 && !is.na(x) } is_integerish <- function(x) { is.integer(x) || (is.numeric(x) && all(round(x) == x)) } is_count <- function(x) { is_integerish(x) && length(x) == 1 && !is.na(x) } is_port <- function(x) { is_count(x) } is_na_scalar <- function(x) { is.atomic(x) && length(x) == 1 && is.na(x) } cat0 <- function(..., sep = "") { cat(..., sep = sep, append = TRUE) } str_trim <- function(x) { sub("\\s+$", "", sub("^\\s+", "", x)) } unquote <- function(str) { len <- nchar(str) if (substr(str, 1, 1) == '"' && substr(str, len, len) == '"') { substr(str, 2, len - 1) } else { str } } isFALSE <- function(x) { identical(x, FALSE) } str_is_suffix <- function(x, sfx) { lx <- nchar(x) lsfx <- nchar(sfx) substring(x, lx - lsfx + 1, lx) == sfx } read_char <- function(path, encoding = "UTF-8") { txt <- rawToChar(readBin(path, "raw", file.info(path)$size)) Encoding(txt) <- encoding txt } read_bin <- function(path) { readBin(path, "raw", file.info(path)$size) } try_silently <- function(expr) { try(expr, silent = TRUE) } sseq <- function(from, to) { if (from > to) integer() else seq(from, to) } is.named <- function(x) { length(names(x)) == length(x) && all(names(x) != "") } set_envvar <- function(envs) { if (length(envs) == 0) { return() } stopifnot(is.named(envs)) old <- Sys.getenv(names(envs), names = TRUE, unset = NA) set <- !is.na(envs) both_set <- set & !is.na(old) if (any(set)) { do.call("Sys.setenv", as.list(envs[set])) } if (any(!set)) { Sys.unsetenv(names(envs)[!set]) } invisible(old) } mkdirp <- function(path, ...) { dir.create(path, showWarnings = FALSE, recursive = TRUE, ...) } strrep <- function(x, no) { paste(rep(x, no), collapse = "") } set_name <- function(x, nm) { names(x) <- nm x } random_id <- generate_token <- function(n = 30) { paste0(sample(c(0:9, letters[1:6]), n, replace = TRUE), collapse = "") } parse_url <- function(url) { re_url <- paste0( "^(?[a-zA-Z0-9]+)://", "(?:(?[^@/:]+)(?::(?[^@/]+))?@)?", "(?[^/]+)", "(?.*)$" # don't worry about query params here... ) re_match(url, re_url)$groups } modify_path <- function(url, path) { purl <- parse_url(url) has_usr <- nzchar(purl$username) has_pwd <- nzchar(purl$password) paste0( purl$protocol, "://", purl$username, if (has_pwd) ":", purl$password, if (has_usr) "@", purl$host, if (substr(path, 1, 1) != "/") "/", path ) } has_seed <- function() { exists(".Random.seed", globalenv(), mode = "integer", inherits = FALSE) } get_seed <- function() { if (has_seed()) { get(".Random.seed", globalenv(), mode = "integer", inherits = FALSE) } } set_seed <- function(seed) { if (is.null(seed)) { rm(".Random.seed", envir = globalenv()) } else { assign(".Random.seed", seed, globalenv()) } } local_options <- function(.new = list(), ..., .local_envir = parent.frame()) { .new <- utils::modifyList(as.list(.new), list(...)) old <- do.call(options, .new) defer(do.call(options, old), .local_envir) } map_chr <- function(X, FUN, ...) { vapply(X, FUN, FUN.VALUE = character(1), ...) } #' Format a time stamp for HTTP #' #' @param t Date-time value to format, defaults to the current date and #' time. It must be a POSIXct object. #' @return Character vector, formatted date-time. #' @export http_time_stamp <- function(t = Sys.time()) { t <- as.POSIXlt(t, tz = "UTC") strftime(t, "%a, %d %b %Y %H:%M:%S GMT") } capitalize <- function(x) { substr(x, 1, 1) <- toupper(substr(x, 1, 1)) x } webfakes/R/mw-authorization.R0000644000176200001440000000441015026556433015716 0ustar liggesusersparse_authorization_header <- function(x) { if (length(x) == 0) { return(NULL) } scheme <- tolower(sub("[ ].*$", "", x)) rest <- trimws(sub("^[^ ]+[ ]", "", x)) if (scheme == "basic") { username <- password <- NULL tryCatch( { ptxt <- strsplit(base64_decode(rest), ":", fixed = TRUE)[[1]] if (length(ptxt) == 2) { username <- ptxt[1] password <- ptxt[2] } }, error = function(err) NULL ) if (!is.null(username) && !is.null(password)) { return(list( scheme = scheme, username = username, password = password )) } else { return(NULL) } } # if it has a (non-trailing) =, then it is a dictionary, otherwise token if (grepl("=", sub("=+$", "", rest))) { return(c(list(scheme = scheme), parse_dict_header(rest))) } list(scheme = scheme, token = rest) } parse_dict_header <- function(x) { result <- list() for (item in parse_list_header(x)) { if (!grepl("=", item)) { result[item] <- list(NULL) next } key <- sub("=.*$", "", item) value <- sub("^[^=]+=", "", item) # https://www.rfc-editor.org/rfc/rfc2231#section-4 # we always assume UTF-8 if (grepl("[*]$", key)) { key <- sub("[*]$", "", key) value <- sub("^.*'.*'", "", value) value <- utils::URLdecode(value) Encoding(value) <- "UTF-8" } if (grepl('^".*"$', value)) { value <- substr(value, 2, nchar(value) - 1L) } result[[key]] <- value } result } parse_list_header <- function(x) { s <- strsplit(x, "")[[1]] res <- character() part <- character() escape <- quote <- FALSE for (cur in s) { if (escape) { part[length(part) + 1L] <- cur escape <- FALSE next } if (quote) { if (cur == "\\") { escape <- TRUE next } else if (cur == '"') { quote <- FALSE } part[length(part) + 1L] <- cur next } if (cur == ",") { res[length(res) + 1L] <- paste(part, collapse = "") part <- character() next } if (cur == '"') { quote <- TRUE } part[length(part) + 1L] <- cur } if (length(part)) { res[length(res) + 1L] <- paste(part, collapse = "") } trimws(res) } webfakes/R/response.R0000644000176200001440000003423415026556433014242 0ustar liggesusers#' A webfakes response object #' #' webfakes creates a `webfakes_response` object for every incoming HTTP #' request. This object is passed to every matched route and middleware, #' until the HTTP response is sent. It has reference semantics, so handlers #' can modify it. #' #' Fields and methods: #' #' * `app`: The `webfakes_app` object itself. #' * `req`: The request object. #' * `headers_sent`: Whether the response headers were already sent out. #' * `locals`: Local variables, the are shared between the handler #' functions. This is for the end user, and not for the middlewares. #' * `delay(secs)`: delay the response for a number of seconds. If a #' handler calls `delay()`, the same handler will be called again, #' after the specified number of seconds have passed. Use the `locals` #' environment to distinguish between the calls. If you are using #' `delay()`, and want to serve requests in parallel, then you probably #' need a multi-threaded server, see [server_opts()]. #' * `add_header(field, value)`: Add a response header. Note that #' `add_header()` may create duplicate headers. You usually want #' `set_header()`. #' * `get_header(field)`: Query the currently set response headers. If #' `field` is not present it return `NULL`. #' * `on_response(fun)`: Run the `fun` handler function just before the #' response is sent out. At this point the headers and the body are #' already properly set. #' * `redirect(path, status = 302)`: Send a redirect response. It sets #' the `Location` header, and also sends a `text/plain` body. #' * `render(view, locals = list())`: Render a template page. Searches #' for the `view` template page, using all registered engine extensions, #' and calls the first matching template engine. Returns the filled #' template. #' * `send(body)`. Send the specified body. `body` can be a raw vector, #' or HTML or other text. For raw vectors it sets the content type to #' `application/octet-stream`. #' * `send_json(object = NULL, text = NULL, ...)`: Send a JSON response. #' Either `object` or `text` must be given. `object` will be converted #' to JSON using [jsonlite::toJSON()]. `...` are passed to #' [jsonlite::toJSON()]. It sets the content type appropriately. #' * `send_file(path, root = ".")`: Send a file. Set `root = "/"` for #' absolute file names. It sets the content type automatically, based #' on the extension of the file, if it is not set already. #' * `send_status(status)`: Send the specified HTTP status code, without #' a response body. #' * `send_chunk(data)`: Send a chunk of a response in chunked encoding. #' The first chunk will automatically send the HTTP response headers. #' Webfakes will automatically send a final zero-lengh chunk, unless #' `$delay()` is called. #' * `set_header(field, value)`: Set a response header. If the headers have #' been sent out already, then it throws a warning, and does nothing. #' * `set_status(status)`: Set the response status code. If the headers #' have been sent out already, then it throws a warning, and does nothing. #' * `set_type(type)`: Set the response content type. If it contains a `/` #' character then it is set as is, otherwise it is assumed to be a file #' extension, and the corresponding MIME type is set. If the headers have #' been sent out already, then it throws a warning, and does nothing. #' * `add_cookie(name, value, options)`: Adds a cookie to the response. #' `options` is a named list, and may contain: #' * `domain`: Domain name for the cookie, not set by default. #' * `expires`: Expiry date in GMT. It must be a POSIXct object, and #' will be formatted correctly. #' * 'http_only': if TRUE, then it sets the 'HttpOnly' attribute, so #' Javasctipt cannot access the cookie. #' * `max_age`: Maximum age, in number of seconds. #' * `path`: Path for the cookie, defaults to "/". #' * `same_site`: The 'SameSite' cookie attribute. Possible values are #' "strict", "lax" and "none". #' * `secure`: if TRUE, then it sets the 'Secure' attribute. #' * `clear_cookie(name, options = list())`: clears a cookie. Typically, #' web browsers will only clear a cookie if the options also match. #' * `write(data)`: writes (part of) the body of the response. It also #' sends out the response headers, if they haven't been sent out before. #' #' Usually you need one of the `send()` methods, to send out the HTTP #' response in one go, first the headers, then the body. #' #' Alternatively, you can use `$write()` to send the response in parts. #' #' @seealso [webfakes_request] for the webfakes request object. #' @name webfakes_response #' @examples #' # This is how you can see the request and response objects: #' app <- new_app() #' app$get("/", function(req, res) { #' browser() #' res$send("done") #' }) #' app #' #' # Now start this app on a port: #' # app$listen(3000) #' # and connect to it from a web browser: http://127.0.0.1:3000 #' # You can also use another R session to connect: #' # httr::GET("http://127.0.0.1:3000") #' # or the command line curl tool: #' # curl -v http://127.0.0.1:3000 #' # The app will stop while processing the request. NULL new_response <- function(app, req) { self <- new_object( "webfakes_response", app = app, req = req, locals = as.environment(as.list(app$locals)), headers_sent = FALSE, delay = function(secs) { self$.stackptr <- self$.i self$.delay <- secs response_delay(self$req, secs) invisible(NULL) }, get_header = function(field) { # this is case insensitive h <- self$.headers names(h) <- tolower(names(h)) h[[tolower(field)]] }, on_response = function(fun) { self$.on_response <- c(self$.on_response, list(fun)) invisible(self) }, redirect = function(path, status = 302) { if (self$.check_sent()) { return(invisible(self)) } self$set_status(status)$set_header("Location", path)$set_type( "text/plain" )$send(paste0( status, " ", http_statuses[as.character(status)], ". Redirecting to ", path )) invisible(self) }, render = function(view, locals = list()) { locals <- as.environment(as.list(locals)) parent.env(locals) <- self$locals root <- self$app$get_config("views") for (eng in self$app$.engines) { f <- file.path(root, paste0(view, ".", eng$ext)) if (file.exists(f)) return(eng$engine(f, locals)) } stop("Cannot find template engine for view '", view, "'") }, send = function(body) { if (self$.check_sent()) { return(invisible(self)) } # We need to do these here, on_response middleware might depend on it self$.body <- body self$.set_defaults() for (fn in self$.on_response) { fn(self$req, self) } response_send(self$req) self$headers_sent <- TRUE self$.sent <- TRUE invisible(self) }, send_chunk = function(data) { if (self$.check_sent()) { return(invisible(self)) } # The first chunk sends the headers automatically, but we make # sure to set chunked encoding if (!self$headers_sent) { self$set_header("Transfer-Encoding", "chunked") if (is.null(self$get_header("Content-Type"))) { self$set_header("Content-Type", "application/octet-stream") } if (is.null(self$.status)) { self$set_status(200L) } self$.set_defaults() } enc <- self$get_header("Transfer-Encoding") if (enc != "chunked") { warning("Headers sent, cannot set chunked encoding now") return(invisible(self)) } if (is.character(data)) { data <- charToRaw(paste(data, collapse = "\n")) } response_send_chunk(self$req, data) self$headers_sent <- TRUE invisible(self) }, send_json = function(object = NULL, text = NULL, ...) { if (!is.null(object) && !is.null(text)) { stop("Specify only one of `object` and `text` in `send_json()`") } if (is.null(text)) { text <- jsonlite::toJSON(object, ...) } self$set_header("Content-Type", "application/json")$send(text) }, send_file = function(path, root = ".") { # Set content type automatically if (is.null(self$get_header("Content-Type"))) { ext <- tools::file_ext(basename(path)) ct <- mime_find(ext) if (!is.na(ct)) { self$set_header("Content-Type", ct) } } if ( root == "/" && .Platform$OS.type == "windows" && grepl("^[a-zA-Z]:", path) ) { abs_path <- path } else { abs_path <- file.path(root, path) } self$send(read_bin(normalizePath(abs_path))) }, send_status = function(status) { self$set_status(status)$send("") }, set_header = function(field, value) { if (self$.check_sent()) { return(invisible(self)) } self$.headers[[field]] <- as.character(value) invisible(self) }, add_header = function(field, value) { if (self$.check_sent()) { return(invisible(self)) } h <- structure(list(value), names = field) self$.headers <- append(self$.headers, h) invisible(self) }, set_status = function(status) { if (self$.check_sent()) { return(invisible(self)) } self$.status <- as.integer(status) invisible(self) }, set_type = function(type) { if (self$.check_sent()) { return(invisible(self)) } if (grepl("/", type)) { self$set_header("Content-Type", type) } else { ct <- mime_find(type) if (!is.na(ct)) { self$set_header("Content-Type", ct) } } invisible(self) }, add_cookie = function(name, value, options = list()) { if (!is_string(name)) { stop("Cookie name must be a string.") } if (grepl("[=;]", name)) { stop("Cookie name cannot contain ';' and '=' characters.") } if (!is_string(value)) { stop("Cookie value must be a string.") } if (grepl("[=;]", value)) { stop("Cookie value cannot contain ';' and '=' characters.") } ck <- paste0( name, "=", value, "; ", format_cookie_options(options) ) self$add_header("Set-Cookie", ck) invisible(self) }, clear_cookie = function(name, options = list()) { if (!is_string(name)) { stop("Cookie name must be a string.") } if (grepl("[=;]", name)) { stop("Cookie name cannot contain ';' and '=' characters.") } options$expires <- .POSIXct(0) options$max_age <- 0L ck <- paste0(name, "=; ", format_cookie_options(options)) self$add_header("Set-Cookie", ck) invisible(self) }, write = function(data) { if (is.null(self$get_header("content-length"))) { warning("response$write() without a Content-Length header") } if (is.null(self$.status)) { self$set_status(200L) } if (is.character(data)) { data <- charToRaw(paste(data, collapse = "\n")) } response_write(self$req, data) self$headers_sent <- TRUE invisible(self) }, .check_sent = function() { if (isTRUE(self$.sent)) { warning("Response is sent already") } self$.sent }, .set_defaults = function() { if (is.null(self$.status)) { if (is.null(self$.body)) { # No status, no body, that's 404 self$.status <- 404L self$.body <- "Not found" } else { # No status, but body, set status self$.status <- 200L } } # Set Content-Type if not set if (is.null(self$get_header("Content-Type"))) { if (is.raw(self$body)) { ct <- "application/octet-stream" } else { ct <- "text/plain" } self$set_header("Content-Type", ct) } # Set Content-Length if not set if ( is.null(self$get_header("Content-Length")) && (self$get_header("Transfer-Encoding") %||% "") != "chunked" ) { if (is.raw(self$.body)) { cl <- length(self$.body) } else if (is.character(self$.body)) { cl <- nchar(self$.body, type = "bytes") } else if (is.null(self$.body)) { cl <- 0L } self$set_header("Content-Length", cl) } # Make sure response to HEAD has empty body if (self$req$method == "head") { self$.body <- raw(0) self$set_header("Content-Length", "0") } }, .body = NULL, .status = NULL, .headers = if (!app$.enable_keep_alive) { list("Connection" = "close") } else { list() }, .on_response = NULL, .sent = FALSE, .stackptr = 1L ) self } format_cookie_options <- function(options) { options$path <- options$path %||% "/" bad <- unique(setdiff( names(options), c( "domain", "expires", "http_only", "max_age", "path", "same_site", "secure" ) )) if (length(bad)) { stop( "Unknown or unsupported cookie attribute(s): ", paste0("\"", bad, "\"", collapse = ", "), "." ) } parts <- c( if (!is.null(options$domain)) { paste0("Domain=", options$domain) }, if (!is.null(options$expires)) { if (!inherits(options$expires, "POSIXct")) { stop("The 'expires' cookie attribute must be a POSIXct object") } paste0("Expires=", http_time_stamp(options$expires)) }, if (isTRUE(options$http_only)) { "HttpOnly" }, if (!is.null(options$max_age)) { paste0("Max-Age=", options$max_age) }, paste0("Path=", options$path), if (!is.null(options$same_site)) { if (tolower(!options$same_site) %in% c("strict", "lax", "none")) { stop( "Invalid value for 'SameSite' cookie atrribute: ", options$same_site, ", must be \"strict\", \"lax\" or \"none\"." ) } paste0("SameSite=", capitalize(options$same_site)) }, if (isTRUE(options$secure)) { "Secure" } ) paste(parts, collapse = "; ") } webfakes/R/status.R0000644000176200001440000000501615026556433013723 0ustar liggesusershttp_statuses <- c( "100" = "Continue", "101" = "Switching Protocols", "102" = "Processing (WebDAV; RFC 2518)", "200" = "OK", "201" = "Created", "202" = "Accepted", "203" = "Non-Authoritative Information", "204" = "No Content", "205" = "Reset Content", "206" = "Partial Content", "207" = "Multi-Status (WebDAV; RFC 4918)", "208" = "Already Reported (WebDAV; RFC 5842)", "226" = "IM Used (RFC 3229)", "300" = "Multiple Choices", "301" = "Moved Permanently", "302" = "Found", "303" = "See Other", "304" = "Not Modified", "305" = "Use Proxy", "306" = "Switch Proxy", "307" = "Temporary Redirect", "308" = "Permanent Redirect (experimental Internet-Draft)", "400" = "Bad Request", "401" = "Unauthorized", "402" = "Payment Required", "403" = "Forbidden", "404" = "Not Found", "405" = "Method Not Allowed", "406" = "Not Acceptable", "407" = "Proxy Authentication Required", "408" = "Request Timeout", "409" = "Conflict", "410" = "Gone", "411" = "Length Required", "412" = "Precondition Failed", "413" = "Request Entity Too Large", "414" = "Request-URI Too Long", "415" = "Unsupported Media Type", "416" = "Requested Range Not Satisfiable", "417" = "Expectation Failed", "418" = "I'm a teapot (RFC 2324)", "420" = "Enhance Your Calm (Twitter)", "422" = "Unprocessable Entity (WebDAV; RFC 4918)", "423" = "Locked (WebDAV; RFC 4918)", "424" = "Failed Dependency (WebDAV; RFC 4918)", "424" = "Method Failure (WebDAV)", "425" = "Unordered Collection (Internet draft)", "426" = "Upgrade Required (RFC 2817)", "428" = "Precondition Required (RFC 6585)", "429" = "Too Many Requests (RFC 6585)", "431" = "Request Header Fields Too Large (RFC 6585)", "444" = "No Response (Nginx)", "449" = "Retry With (Microsoft)", "450" = "Blocked by Windows Parental Controls (Microsoft)", "451" = "Unavailable For Legal Reasons (Internet draft)", "499" = "Client Closed Request (Nginx)", "500" = "Internal Server Error", "501" = "Not Implemented", "502" = "Bad Gateway", "503" = "Service Unavailable", "504" = "Gateway Timeout", "505" = "HTTP Version Not Supported", "506" = "Variant Also Negotiates (RFC 2295)", "507" = "Insufficient Storage (WebDAV; RFC 4918)", "508" = "Loop Detected (WebDAV; RFC 5842)", "509" = "Bandwidth Limit Exceeded (Apache bw/limited extension)", "510" = "Not Extended (RFC 2774)", "511" = "Network Authentication Required (RFC 6585)", "598" = "Network read timeout error (Unknown)", "599" = "Network connect timeout error (Unknown)" ) webfakes/R/oauth.R0000644000176200001440000005352015026556433013523 0ustar liggesusers#' Fake OAuth 2.0 resource and authorization app #' #' @includeRmd man/rmd-fragments/oauth2.Rmd description #' #' @details #' The app has the following endpoints: #' * `GET /register` is the endpoint that you can use to register #' your third party app. It needs to receive the `name` of the #' third party app, and its `redirect_uri` as query parameters, #' otherwise returns an HTTP 400 error. On success it returns a #' JSON dictionary with entries `name` (the name of the third party #' app), `client_id`, `client_secret` and `redirect_uri`. #' * `GET /authorize` is the endpoint where the user of the third #' party app is sent. You can change the URL of this endpoint with #' the `authorize_endpoint` argument. It needs to receive the `client_id` #' of the third party app, and its correct `redirect_uri` as query #' parameters. It may receive a `state` string as well, which can #' be used by a client to identify the request. Otherwise it #' generates a random `state` string. On error it fails with a HTTP #' 400 error. On success it returns a simple HTML login page. #' * `POST /authorize/decision` is the endpoint where the HTML login #' page generated at `/authorize` connects back to, either with a #' positive or negative result. The form on the login page will send #' the `state` string and the user's choice in the `action` variable. #' If the user authorized the third party app, then they are #' redirected to the `redirect_uri` of the app, with a temporary #' `code` and the `state` string supplied as query parameters. #' Otherwise a simple HTML page is returned. #' * `POST /token` is the endpoint where the third party app requests #' a temporary access token. It is also uses for refreshing an #' access token with a refresh token. You can change the URL of this #' endpoint with the `token_endpoint` argument. #' To request a new token or refresh an existing one, the following #' data must be included in either a JSON or an URL encoded request body: #' - `grant_type`, this must be `authorization_code` for new tokens, #' and `refresh_token` for refreshing. #' - `code`, this must be the temporary code obtained from the #' `/authorize/decision` redirection, for new tokens. It is not #' needed when refreshing. #' - `client_id` must be the client id of the third party app. #' - `client_secret` must be the client secret of the third party #' app. #' - `redirect_uri` must be the correct redirection URI of the #' third party app. It is not needed when refreshing tokens. #' - `refresh_token` must be the refresh token obtained previously, #' when refreshing a token. It is not needed for new tokens. #' On success a JSON dictionary is returned with entries: #' `access_token`, `expiry` and `refresh_token`. (The latter is #' omitted if the `refresh` argument is `FALSE`). #' * `GET /locals` returns a list of current apps, access tokens and #' refresh tokens. #' * `GET /data` is an endpoint that returns a simple JSON response, #' and needs authorization. #' #' ## Notes #' #' * Using this app in your tests requires the glue package, so you #' need to put it in `Suggests`. #' * You can add custom endpoints to the app, as needed. #' * If you need authorization in your custom endpoint, call #' `app$is_authorized()` in your handler: #' ``` #' if (!app$is_authorized(req, res)) return() #' ``` #' `app$is_authorized()` returns an HTTP 401 response if the #' client is not authorized, so you can simply return from your #' handler. #' #' For more details see `vignette("oauth", package = "webfakes")`. #' #' @section `oauth2_resource_app()`: #' App representing the API server (resource/authorization) #' @return a `webfakes` app #' @param access_duration After how many seconds should access tokens #' expire. #' @param refresh_duration After how many seconds should refresh #' tokens expire (ignored if `refresh` is `FALSE`). #' @param refresh Should a refresh token be returned (logical). #' @param seed Random seed used when creating tokens. If `NULL`, #' we rely on R to provide a seed. The app uses its own RNG stream, #' so it does not affect reproducibility of the tests. #' @param authorize_endpoint The authorization endpoint of the resource #' server. Change this from the default if the real app that you #' are faking does not use `/authorize`. #' @param token_endpoint The endpoint to request tokens. Change this if the #' real app that you are faking does not use `/token`. #' @return webfakes app #' #' @export #' @family OAuth2.0 functions oauth2_resource_app <- function( access_duration = 3600L, refresh_duration = 7200L, refresh = TRUE, seed = NULL, authorize_endpoint = "/authorize", token_endpoint = "/token" ) { access_duration refresh_duration refresh seed authorize_endpoint token_endpoint app <- new_app() app$locals$seed <- seed %||% get_seed() # Parse body for /authorize/decision, /token app$use(mw_urlencoded()) app$use(mw_json()) app$locals$tpapps <- data.frame( name = character(), client_id = character(), client_secret = character(), redirect_uri = character() ) app$set_config("views", system.file("views", package = "webfakes")) app$engine("html", tmpl_glue()) app$get("/register", function(req, res) { if (is.null(req$query$name) || is.null(req$query$redirect_uri)) { res$set_status(400L)$send( "Cannot register without 'name' and 'redirect_uri'" ) return() } rec <- list( name = req$query$name, client_id = paste0("id-", generate_token()), client_secret = paste0("secret-", generate_token()), redirect_uri = req$query$redirect_uri ) app$locals$tpapps <- rbind(app$locals$tpapps, rec) res$send_json(rec) }) app$get(authorize_endpoint, function(req, res) { # Missing or invalid client id client_id <- req$query$client_id if (is.null(client_id)) { res$set_status(400L)$send("Invalid authorization request, no client id") return() } else if (!client_id %in% app$locals$tpapps$client_id) { res$set_status(400L)$send( "Invalid authorization request, unknown client id" ) return() } tpapps <- app$locals$tpapps tprec <- tpapps[match(client_id, tpapps$client_id), ] # Bad redirect URL? if (req$query$redirect_uri %||% "" != tprec$redirect_uri) { res$set_status(400L)$send(paste0( "Invalid authorization request, redirect URL mismatch: ", req$query$redirect_uri %||% "", " vs ", tprec$redirect_uri )) return() } state <- req$query$state %||% generate_token() app$locals$states <- c(app$locals$states, set_name(client_id, state)) html <- res$render("authorize", list(state = state, app = tprec$name)) res$set_type("text/html")$send(html) }) app$post(paste0(authorize_endpoint, "/decision"), function(req, res) { state <- req$form$state if (is.null(state) || !state %in% names(app$locals$states)) { res$set_status(400L)$send("Invalid decision, no state") return() } client_id <- app$locals$states[state] tpapps <- app$locals$tpapps tprec <- tpapps[match(client_id, tpapps$client_id), ] app$local$states <- app$local$states[setdiff(names(app$local$states), state)] if (req$form$action %||% "" == "yes") { code <- generate_token() # TODO: make this app specific app$locals$codes <- c(app$locals$codes, code) red_uri <- paste0(tprec$redirect_uri, "?code=", code, "&state=", state) res$redirect(red_uri)$send() } else { res$send("Maybe next time.") } }) local_app_seed <- function(.local_envir = parent.frame()) { old_seed <- get_seed() set_seed(app$locals$seed) defer( { app$locals$seed <- get_seed() set_seed(old_seed) }, envir = .local_envir ) } new_access_token <- function(client_id, duration) { local_app_seed() token <- paste0("token-", generate_token()) new <- data.frame( stringsAsFactors = FALSE, client_id = client_id, token = token, expiry = Sys.time() + duration ) app$locals$tokens <- rbind(app$locals$tokens, new) token } new_refresh_token <- function(client_id, duration) { local_app_seed() token <- paste0("refresh-token-", generate_token()) new <- data.frame( stringsAsFactors = FALSE, client_id = client_id, token = token, expiry = Sys.time() + duration ) app$locals$refresh_tokens <- rbind(app$locals$refresh_tokens, new) token } expire_tokens <- function() { if (!is.null(app$locals$tokens)) { app$locals$tokens <- app$locals$tokens[ app$locals$tokens$expiry > Sys.time(), , drop = FALSE ] } if (!is.null(app$locals$refresh_tokens)) { app$locals$refresh_tokens <- app$locals$refresh_tokens[ app$locals$refresh_tokens$expiry > Sys.time(), , drop = FALSE ] } } is_valid_token <- function(token) { expire_tokens() token %in% app$locals$tokens$token } is_valid_refresh_token <- function(client_id, token) { expire_tokens() wh <- match(token, app$locals$refresh_tokens$token) if (is.na(wh)) { return(FALSE) } # client ID must match as well app$locals$refresh_tokens$client_id == client_id } # For refresh tokens app$post(token_endpoint, function(req, res) { if (req$form$grant_type != "refresh_token") { return("next") } client_id <- req$form$client_id tpapps <- app$locals$tpapps if (!client_id %in% tpapps$client_id) { res$set_status(400L)$send("Invalid client id") return() } tprec <- tpapps[match(client_id, tpapps$client_id), ] if (req$form$client_secret %||% "" != tprec$client_secret) { res$set_status(400L)$send("Invalid token request, client secret mismatch") return() } if (!is_valid_refresh_token(client_id, req$form$refresh_token)) { res$set_status(400L)$send_json( list(error = "invalid_request"), auto_unbox = TRUE ) return() } res$send_json( list( access_token = new_access_token(client_id, access_duration), expiry = access_duration, refresh_token = new_refresh_token(client_id, refresh_duration) ), auto_unbox = TRUE ) }) # For regular tokens app$post(token_endpoint, function(req, res) { if (req$form$grant_type %||% "" != "authorization_code") { res$set_status(400L)$send( "Invalid grant type, must be 'authorization_code'" ) return() } if (!req$form$code %in% app$locals$codes) { res$set_status(400L)$send("Unknown authorization code") return() } tpapps <- app$locals$tpapps client_id <- req$form$client_id if (!client_id %in% tpapps$client_id) { res$set_status(400L)$send("Invalid client id") return() } tprec <- tpapps[match(client_id, tpapps$client_id), ] if (req$form$client_secret %||% "" != tprec$client_secret) { res$set_status(400L)$send("Invalid token request, client secret mismatch") return() } if (req$form$redirect_uri %||% "" != tprec$redirect_uri) { res$set_status(400L)$send("Invalid token request, redirect URL mismatch") return() } app$locals$codes <- setdiff(app$locals$codes, req$query$code) res$send_json( list( access_token = new_access_token(client_id, access_duration), expiry = access_duration, refresh_token = if (refresh) { new_refresh_token(client_id, refresh_duration) } ), auto_unbox = TRUE, pretty = TRUE ) }) app$get("/locals", function(req, res) { res$set_status(200L)$send_json( list( apps = app$locals$tpapps, access = app$locals$tokens, refresh = app$locals$refresh_tokens ), auto_unbox = TRUE ) }) app$is_authorized <- function(req, res) { expire_tokens() if (!("Authorization" %in% names(req$headers))) { res$set_status(401L)$send("Missing bearer token") return(FALSE) } token <- gsub("Bearer ", "", req$headers$Authorization[[1]]) if (!is_valid_token(token)) { res$set_status(401L)$send("Invalid bearer token") return(FALSE) } TRUE } app$get("/data", function(req, res) { if (!app$is_authorized(req, res)) { return() } res$send_json(list(data = "top secret!")) }) app } #' App representing the third-party app #' #' @includeRmd man/rmd-fragments/oauth2.Rmd description #' #' @details #' Endpoints: #' * `POST /login/config` Use this endpoint to configure the client ID #' and the client secret of the app, received from #' [oauth2_resource_app()] (or another resource app). You need to #' send in a JSON or URL encoded body: #' - `auth_url`, the authorization URL of the resource app. #' - `token_url`, the token URL of the resource app. #' - `client_id`, the client ID, received from the resource app. #' - `client_secret` the client secret, received from the resource #' app. #' * `GET /login` Use this endpoint to start the login process. It #' will redirect to the resource app for authorization and after the #' OAuth2.0 dance to `/login/redirect`. #' * `GET /login/redirect`, `POST /login/redirect` This is the #' redirect URI of the third party app. (Some HTTP clients redirect #' a `POST` to a `GET`, others don't, so it has both.) This endpoint #' is used by the resource app, and it received the `code` that can #' be exchanged to an access token and the `state` which was #' generated in `/login`. It contacts the resource app to get an #' access token, and then stores the token in its `app$locals` #' local variables. It fails with HTTP code 500 if it cannot obtain #' an access token. On success it returns a JSON dictionary with #' `access_token`, `expiry` and `refresh_token` (optionally) by #' default. This behavior can be changed by redefining the #' `app$redirect_hook()` function. #' * `GET /locals` returns the tokens that were obtained from the #' resource app. #' * `GET /data` is an endpoint that uses the obtained token(s) to #' connect to the `/data` endpoint of the resource app. The `/data` #' endpoint of the resource app needs authorization. It responds #' with the response of the resource app. It tries to refresh the #' access token of the app if needed. #' #' For more details see `vignette("oauth", package = "webfakes")`. #' #' @param name Name of the third-party app #' @return webfakes app #' @export #' @family OAuth2.0 functions oauth2_third_party_app <- function(name = "Third-Party app") { app <- new_app() app$use(mw_urlencoded()) app$use(mw_json()) app$locals$auth_url <- NA_character_ app$locals$token_url <- NA_character_ app$locals$client_id <- NA_character_ app$locals$client_secret <- NA_character_ app$post("/login/config", function(req, res) { if ( is.null(req$json$auth_url) || is.null(req$json$token_url) || is.null(req$json$client_id) || is.null(req$json$client_secret) ) { res$set_status(400L)$send( "Need `client_id` and `client_secret` to config auth" ) return() } if (!is.na(app$locals$auth_url)) { res$set_status(400L)$send("Auth already configured") return() } app$locals$auth_url <- req$json$auth_url app$locals$token_url <- req$json$token_url app$locals$client_id <- req$json$client_id app$locals$client_secret <- req$json$client_secret res$send_json(list(response = "Authorization configured")) }) app$get("/login", function(req, res) { state <- generate_token() app$locals$state <- state url <- paste0( app$locals$auth_url, "?client_id=", app$locals$client_id, "&redirect_uri=", paste0(req$url, "/redirect"), "&state=", state ) res$redirect(url)$send() }) # I could not convince curl to redirect a POST to a GET, so both are good app$all("/login/redirect", function(req, res) { code <- req$query$code state <- req$query$state if (is.null(code) || is.null(state)) { res$set_status(400L)$send( "Invalid request via auth server, no 'code' or 'state'." ) return() } if (state != app$locals$state) { res$set_status(400L)$send("Unknown state in request via auth server") return() } # Get a token handle <- curl::new_handle() data <- charToRaw(paste0( "grant_type=authorization_code&", "code=", code, "&", "client_id=", app$locals$client_id, "&", "client_secret=", app$locals$client_secret, "&", "redirect_uri=", req$url )) curl::handle_setheaders( handle, "content-type" = "application/x-www-form-urlencoded" ) curl::handle_setopt( handle, customrequest = "POST", postfieldsize = length(data), postfields = data ) resp <- curl::curl_fetch_memory(app$locals$token_url, handle = handle) if (resp$status_code != 200L) { res$set_status(500L)$send(paste0( "Failed to acquire authorization token. ", rawToChar(resp$content) )) return() } tokens <- rawToChar(resp$content) app$locals$tokens <- jsonlite::fromJSON(tokens) app$redirect_hook(res, tokens) }) app$redirect_hook <- function(res, tokens) { res$send_json(text = tokens) } app$get("/locals", function(req, res) { res$set_status(200L)$send_json(app$locals$tokens, auto_unbox = TRUE) }) get_data <- function() { auth <- paste("Bearer", app$locals$tokens$access_token) handle <- curl::new_handle() curl::handle_setheaders(handle, Authorization = auth) url <- modify_path(app$locals$token_url, "/data") curl::curl_fetch_memory(url, handle = handle) } try_refresh <- function() { refresh_token <- app$locals$tokens$refresh_token if (is.null(refresh_token)) { return(FALSE) } data <- charToRaw(paste0( "refresh_token=", refresh_token, "&", "grant_type=refresh_token" )) handle <- curl::new_handle() curl::handle_setheaders( handle, "content-type" = "application/x-www-form-urlencoded" ) curl::handle_setopt( handle, customrequest = "POST", postfieldsize = length(data), postfields = data ) resp <- curl::curl_fetch_memory(app$locals$token_url, handle = handle) if (resp$status_code != 200L) { return(FALSE) } tokens <- rawToChar(resp$content) app$locals$tokens <- jsonlite::fromJSON(tokens) TRUE } app$get("/data", function(req, res) { resp <- get_data() if (resp$status_code == 401) { if (try_refresh()) resp <- get_data() } res$set_status(resp$status_code)$set_type(resp$type)$send(resp$content) }) } #' Helper function to log in to a third party OAuth2.0 app without a #' browser #' #' It works with [oauth2_resource_app()], and any third party app, #' including the fake [oauth2_third_party_app()]. #' #' See `test-oauth.R` in webfakes for an example. #' #' @param login_url The login URL of the third party app. #' @return A named list with #' * `login_response` The curl HTTP response object for the login #' page. #' * `token_response` The curl HTTP response object for submitting #' the login page. #' #' @family OAuth2.0 functions #' @export oauth2_login <- function(login_url) { login_resp <- curl::curl_fetch_memory(login_url) html <- rawToChar(login_resp$content) xml <- xml2::read_html(html) form <- xml2::xml_find_first(xml, "//form") input <- xml2::xml_find_first(form, "//input") actn <- xml2::xml_attr(form, "action") stnm <- xml2::xml_attr(input, "name") stvl <- xml2::xml_attr(input, "value") data <- charToRaw(paste0( stnm, "=", stvl, "&", "action=yes" )) handle2 <- curl::new_handle() curl::handle_setheaders( handle2, "content-type" = "application/x-www-form-urlencoded" ) curl::handle_setopt( handle2, customrequest = "POST", postfieldsize = length(data), postfields = data ) psurl <- parse_url(login_resp$url) actn_url <- paste0(psurl$protocol, "://", psurl$host, actn) token_resp <- curl::curl_fetch_memory(actn_url, handle = handle2) list( login_response = login_resp, token_response = token_resp ) } #' Helper function to use httr's OAuth2.0 functions #' non-interactively, e.g. in test cases #' #' To perform an automatic acknowledgement and log in for a #' local OAuth2.0 app, run by httr, wrap the expression that #' obtains the OAuth2.0 token in `oauth2_httr_login()`. #' #' In interactive sessions, `oauth2_httr_login()` overrides the #' `browser` option, and when httr opens a browser page, it #' calls [oauth2_login()] in a subprocess. #' #' In non-interactive sessions, httr does not open a browser page, #' only messages the user to do it manually. `oauth2_httr_login()` #' listens for these messages, and calls [oauth2_login()] in a #' subprocess. #' #' @param expr Expression that calls [httr::oauth2.0_token()], #' either directly, or indirectly. #' @return The return value of `expr`. #' #' @seealso See `?vignette("oauth", package = "webfakes")` for a case #' study that uses this function. #' #' @export #' @family OAuth2.0 functions oauth2_httr_login <- function(expr) { proc <- NULL if (interactive()) { local_options(browser = function(url) { proc <<- callr::r_bg( oauth2_login, list(url), package = "webfakes" ) }) expr } else { withCallingHandlers( expr, message = function(msg) { if ( grepl("^Please point your browser to the following url:", msg$message) ) { invokeRestart("muffleMessage") } if (grepl("^http", msg$message)) { proc <<- callr::r_bg( oauth2_login, list(trimws(msg$message)), package = "webfakes" ) invokeRestart("muffleMessage") } } ) } } webfakes/R/mw-cgi.R0000644000176200001440000001340615026556433013565 0ustar liggesusers#' Middleware that calls a CGI script #' #' You can use it as an unconditional middleware in `app$use()`, #' as a handler on `app$get()`, `app$post()`, etc., or you can call it #' from a handler. See examples below. #' #' @param command External command to run. #' @param args Arguments to pass to the external command. #' @param timeout Timeout for the external command. If the command does #' not terminate in time, the web server kills it and returns an 500 #' response. #' @return A function with signature #' ``` #' function(req, res, env = character()) #' ``` #' #' See [RFC 3875](https://datatracker.ietf.org/doc/html/rfc3875) #' for details on the CGI protocol. #' #' The request body (if any) is passed to the external command as standard #' intput. `mw_cgi()` sets `CONTENT_LENGTH`, `CONTENT_TYPE`, #' `GATEWAY_INTERFACE`, `PATH_INFO`, `QUERY_STRING`, `REMOTE_ADDR`, #' `REMOTE_HOST`, `REMOTE_USER`, `REQUEST_METHOD`, `SERVER_NAME`, #' `SERVER_PORT`, `SERVER_PROTOCOL`, `SERVER_SOFTEWARE`. #' #' It does not currently set the `AUTH_TYPE`, `PATH_TRANSLATED`, #' `REMOTE_IDENT`, `SCRIPT_NAME` environment variables. #' #' The standard output of the external command is used to set the #' response status code, the response headers and the response body. #' Example output from git's CGI: #' ``` #' Status: 200 OK #' Expires: Fri, 01 Jan 1980 00:00:00 GMT #' Pragma: no-cache #' Cache-Control: no-cache, max-age=0, must-revalidate #' Content-Type: application/x-git-upload-pack-advertisement #' #' 000eversion 2 #' 0015agent=git/2.42.0 #' 0013ls-refs=unborn #' 0020fetch=shallow wait-for-done #' 0012server-option #' 0017object-format=sha1 #' 0010object-info #' 0000 #' ``` #' #' @family middleware #' @export #' @examples #' app <- new_app() #' app$use(mw_cgi("echo", "Status: 200\n\nHello")) #' app #' #' app2 <- new_app() #' app2$get("/greet", mw_cgi("echo", "Status: 200\n\nHello")) #' app2 #' #' # Using `mw_cgi()` in a handler, you can pass extra environment variables #' app3 <- new_app() #' cgi <- mw_cgi("echo", "Status: 200\n\nHello") #' app2$get("/greet", function(req, res) { #' cgi(req, res, env = c("EXTRA_VAR" = "EXTRA_VALUE")) #' }) #' app3 mw_cgi <- function( command, args = character(), timeout = as.difftime(Inf, units = "secs") ) { command args timeout <- if (timeout == Inf) { -1 } else { as.double(timeout, units = "secs") * 1000 } function(req, res, env = character()) { all_env <- c("current", cgi_env(req), env) inp <- tempfile() out <- tempfile() err <- tempfile() on.exit(unlink(c(inp, out, err)), add = TRUE) writeBin(req$.body %||% raw(), inp) px <- processx::process$new( command, args, env = all_env, stdin = inp, stdout = out, stderr = err ) px$wait(timeout) output <- parse_cgi_output(px, out, err) res$set_status(output$status) for (idx in seq_along(output$headers)) { res$set_header(names(output$headers)[idx], output$headers[[idx]]) } res$send(output$body) } } parse_cgi_output <- function(px, out, err) { if (px$is_alive() || px$get_exit_status() != 0) { px$kill() err <- tryCatch(read_char(err), error = function(e) "???") return(list( status = 500L, headers = c("content-type" = "text/plain"), body = paste0("Internal git error: ", err) )) } out <- read_bin(out) err <- read_char(err) cgi_res <- split_cgi_output(out) headers <- cgi_res$headers names(headers) <- tolower(names(headers)) status <- parse_status(headers[["status"]] %||% "200") headers <- headers[names(headers) != "status"] list(status = status, headers = headers, body = cgi_res$body) } cgi_env <- function(req) { url <- parse_url(req$url) c( CONTENT_LENGTH = length(req$.body), CONTENT_TYPE = if (!is.null(req$get_header)) { req$get_header("content-type") %||% "" }, GATEWAY_INTERFACE = "CGI/1.1", PATH_INFO = req$path, QUERY_STRING = req$query_string, REMOTE_ADDR = req$remote_addr, REMOTE_HOST = req$remote_addr, REMOTE_USER = "anonymous", REQUEST_METHOD = toupper(req$method), SERVER_NAME = url$host, SERVER_PORT = url$port, SERVER_PROTOCOL = paste0("http/", req$http_version), SERVER_SOFTWARE = "https://github.com/r-lib/webfakes" ) } split_cgi_output <- function(x) { nlnl <- grepRaw("\r?\n\r?\n", x)[1] if (is.na(nlnl)) { stop("Invalid response from git cgi, no headers?") } headers <- parse_headers(rawToChar(x[1:(nlnl - 1L)])) body <- x[nlnl:length(x)] ndrop <- 1L while (body[ndrop] != 0x0a) { ndrop <- ndrop + 1L } ndrop <- ndrop + 1L while (body[ndrop] != 0x0a) { ndrop <- ndrop + 1L } body <- utils::tail(body, -ndrop) list(headers = headers, body = body) } parse_status <- function(x) { status <- as.integer(strsplit(x, " ", fixed = TRUE)[[1]][1]) if (is.na(status)) { stop("Invalid status from git cgi: ", x) } status } parse_headers <- function(txt) { headers <- grep(":", parse_headers0(txt), fixed = TRUE, value = TRUE) out <- lapply(headers, split_header) names <- tolower(vapply(out, `[[`, character(1), 1)) values <- lapply(lapply(out, `[[`, 2), trimws) names(values) <- names values } parse_headers0 <- function(txt, multiple = FALSE) { if (!length(txt)) { return(NULL) } if (is.raw(txt)) { txt <- rawToChar(txt) } stopifnot(is.character(txt)) if (length(txt) > 1) { txt <- paste(txt, collapse = "\n") } sets <- strsplit(txt, "\\r\\n\\r\\n|\\n\\n|\\r\\r")[[1]] headers <- strsplit(sets, "\\r\\n|\\n|\\r") if (multiple) { headers } else { headers[[length(headers)]] } } split_header <- function(x) { pos <- grepRaw(":", x, fixed = TRUE)[1] if (is.na(pos)) { stop("Invalid response header from git cgi: ", x) } c(substr(x, 1, pos - 1L), substr(x, pos + 1L, nchar(x))) } webfakes/R/mw-urlencoded.R0000644000176200001440000000133715026556433015147 0ustar liggesusers#' Middleware to parse an url-encoded request body #' #' This is typically data from a form. The parsed data is added #' as the `form` element of the request object. #' #' @param type Content type to match before parsing. If it does not #' match, then the request object is not modified. #' @return Handler function. #' #' @family middleware #' @export #' @examples #' app <- new_app() #' app$use(mw_urlencoded()) #' app mw_urlencoded <- function(type = "application/x-www-form-urlencoded") { function(req, res) { ct <- req$get_header("Content-Type") %||% "" if (!ct %in% tolower(type)) { return("next") } if (!is.null(req$.body)) { req$form <- parse_query(rawToChar(req$.body)) } "next" } } webfakes/R/request.R0000644000176200001440000000532415026556433014072 0ustar liggesusers#' A webfakes request object #' #' webfakes creates a `webfakes_request` object for every incoming HTTP #' request. This object is passed to every matched route and middleware, #' until the response is sent. It has reference semantics, so handlers #' can modify it. #' #' Fields and methods: #' #' * `app`: The `webfakes_app` object itself. #' * `headers`: Named list of HTTP request headers. #' * `hostname`: The Host header, the server hostname and maybe port. #' * `method`: HTTP method. #' * `path`: Server path. #' * `protocol`: `"http"` or `"https"`. #' * `query_string`: The raw query string, without the starting `?`. #' * `query`: Parsed query parameters in a named list. #' * `remote_addr`: String, the domain name or IP address of the client. #' webfakes runs on the localhost, so this is `127.0.0.1`. #' * `url`: The full URL of the request. #' * `get_header(field)`: Function to query a request header. Returns #' `NULL` if the header is not present. #' #' Body parsing middleware adds additional fields to the request object. #' See [mw_raw()], [mw_text()], [mw_json()], [mw_multipart()] and #' [mw_urlencoded()]. #' #' @seealso [webfakes_response] for the webfakes response object. #' @name webfakes_request #' @examples #' # This is how you can see the request and response objects: #' app <- new_app() #' app$get("/", function(req, res) { #' browser() #' res$send("done") #' }) #' app #' #' # Now start this app on a port: #' # app$listen(3000) #' # and connect to it from a web browser: http://127.0.0.1:3000 #' # You can also use another R session to connect: #' # httr::GET("http://127.0.0.1:3000") #' # or the command line curl tool: #' # curl -v http://127.0.0.1:3000 #' # The app will stop while processing the request. NULL new_request <- function(app, self) { if (isTRUE(self$.has_methods)) { return(self) } parsed_headers <- self$headers self$.has_methods <- TRUE self$app <- app self$headers <- parsed_headers self$hostname <- parsed_headers$host self$method <- tolower(self$method) self$protocol <- "http" self$query = parse_query(self$query_string) self$get_header <- function(field) { h <- self$headers names(h) <- tolower(names(h)) h[[tolower(field)]] } rm(parsed_headers) self$res <- new_response(app, self) class(self) <- c("webfakes_request", class(self)) self } parse_query <- function(query) { query <- sub("^[?]", "", query) query <- chartr("+", " ", query) argstr <- strsplit(query, "&", fixed = TRUE)[[1]] argstr <- strsplit(argstr, "=", fixed = TRUE) keys <- vapply(argstr, function(x) utils::URLdecode(x[[1]]), character(1)) vals <- lapply(argstr, function(x) { if (length(x) == 2) utils::URLdecode(x[[2]]) else "" }) structure(vals, names = keys) } webfakes/R/mime.R0000644000176200001440000002500615026556433013330 0ustar liggesusersmime_find <- function(ext) { stopifnot(is_string(ext)) m <- mime_types[ext] if (is.na(m)) { ew <- str_is_suffix(ext, names(mime_types_sfx)) m <- mime_types_sfx[ew] } c(m, NA_character_)[1] } mime_types_sfx <- c( `3gpp` = "audio/3gpp", `jpm` = "video/jpm", `mp3` = "audio/mp3", `rtf` = "text/rtf", `wav` = "audio/wave", `x3db` = "model/x3d+binary", `x3dv` = "model/x3d+vrml", `xml` = "text/xml" ) mime_types <- c( `3g2` = "video/3gpp2", `3gp` = "video/3gpp", `3gpp` = "video/3gpp", `3mf` = "model/3mf", ac = "application/pkix-attr-cert", adp = "audio/adpcm", ai = "application/postscript", apng = "image/apng", appcache = "text/cache-manifest", asc = "application/pgp-signature", atom = "application/atom+xml", atomcat = "application/atomcat+xml", atomsvc = "application/atomsvc+xml", au = "audio/basic", aw = "application/applixware", bdoc = "application/bdoc", bin = "application/octet-stream", bmp = "image/bmp", bpk = "application/octet-stream", buffer = "application/octet-stream", ccxml = "application/ccxml+xml", cdmia = "application/cdmi-capability", cdmic = "application/cdmi-container", cdmid = "application/cdmi-domain", cdmio = "application/cdmi-object", cdmiq = "application/cdmi-queue", cer = "application/pkix-cert", cgm = "image/cgm", class = "application/java-vm", coffee = "text/coffeescript", conf = "text/plain", cpt = "application/mac-compactpro", crl = "application/pkix-crl", css = "text/css", csv = "text/csv", cu = "application/cu-seeme", davmount = "application/davmount+xml", dbk = "application/docbook+xml", deb = "application/octet-stream", def = "text/plain", deploy = "application/octet-stream", `disposition-notification` = "message/disposition-notification", dist = "application/octet-stream", distz = "application/octet-stream", dll = "application/octet-stream", dmg = "application/octet-stream", dms = "application/octet-stream", doc = "application/msword", dot = "application/msword", drle = "image/dicom-rle", dssc = "application/dssc+der", dtd = "application/xml-dtd", dump = "application/octet-stream", ear = "application/java-archive", ecma = "application/ecmascript", elc = "application/octet-stream", emf = "image/emf", eml = "message/rfc822", emma = "application/emma+xml", eps = "application/postscript", epub = "application/epub+zip", es = "application/ecmascript", exe = "application/octet-stream", exi = "application/exi", exr = "image/aces", ez = "application/andrew-inset", fits = "image/fits", g3 = "image/g3fax", gbr = "application/rpki-ghostbusters", geojson = "application/geo+json", gif = "image/gif", glb = "model/gltf-binary", gltf = "model/gltf+json", gml = "application/gml+xml", gpx = "application/gpx+xml", gram = "application/srgs", grxml = "application/srgs+xml", gxf = "application/gxf", gz = "application/gzip", h261 = "video/h261", h263 = "video/h263", h264 = "video/h264", heic = "image/heic", heics = "image/heic-sequence", heif = "image/heif", heifs = "image/heif-sequence", hjson = "application/hjson", hlp = "application/winhlp", hqx = "application/mac-binhex40", htm = "text/html", html = "text/html", ics = "text/calendar", ief = "image/ief", ifb = "text/calendar", iges = "model/iges", igs = "model/iges", img = "application/octet-stream", `in` = "text/plain", ini = "text/plain", ink = "application/inkml+xml", inkml = "application/inkml+xml", ipfix = "application/ipfix", iso = "application/octet-stream", jade = "text/jade", jar = "application/java-archive", jls = "image/jls", jp2 = "image/jp2", jpe = "image/jpeg", jpeg = "image/jpeg", jpf = "image/jpx", jpg = "image/jpeg", jpg2 = "image/jp2", jpgm = "video/jpm", jpgv = "video/jpeg", jpm = "image/jpm", jpx = "image/jpx", js = "application/javascript", json = "application/json", json5 = "application/json5", jsonld = "application/ld+json", jsonml = "application/jsonml+json", jsx = "text/jsx", jxr = "image/jxr", kar = "audio/midi", ktx = "image/ktx", less = "text/less", list = "text/plain", litcoffee = "text/coffeescript", log = "text/plain", lostxml = "application/lost+xml", lrf = "application/octet-stream", m1v = "video/mpeg", m21 = "application/mp21", m2a = "audio/mpeg", m2v = "video/mpeg", m3a = "audio/mpeg", m4a = "audio/mp4", m4p = "application/mp4", ma = "application/mathematica", mads = "application/mads+xml", man = "text/troff", manifest = "text/cache-manifest", map = "application/json", mar = "application/octet-stream", markdown = "text/markdown", mathml = "application/mathml+xml", mb = "application/mathematica", mbox = "application/mbox", md = "text/markdown", mdx = "text/mdx", me = "text/troff", mesh = "model/mesh", meta4 = "application/metalink4+xml", metalink = "application/metalink+xml", mets = "application/mets+xml", mft = "application/rpki-manifest", mid = "audio/midi", midi = "audio/midi", mime = "message/rfc822", mj2 = "video/mj2", mjp2 = "video/mj2", mjs = "application/javascript", mml = "text/mathml", mods = "application/mods+xml", mov = "video/quicktime", mp2 = "audio/mpeg", mp21 = "application/mp21", mp2a = "audio/mpeg", mp3 = "audio/mpeg", mp4 = "video/mp4", mp4a = "audio/mp4", mp4s = "application/mp4", mp4v = "video/mp4", mpd = "application/dash+xml", mpe = "video/mpeg", mpeg = "video/mpeg", mpg = "video/mpeg", mpg4 = "video/mp4", mpga = "audio/mpeg", mrc = "application/marc", mrcx = "application/marcxml+xml", ms = "text/troff", mscml = "application/mediaservercontrol+xml", msh = "model/mesh", msi = "application/octet-stream", msm = "application/octet-stream", msp = "application/octet-stream", mxf = "application/mxf", mxml = "application/xv+xml", n3 = "text/n3", nb = "application/mathematica", nq = "application/n-quads", nt = "application/n-triples", oda = "application/oda", oga = "audio/ogg", ogg = "audio/ogg", ogv = "video/ogg", ogx = "application/ogg", omdoc = "application/omdoc+xml", onepkg = "application/onenote", onetmp = "application/onenote", onetoc = "application/onenote", onetoc2 = "application/onenote", opf = "application/oebps-package+xml", otf = "font/otf", owl = "application/rdf+xml", oxps = "application/oxps", p10 = "application/pkcs10", p7c = "application/pkcs7-mime", p7m = "application/pkcs7-mime", p7s = "application/pkcs7-signature", p8 = "application/pkcs8", pdf = "application/pdf", pfr = "application/font-tdpfr", pgp = "application/pgp-encrypted", pkg = "application/octet-stream", pki = "application/pkixcmp", pkipath = "application/pkix-pkipath", pls = "application/pls+xml", png = "image/png", prf = "application/pics-rules", ps = "application/postscript", pskcxml = "application/pskc+xml", qt = "video/quicktime", raml = "application/raml+yaml", rdf = "application/rdf+xml", rif = "application/reginfo+xml", rl = "application/resource-lists+xml", rld = "application/resource-lists-diff+xml", rmi = "audio/midi", rnc = "application/relax-ng-compact-syntax", rng = "application/xml", roa = "application/rpki-roa", roff = "text/troff", rq = "application/sparql-query", rs = "application/rls-services+xml", rsd = "application/rsd+xml", rss = "application/rss+xml", rtf = "application/rtf", rtx = "text/richtext", s3m = "audio/s3m", sbml = "application/sbml+xml", scq = "application/scvp-cv-request", scs = "application/scvp-cv-response", sdp = "application/sdp", ser = "application/java-serialized-object", setpay = "application/set-payment-initiation", setreg = "application/set-registration-initiation", sgi = "image/sgi", sgm = "text/sgml", sgml = "text/sgml", shex = "text/shex", shf = "application/shf+xml", shtml = "text/html", sieve = "application/sieve", sig = "application/pgp-signature", sil = "audio/silk", silo = "model/mesh", siv = "application/sieve", slim = "text/slim", slm = "text/slim", smi = "application/smil+xml", smil = "application/smil+xml", snd = "audio/basic", so = "application/octet-stream", spp = "application/scvp-vp-response", spq = "application/scvp-vp-request", spx = "audio/ogg", sru = "application/sru+xml", srx = "application/sparql-results+xml", ssdl = "application/ssdl+xml", ssml = "application/ssml+xml", stk = "application/hyperstudio", stl = "model/stl", styl = "text/stylus", stylus = "text/stylus", svg = "image/svg+xml", svgz = "image/svg+xml", t = "text/troff", t38 = "image/t38", tei = "application/tei+xml", teicorpus = "application/tei+xml", text = "text/plain", tfi = "application/thraud+xml", tfx = "image/tiff-fx", tif = "image/tiff", tiff = "image/tiff", tr = "text/troff", ts = "video/mp2t", tsd = "application/timestamped-data", tsv = "text/tab-separated-values", ttc = "font/collection", ttf = "font/ttf", ttl = "text/turtle", txt = "text/plain", u8dsn = "message/global-delivery-status", u8hdr = "message/global-headers", u8mdn = "message/global-disposition-notification", u8msg = "message/global", uri = "text/uri-list", uris = "text/uri-list", urls = "text/uri-list", vcard = "text/vcard", vrml = "model/vrml", vtt = "text/vtt", vxml = "application/voicexml+xml", war = "application/java-archive", wasm = "application/wasm", wav = "audio/wav", weba = "audio/webm", webm = "video/webm", webmanifest = "application/manifest+json", webp = "image/webp", wgt = "application/widget", wmf = "image/wmf", woff = "font/woff", woff2 = "font/woff2", wrl = "model/vrml", wsdl = "application/wsdl+xml", wspolicy = "application/wspolicy+xml", x3d = "model/x3d+xml", x3db = "model/x3d+fastinfoset", x3dbz = "model/x3d+binary", x3dv = "model/x3d-vrml", x3dvz = "model/x3d+vrml", x3dz = "model/x3d+xml", xaml = "application/xaml+xml", xdf = "application/xcap-diff+xml", xdssc = "application/dssc+xml", xenc = "application/xenc+xml", xer = "application/patch-ops-error+xml", xht = "application/xhtml+xml", xhtml = "application/xhtml+xml", xhvml = "application/xv+xml", xm = "audio/xm", xml = "application/xml", xop = "application/xop+xml", xpl = "application/xproc+xml", xsd = "application/xml", xsl = "application/xml", xslt = "application/xslt+xml", xspf = "application/xspf+xml", xvm = "application/xv+xml", xvml = "application/xv+xml", yaml = "text/yaml", yang = "application/yang", yin = "application/yin+xml", yml = "text/yaml", zip = "application/zip" ) webfakes/R/git-app.R0000644000176200001440000000376115026556433013746 0ustar liggesusers#' Web app that acts as a git http server #' #' It is useful for tests that need an HTTP git server. #' #' @param git_root Path to the root of the directory tree to be served. #' @param git_cmd Command to call, by default it is `"git"`. It may also #' be a full path to git. #' @param git_timeout A `difftime` object, time limit for the git #' command. #' @param filter Whether to support the `filter` capability in the server. #' @param cleanup Whether to clean up `git_root` when the app is #' garbage collected. #' #' @export #' @examplesIf FALSE #' dir.create(tmp <- tempfile()) #' setwd(tmp) #' system("git clone --bare https://github.com/cran/crayon") #' system("git clone --bare https://github.com/cran/glue") #' app <- git_app(tmp) #' git <- new_app_process(app) #' system(paste("git ls-remote", git$url("/crayon"))) git_app <- function( git_root, git_cmd = "git", git_timeout = as.difftime(1, units = "mins"), filter = TRUE, cleanup = TRUE ) { app <- webfakes::new_app() app$locals$git_root <- git_root app$locals$git_timeout <- as.double(git_timeout, units = "secs") * 1000 app$locals$git_config <- tempfile() reg.finalizer(app, function(app0) unlink(app$locals$git_config), TRUE) writeLines( c( "[uploadpack]", paste0("\tallowFilter = ", if (isTRUE(filter)) "true" else "false") ), app$locals$git_config ) if (cleanup) { reg.finalizer( app, function(app) unlink(app$locals$git_root, recursive = TRUE), TRUE ) } cgi <- mw_cgi(git_cmd, "http-backend", timeout = git_timeout) handler <- function(req, res) { env <- c( GIT_CONFIG_GLOBAL = req$app$locals$git_config, GIT_HTTP_EXPORT_ALL = "true", GIT_PROJECT_ROOT = req$app$locals$git_root, GIT_PROTOCOL = req$get_header("Git-Protocol") %||% "", HTTP_GIT_PROTOCOL = req$get_header("Git-Protocol") %||% "" ) cgi(req, res, env = env) } re_all <- new_regexp("^(?.*)$") app$get(re_all, handler) app$post(re_all, handler) app } webfakes/R/docs.R0000644000176200001440000000073114740737023013325 0ustar liggesusers#' @title Happy HTTP testing with webfakes #' @name introduction #' @section Happy HTTP testing with webfakes: #' #' ```{r child = "vignettes/introduction.Rmd"} #' ``` NULL #' @title webfakes glossary #' @name glossary #' @section Webfakes glossary: #' #' ```{r child = "vignettes/glossary.Rmd"} #' ``` NULL #' @title How to use webfakes in your tests #' @name how-to #' @section How to use webfakes in your tests: #' #' ```{r child = "vignettes/how-to.Rmd"} #' ``` NULL webfakes/R/app.R0000644000176200001440000004476715026556433013200 0ustar liggesuserspkg_data <- new.env(parent = emptyenv()) #' Create a new web application #' #' @details #' The typical workflow of creating a web application is: #' #' 1. Create a `webfakes_app` object with `new_app()`. #' 1. Add middleware and/or routes to it. #' 1. Start is with the `webfakes_app$listen()` method, or start it in #' another process with [new_app_process()]. #' 1. Make queries to the web app. #' 1. Stop it via `CTRL+C` / `ESC`, or, if it is running in another #' process, with the `$stop()` method of [new_app_process()]. #' #' A web application can be #' * restarted, #' * saved to disk, #' * copied to another process using the callr package, or a similar way, #' * embedded into a package, #' * extended by simply adding new routes and/or middleware. #' #' The webfakes API is very much influenced by the #' [express.js](https://expressjs.com/) project. #' #' ## Create web app objects #' #' ```r #' new_app() #' ``` #' #' `new_app()` returns a `webfakes_app` object the has the methods listed #' on this page. #' #' An app is an environment with S3 class `webfakes_app`. #' #' ## The handler stack #' #' An app has a stack of handlers. Each handler can be a route or #' middleware. The differences between the two are: #' * A route is bound to one or more paths on the web server. Middleware #' is not (currently) bound to paths, but run for all paths. #' * A route is usually (but not always) the end of the handler stack for #' a request. I.e. a route takes care of sending out the response to #' the request. Middleware typically performs some action on the request #' or the response, and then the next handler in the stack is invoked. #' #' ## Routes #' #' The following methods define routes. Each method corresponds to the #' HTTP verb with the same name, except for `app$all()`, which creates a #' route for all HTTP methods. #' #' ```r #' app$all(path, ...) #' app$delete(path, ...) #' app$get(path, ...) #' app$head(path, ...) #' app$patch(path, ...) #' app$post(path, ...) #' app$put(path, ...) #' ... (see list below) #' ``` #' #' * `path` is a path specification, see 'Path specification' below. #' * `...` is one or more handler functions. These will be placed in the #' handler stack, and called if they match an incoming HTTP request. #' See 'Handler functions' below. #' #' webfakes also has methods for the less frequently used HTTP verbs: #' `CONNECT`, `MKCOL`, `OPTIONS`, `PROPFIND`, `REPORT`. (The method #' names are always in lowercase.) #' #' If a request is not handled by any routes (or handler functions in #' general), then webfakes will send a simple HTTP 404 response. #' #' ## Middleware #' #' `app$use()` adds a middleware to the handler stack. A middleware is #' a handler function, see 'Handler functions' below. webfakes comes with #' middleware to perform common tasks: #' #' * [mw_cookie_parser()] parses `Cookie` headers. #' * [mw_etag()] adds an `ETag` header to the response. #' * [mw_json()] parses JSON request bodies. #' * [mw_log()] logs each requests to standard output, or another connection. #' * [mw_multipart()] parses multipart request bodies. #' * [mw_range_parser()] parses `Range` headers. #' * [mw_raw()] parses raw request bodies. #' * [mw_static()] serves static files from a directory. #' * [mw_text()] parses plain text request bodies. #' * [mw_urlencoded()] parses URL encoded request bodies. #' #' ```r #' app$use(..., .first = FALSE) #' ``` #' #' * `...` is a set of (middleware) handler functions. They are added to #' the handler stack, and called for every HTTP request. (Unless an HTTP #' response is created before reaching this point in the handler stack.) #' * `.first` set to `TRUE` is you want to add the handler function #' to the bottom of the stack. #' #' ## Handler functions #' #' A handler function is a route or middleware. A handler function is #' called by webfakes with the incoming HTTP request and the outgoing #' HTTP response objects (being built) as arguments. The handler function #' may query and modify the members of the request and/or the response #' object. If it returns the string `"next"`, then it is _not_ a terminal #' handler, and once it returns, webfakes will move on to call the next #' handler in the stack. #' #' A typical route: #' #' ```r #' app$get("/user/:id", function(req, res) { #' id <- req$params$id #' ... #' res$ #' set_status(200L)$ #' set_header("X-Custom-Header", "foobar")$ #' send_json(response, auto_unbox = TRUE) #' }) #' ``` #' #' * The handler belongs to an API path, which is a wildcard path in #' this case. It matches `/user/alice`, `/user/bob`, etc. The handler #' will be only called for GET methods and matching API paths. #' * The handler receives the request (`req`) and the response (`res`). #' * It sets the HTTP status, additional headers, and sends the data. #' (In this case the `webfakes_response$send_json()` method automatically #' converts `response` to JSON and sets the `Content-Type` and #' `Content-Length` headers. #' * This is a terminal handler, because it does _not_ return `"next"`. #' Once this handler function returns, webfakes will send out the HTTP #' response. #' #' A typical middleware: #' #' ```r #' app$use(function(req, res) { #' ... #' "next" #' }) #' ```` #' #' * There is no HTTP method and API path here, webfakes will call the #' handler for each HTTP request. #' * This is not a terminal handler, it does return `"next"`, so after it #' returns webfakes will look for the next handler in the stack. #' #' ## Errors #' #' If a handler function throws an error, then the web server will return #' a HTTP 500 `text/plain` response, with the error message as the #' response body. #' #' ## Request and response objects #' #' See [webfakes_request] and [webfakes_response] for the methods of the #' request and response objects. #' #' ## Path specification #' #' Routes are associated with one or more API paths. A path specification #' can be #' #' * A "plain" (i.e. without parameters) string. (E.g. `"/list"`.) #' * A parameterized string. (E.g. `"/user/:id"`.) #' * A regular expression created via [new_regexp()] function. #' * A list or character vector of the previous ones. (Regular expressions #' must be in a list.) #' #' ## Path parameters #' #' Paths that are specified as parameterized strings or regular expressions #' can have parameters. #' #' For parameterized strings the keys may contain letters, numbers and #' underscores. When webfakes matches an API path to a handler with a #' parameterized string path, the parameters will be added to the #' request, as `params`. I.e. in the handler function (and subsequent #' handler functions, if the current one is not terminal), they are #' available in the `req$params` list. #' #' For regular expressions, capture groups are also added as parameters. #' It is best to use named capture groups, so that the parameters are in #' a named list. #' #' If the path of the handler is a list of parameterized strings or #' regular expressions, the parameters are set according to the first #' matching one. #' #' ## Templates #' #' webfakes supports templates, using any template engine. It comes with #' a template engine that uses the glue package, see [tmpl_glue()]. #' #' `app$engine()` registers a template engine, for a certain file #' extension. The `$render()` method of [webfakes_response] #' can be called from the handler function to evaluate a template from a #' file. #' #' ```r #' app$engine(ext, engine) #' ``` #' #' * `ext`: the file extension for which the template engine is added. #' It should not contain the dot. E.g. `"html"', `"brew"`. #' * `engine`: the template engine, a function that takes the file path #' (`path`) of the template, and a list of local variables (`locals`) #' that can be used in the template. It should return the result. #' #' An example template engine that uses glue might look like this: #' #' ```r #' app$engine("txt", function(path, locals) { #' txt <- readChar(path, nchars = file.size(path)) #' glue::glue_data(locals, txt) #' }) #' ``` #' #' (The built-in [tmpl_glue()] engine has more features.) #' #' This template engine can be used in a handler: #' #' ```r #' app$get("/view", function(req, res) { #' txt <- res$render("test") #' res$ #' set_type("text/plain")$ #' send(txt) #' }) #' ``` #' #' The location of the templates can be set using the `views` configuration #' parameter, see the `$set_config()` method below. #' #' In the template, the variables passed in as `locals`, and also the #' response local variables (see `locals` in [webfakes_response]), are #' available. #' #' ## Starting and stopping #' #' ```r #' app$listen(port = NULL, opts = server_opts(), cleanup = TRUE) #' ``` #' #' * `port`: port to listen on. When `NULL`, the operating system will #' automatically select a free port. Add an `"s"` suffix to the port #' to use HTTPS. Use `"0s"` to use an OS assigned port with HTTPS. #' See the [how-to] manual page if you want to start the web server #' on more than one ports. #' #' * `opts`: options to the web server. See [server_opts()] for the #' list of options and their default values. #' #' * `cleanup`: stop the server (with an error) if the standard input #' of the process is closed. This is handy when the app runs in a #' `callr::r_session` subprocess, because it stops the app (and the #' subprocess) if the main process has terminated. #' #' This method does not return, and can be interrupted with `CTRL+C` / `ESC` #' or a SIGINT signal. See [new_app_process()] for interrupting an app that #' is running in another process. #' #' When `port` is `NULL`, the operating system chooses a port where the #' app will listen. To be able to get the port number programmatically, #' before the listen method blocks, it advertises the selected port in a #' `webfakes_port` condition, so one can catch it: #' #' webfakes by default binds only to the loopback interface at 127.0.0.1, so #' the webfakes web app is never reachable from the network. #' #' ```r #' withCallingHandlers( #' app$listen(), #' "webfakes_port" = function(msg) print(msg$port) #' ) #' ``` #' #' ## Logging #' #' webfakes can write an access log that contains an entry for all incoming #' requests, and also an error log for the errors that happen while #' the server is running. This is the default behavior for local app #' (the ones started by `app$listen()` and for remote apps (the ones #' started via `new_app_process()`: #' #' * Local apps do not write an access log by default. #' * Remote apps write an access log into the #' `/webfakes//access.log` file, where `` is the #' session temporary directory of the _main process_, and `` is #' the process id of the _subprocess_. #' * Local apps write an error log to `/webfakes/error.log`, where #' `` is the session temporary directory of the current process. #' * Remote app write an error log to the `/webfakes//error.log`, #' where `` is the session temporary directory of the #' _main process_ and `` is the process id of the _subprocess_`. #' #' See [server_opts()] for changing the default logging behavior. #' #' ## Shared app data #' #' ```r #' app$locals #' ``` #' #' It is often useful to share data between handlers and requests in an #' app. `app$locals` is an environment that supports this. E.g. a #' middleware that counts the number of requests can be implemented as: #' #' ``` #' app$use(function(req, res) { #' locals <- req$app$locals #' if (is.null(locals$num)) locals$num <- 0L #' locals$num <- locals$num + 1L #' "next" #' }) #' ``` #' #' [webfakes_response] objects also have a `locals` environment, that is #' initially populated as a copy of `app$locals`. #' #' ## Configuration #' #' ```r #' app$get_config(key) #' app$set_config(key, value) #' ``` #' #' * `key`: configuration key. #' * `value`: configuration value. #' #' Currently used configuration values: #' #' * `views`: path where webfakes searches for templates. #' #' @return A new `webfakes_app`. #' @aliases webfakes_app #' @seealso [webfakes_request] for request objects, [webfakes_response] for #' response objects. #' @export #' @examples #' # see example web apps in the `/examples` directory in #' system.file(package = "webfakes", "examples") #' #' app <- new_app() #' app$use(mw_log()) #' #' app$get("/hello", function(req, res) { #' res$send("Hello there!") #' }) #' #' app$get(new_regexp("^/hi(/.*)?$"), function(req, res) { #' res$send("Hi indeed!") #' }) #' #' app$post("/hello", function(req, res) { #' res$send("Got it, thanks!") #' }) #' #' app #' #' # Start the app with: app$listen() #' # Or start it in another R session: new_app_process(app) new_app <- function() { self <- new_object( "webfakes_app", all = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("all", path, ...)) invisible(self) }, connect = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("connect", path, ...)) invisible(self) }, delete = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("delete", path, ...)) invisible(self) }, get = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("get", path, ...)) invisible(self) }, engine = function(ext, engine) { rec <- list(ext = ext, engine = engine) self$.engines <- c(self$.engines, list(rec)) invisible(self) }, get_config = function(key) { self$.config[[key]] }, head = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("head", path, ...)) invisible(self) }, listen = function(port = NULL, opts = server_opts(), cleanup = TRUE) { if (is_na_scalar(port)) { port <- NULL } opts$port <- port self$.enable_keep_alive <- opts$enable_keep_alive opts$access_log_file <- sub("%p", Sys.getpid(), opts$access_log_file) opts$error_log_file <- sub("%p", Sys.getpid(), opts$error_log_file) self$.opts <- opts tryCatch(srv <- server_start(opts), error = function(err) { err$message <- paste(sep = "\n", err$message, self$.get_error_log()) stop(err) }) self$.ports <- server_get_ports(srv) self$.port <- self$.ports$port[1] port_nums <- paste0( self$.ports$port, ifelse(self$.ports$ssl, " (SSL)", "") ) message( "Running webfakes web app on port", if (length(port_nums) > 1) "s " else " ", paste(port_nums, collapse = ", ") ) if (!is.na(opts$access_log_file)) { message("Access log file: ", opts$access_log_file) } if (!is.na(opts$error_log_file)) { message("Error log file: ", opts$error_log_file) } msg <- structure( list( ports = self$.ports, port = self$.port, access_log = attr(srv, "options")$access_log_file, error_log = attr(srv, "options")$error_log_file ), class = c("webfakes_port", "callr_message", "condition") ) message(msg) on.exit(server_stop(srv), add = TRUE) while (TRUE) { req <- server_poll(srv, cleanup) tryCatch( self$.process_request(req), error = function(err) { cat(as.character(err), file = stderr()) response_send_error(req, as.character(err), 500L) } ) } }, mkcol = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("mkcol", path, ...)) invisible(self) }, options = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("options", path, ...)) invisible(self) }, patch = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("patch", path, ...)) invisible(self) }, post = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("post", path, ...)) invisible(self) }, propfind = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("propfind", path, ...)) invisible(self) }, put = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("put", path, ...)) invisible(self) }, report = function(path, ...) { self$.stack <- c(self$.stack, parse_handlers("report", path, ...)) invisible(self) }, set_config = function(key, value) { self$.config[[key]] <- value invisible(self) }, use = function(..., .first = FALSE) { mw <- parse_handlers("use", "*", ...) if (.first) { self$.stack <- c(mw, self$.stack) } else { self$.stack <- c(self$.stack, mw) } invisible(self) }, # Public data to be used in handlers locals = new.env(parent = parent.frame()), # Private data .ports = NULL, .port = NULL, .enable_keep_alive = NULL, .opts = NULL, # middleware stack .stack = list(), # view engines .engines = list(), # config .config = as.environment(list( views = file.path(getwd(), "views") )), # The request processing function .process_request = function(req) { req <- new_request(self, req) res <- req$res res$.delay <- NULL tryCatch( { for (i in sseq(res$.stackptr, length(self$.stack))) { handler <- self$.stack[[i]] m <- path_match(req$method, req$path, handler) if (!isFALSE(m)) { res$.i <- i if (is.list(m)) { req$params <- m$params } out <- handler$handler(req, res) if (!identical(out, "next")) break } } if (!res$.sent && is.null(res$.delay)) { if (!res$headers_sent) { res$send_status(404) } else if ( (res$get_header("Transfer-Encoding") %||% "") == "chunked" ) { res$send_chunk(raw(0)) res$headers_sent <- TRUE res$send("") } else { res$send("") } } }, webfakes_error = function(err) {} ) }, .get_error_log = function() { if (!is.na(self$.opts$error_log_file)) { paste0("Error log:\n", read_char(self$.opts$error_log_file)) } } ) self } parse_handlers <- function(method, path, ...) { handlers <- list(...) ans <- list() for (h in seq_along(handlers)) { handler <- handlers[[h]] if (is.function(handler)) { rec <- list( method = method, path = path, handler = handler, name = names(handlers)[h] ) ans <- c(ans, list(rec)) } else { stop("Invalid webfakes handler") } } ans } webfakes/cleanup0000755000176200001440000000006015026563043013416 0ustar liggesusers#' !/usr/bin/env sh rm -f src/Makevars src/*.a webfakes/src/0000755000176200001440000000000015026563042012633 5ustar liggesuserswebfakes/src/errors.h0000644000176200001440000000342414172041777014332 0ustar liggesusers #ifndef R_THROW_ERROR_H #define R_THROW_ERROR_H #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif #ifdef _WIN32 #include #else #include #endif #include #define R_THROW_ERROR(...) \ r_throw_error(__func__, __FILE__, __LINE__, __VA_ARGS__) SEXP r_throw_error(const char *func, const char *filename, int line, const char *msg, ...); #ifdef _WIN32 #define R_THROW_SYSTEM_ERROR(...) \ r_throw_system_error(__func__, __FILE__, __LINE__, (-1), NULL, __VA_ARGS__) #define R_THROW_SYSTEM_ERROR_CODE(errorcode, ...) \ r_throw_system_error(__func__, __FILE__, __LINE__, (errorcode), NULL, __VA_ARGS__) SEXP r_throw_system_error(const char *func, const char *filename, int line, DWORD errorcode, const char *sysmsg, const char *msg, ...); SEXP r_throw_posix_error(const char *func, const char *filename, int line, int errorcode, const char *sysmsg, const char *msg, ...); #define R_THROW_POSIX_ERROR(...) \ r_throw_posix_error(__func__, __FILE__, __LINE__, errno, NULL, __VA_ARGS__) #define R_THROW_POSIX_ERROR_CODE(errorcode, ...) \ r_throw_posix_error(__func__, __FILE__, __LINE__, errorcode, NULL, __VA_ARGS__) #else #define R_THROW_SYSTEM_ERROR(...) \ r_throw_system_error(__func__, __FILE__, __LINE__, errno, NULL, __VA_ARGS__) #define R_THROW_SYSTEM_ERROR_CODE(errorcode, ...) \ r_throw_system_error(__func__, __FILE__, __LINE__, errorcode, NULL, __VA_ARGS__) SEXP r_throw_system_error(const char *func, const char *filename, int line, int errorcode, const char *sysmsg, const char *msg, ...); #endif #endif webfakes/src/rweb.c0000644000176200001440000007036614765664470013772 0ustar liggesusers #include #include #include #include "civetweb.h" #include "errors.h" #include "cleancall.h" #include #include #ifdef _WIN32 #include #else #include #include #endif /* --------------------------------------------------------------------- */ /* registration */ /* --------------------------------------------------------------------- */ SEXP server_start(SEXP options); SEXP server_poll(SEXP rsrv, SEXP clean); SEXP server_stop(SEXP rsrv); SEXP server_get_ports(SEXP rsrv); SEXP response_delay(SEXP req, SEXP secs); SEXP response_send_headers(SEXP req); SEXP response_send(SEXP req); SEXP response_write(SEXP req, SEXP data); SEXP response_send_error(SEXP req, SEXP message, SEXP status); SEXP response_send_chunk(SEXP req, SEXP data); SEXP webfakes_crc32(SEXP v); static const R_CallMethodDef callMethods[] = { CLEANCALL_METHOD_RECORD, /* server */ { "server_start", (DL_FUNC) &server_start, 1 }, { "server_poll", (DL_FUNC) &server_poll, 2 }, { "server_stop", (DL_FUNC) &server_stop, 1 }, { "server_get_ports", (DL_FUNC) &server_get_ports, 1 }, /* request/response/connection */ { "response_delay", (DL_FUNC) &response_delay, 2 }, { "response_send_headers", (DL_FUNC) &response_send_headers, 1 }, { "response_send", (DL_FUNC) &response_send, 1 }, { "response_write", (DL_FUNC) &response_write, 2 }, { "response_send_error", (DL_FUNC) &response_send_error, 3 }, { "response_send_chunk", (DL_FUNC) &response_send_chunk, 2 }, /* others */ { "webfakes_crc32", (DL_FUNC) &webfakes_crc32, 1 }, { NULL, NULL, 0 } }; void R_init_webfakes(DllInfo *dll) { R_registerRoutines(dll, NULL, callMethods, NULL, NULL); R_useDynamicSymbols(dll, FALSE); R_forceSymbols(dll, TRUE); cleancall_fns_dot_call = Rf_findVar(Rf_install(".Call"), R_BaseEnv); /* Once we require some features we need to check the return value. */ mg_init_library(0); } /* --------------------------------------------------------------------- */ /* for older macOS versions */ /* --------------------------------------------------------------------- */ #if defined(__MACH__) && defined(__APPLE__) #include #include #include #include /* It doesn't really matter what these are defined to, as long as they are defined */ #ifndef CLOCK_REALTIME #define CLOCK_REALTIME 0 #endif #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC 1 #endif static int webfakes_clock_gettime(int clk_id, struct timespec *t) { memset(t, 0, sizeof(*t)); if (clk_id == CLOCK_REALTIME) { struct timeval now; int rv = gettimeofday(&now, NULL); if (rv) { return rv; } t->tv_sec = now.tv_sec; t->tv_nsec = now.tv_usec * 1000; return 0; } else if (clk_id == CLOCK_MONOTONIC) { static uint64_t clock_start_time = 0; static mach_timebase_info_data_t timebase_ifo = {0, 0}; uint64_t now = mach_absolute_time(); if (clock_start_time == 0) { kern_return_t mach_status = mach_timebase_info(&timebase_ifo); /* appease "unused variable" warning for release builds */ (void)mach_status; clock_start_time = now; } now = (uint64_t)((double)(now - clock_start_time) * (double)timebase_ifo.numer / (double)timebase_ifo.denom); t->tv_sec = now / 1000000000; t->tv_nsec = now % 1000000000; return 0; } return -1; /* EINVAL - Clock ID is unknown */ } #else #define webfakes_clock_gettime(a,b) clock_gettime(a,b) #endif /* --------------------------------------------------------------------- */ /* internals */ /* --------------------------------------------------------------------- */ #ifdef _WIN32 int check_stdin(void) { HANDLE hnd = GetStdHandle(STD_INPUT_HANDLE); if (hnd == INVALID_HANDLE_VALUE) { R_THROW_SYSTEM_ERROR("Cannot get stdin handle"); } DWORD type = GetFileType(hnd); if (type != FILE_TYPE_PIPE) return 0; DWORD ret = WaitForSingleObject(hnd, 0); if (ret == WAIT_TIMEOUT) return 0; if (ret == WAIT_FAILED) R_THROW_SYSTEM_ERROR("Cannot poll stdin"); if (ret == WAIT_OBJECT_0) { DWORD avail; DWORD ret2 = PeekNamedPipe(hnd, NULL, 0, NULL, &avail, NULL); if (!ret2) { DWORD err = GetLastError(); if (err == ERROR_BROKEN_PIPE) return 1; R_THROW_SYSTEM_ERROR_CODE(err, "Cannot peek stdin pipe"); } } return 0; } #else int check_stdin(void) { static char buffer[4096]; struct pollfd pfd; pfd.fd = 0; pfd.events = POLLIN; pfd.revents = 0; int ret = poll(&pfd, 1, 0); if (ret == -1) R_THROW_SYSTEM_ERROR("Cannot poll stdin"); // Nothing happened on stdin, keep running if (ret == 0) return 0; // Event on stdin, if we cannot read, then it if EOF ssize_t num = read(0, buffer, 4096); if (num == -1) R_THROW_SYSTEM_ERROR("Cannot read from stdin"); if (num == 0) return 1; // Otherwise fine return 0; } #endif #define WEBFAKES_NOTHING 0 #define WEBFAKES_REQ 1 /* request just came it */ #define WEBFAKES_WAIT 2 /* waited a bit / wait a bit */ #define WEBFAKES_DONE 3 /* request is done */ struct server_user_data { SEXP requests; pthread_cond_t process_more; /* there is something to process */ pthread_cond_t process_less; /* we can process something */ pthread_mutex_t process_lock; struct mg_connection *nextconn; struct mg_server_port ports[4]; int num_ports; int shutdown; }; struct connection_user_data { pthread_cond_t finish_cond; /* can finish callback? */ pthread_mutex_t finish_lock; int main_todo; /* what should the main thread do? */ int req_todo; /* what shoudl the request thread do? */ double secs; /* how much should we wait? */ SEXP req; int id; }; SEXP webfakes_create_request(struct mg_connection *conn); #define PTHCHK(expr) if ((ret = expr)) { \ mg_cry(conn, "ERROR @ %s %s:%d", __func__, __FILE__, __LINE__); \ R_THROW_SYSTEM_ERROR_CODE( \ ret, "Cannot process webfakes web server requests"); \ } #define CHK(expr) if ((ret = expr) < 0) { \ mg_cry(conn, "ERROR @ %s %s:%d", __func__, __FILE__, __LINE__); \ R_THROW_ERROR("Cannot process webfakes web server requests"); \ } static R_INLINE SEXP new_env(void) { SEXP env; #if R_VERSION >= R_Version(4, 1, 0) PROTECT(env = R_NewEnv(R_EmptyEnv, 1, 29)); #else PROTECT(env = allocSExp(ENVSXP)); SET_FRAME(env, R_NilValue); SET_ENCLOS(env, R_EmptyEnv); SET_HASHTAB(env, R_NilValue); SET_ATTRIB(env, R_NilValue); #endif UNPROTECT(1); return env; } static void SEXP_to_char_vector(SEXP x, char*** vec) { int i, len = LENGTH(x); SEXP nms = PROTECT(getAttrib(x, R_NamesSymbol)); *vec = (char**) R_alloc(2 * len + 1, sizeof(char*)); for (i = 0; i < len; i++) { (*vec)[2 * i ] = (char*) CHAR(STRING_ELT(nms, i)); (*vec)[2 * i + 1] = (char*) CHAR(STRING_ELT(x, i)); } (*vec)[2 * len] = NULL; UNPROTECT(1); } static int ms_sleep(struct server_user_data* srv_data, int ms) { int tosleep = ms > 100 ? 100 : ms; while (tosleep > 0) { #ifdef _WIN32 Sleep(tosleep); #else usleep(tosleep * 1000); #endif if (srv_data->shutdown) return 1; ms -= tosleep; tosleep = ms > 100 ? 100 : ms; } return 0; } /* --------------------------------------------------------------------- */ /* civetweb callbacks */ /* --------------------------------------------------------------------- */ static int begin_request(struct mg_connection *conn) { #ifndef NDEBUG fprintf(stderr, "conn %p: starting\n", (void*) conn); #endif struct mg_context *ctx = mg_get_context(conn); struct server_user_data *srv_data = mg_get_user_data(ctx); if (srv_data->shutdown) return 1; struct connection_user_data conn_data = { PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, WEBFAKES_REQ, WEBFAKES_NOTHING, 0.0, R_NilValue, 0, }; mg_set_user_connection_data(conn, &conn_data); if (pthread_mutex_lock(&conn_data.finish_lock)) goto exit; while (1) { if (pthread_mutex_lock(&srv_data->process_lock)) goto exit; #ifndef NDEBUG fprintf(stderr, "conn %p: waiting for slot\n", (void*) conn); #endif while (srv_data->nextconn != NULL) { pthread_cond_wait(&srv_data->process_less, &srv_data->process_lock); } #ifndef NDEBUG fprintf(stderr, "conn %p: scheduled\n", (void*) conn); #endif srv_data->nextconn = conn; /* only used to pass it to the main thread */ if (srv_data->shutdown) goto exit; if (pthread_cond_signal(&srv_data->process_more)) goto exit; if (pthread_mutex_unlock(&srv_data->process_lock)) goto exit; /* Need to wait for the response... */ #ifndef NDEBUG fprintf(stderr, "conn %p: waiting for order\n", (void*) conn); #endif while (conn_data.req_todo == WEBFAKES_NOTHING) { if (pthread_cond_wait(&conn_data.finish_cond, &conn_data.finish_lock)) { goto exit; } } #ifndef NDEBUG fprintf(stderr, "conn %p: got order: %d\n", (void*) conn, conn_data.req_todo); #endif if (conn_data.req_todo == WEBFAKES_DONE) goto exit; if (conn_data.req_todo == WEBFAKES_WAIT) { #ifndef NDEBUG fprintf(stderr, "conn %p: sleeping\n", (void*) conn); #endif if (ms_sleep(srv_data, conn_data.secs * 1000)) goto exit; #ifndef NDEBUG fprintf(stderr, "conn %p: sleeping done\n", (void*) conn); #endif } if (srv_data->shutdown) goto exit; conn_data.main_todo = WEBFAKES_WAIT; conn_data.req_todo = WEBFAKES_NOTHING; } exit: #ifndef NDEBUG fprintf(stderr, "conn %p: good bye all\n", (void*) conn); #endif mg_set_user_connection_data(conn, NULL); pthread_mutex_unlock(&conn_data.finish_lock); pthread_mutex_destroy(&conn_data.finish_lock); pthread_cond_destroy(&conn_data.finish_cond); return 1; } /* --------------------------------------------------------------------- */ /* server */ /* --------------------------------------------------------------------- */ static int register_request(struct server_user_data *srv_data, SEXP req) { SEXP nextid = PROTECT(Rf_install("nextid")); int id = INTEGER(Rf_findVar(nextid, srv_data->requests))[0] + 1; SEXP xid = PROTECT(ScalarInteger(id)); Rf_defineVar(nextid, xid, srv_data->requests); SEXP cid = PROTECT(asChar(xid)); SEXP rname = PROTECT(Rf_installChar(cid)); Rf_defineVar(rname, req, srv_data->requests); UNPROTECT(4); return id; } static void deregister_request(struct server_user_data *srv_data, int id) { SEXP xid = PROTECT(ScalarInteger(id)); SEXP cid = PROTECT(asChar(xid)); SEXP rname = PROTECT(Rf_installChar(cid)); Rf_defineVar(rname, R_NilValue, srv_data->requests); UNPROTECT(3); } static void release_all_requests(SEXP requests) { SEXP nms = PROTECT(R_lsInternal3(requests, 1, 0)); int i, n = LENGTH(nms); for (i = 0; i < n; i++) { const char *nm = CHAR(STRING_ELT(nms, i)); if (!strcmp("nextid", nm)) continue; SEXP sym = PROTECT(Rf_installChar(STRING_ELT(nms, i))); SEXP req = Rf_findVar(sym, requests); if (!isNull(req)) { SEXP xconn = Rf_findVar(Rf_install(".xconn"), req); struct mg_connection *conn = R_ExternalPtrAddr(xconn); if (conn) { #ifndef NDEBUG fprintf(stderr, "conn %p: emergency cleanup\n", (void*) conn); #endif struct connection_user_data *conn_data = mg_get_user_connection_data(conn); struct mg_context *ctx = mg_get_context(conn); struct server_user_data *srv_data = mg_get_user_data(ctx); pthread_mutex_lock(&conn_data->finish_lock); conn_data->req_todo = WEBFAKES_DONE; conn_data->req = R_NilValue; pthread_cond_signal(&conn_data->finish_cond); pthread_mutex_unlock(&conn_data->finish_lock); pthread_cond_signal(&srv_data->process_less); } } UNPROTECT(1); } UNPROTECT(1); } static void webfakes_server_finalizer(SEXP server) { struct mg_context *ctx = R_ExternalPtrAddr(server); if (ctx == NULL) return; #ifndef NDEBUG fprintf(stderr, "serv %p: cleaning up\n", (void*) ctx); #endif R_ClearExternalPtr(server); struct server_user_data* srv_data = mg_get_user_data(ctx); srv_data->shutdown = 1; release_all_requests(srv_data->requests); #ifndef NDEBUG fprintf(stderr, "serv %p: waiting for worker threads\n", (void*) ctx); void *ctx_addr = ctx; #endif mg_stop(ctx); pthread_mutex_unlock(&srv_data->process_lock); pthread_mutex_destroy(&srv_data->process_lock); pthread_cond_destroy(&srv_data->process_more); pthread_cond_destroy(&srv_data->process_less); free(srv_data); #ifndef NDEBUG fprintf(stderr, "serv %p: that would be all for today\n", (void*) ctx_addr); #endif } SEXP server_start(SEXP options) { #ifndef NDEBUG fprintf(stderr, "creating new server\n"); #endif SEXP server = R_NilValue; struct server_user_data *srv_data = malloc(sizeof(struct server_user_data)); if (!srv_data) R_THROW_SYSTEM_ERROR("Cannot start webfakes server"); struct mg_context *ctx = NULL; int ret = 0; memset(srv_data, 0, sizeof(struct server_user_data)); srv_data->requests = PROTECT(new_env()); SEXP x1 = PROTECT(ScalarInteger(1)); Rf_defineVar(Rf_install("nextid"), x1, srv_data->requests); UNPROTECT(1); if ((ret = pthread_cond_init(&srv_data->process_more, NULL))) goto cleanup; if ((ret = pthread_cond_init(&srv_data->process_less, NULL))) goto cleanup; if ((ret = pthread_mutex_init(&srv_data->process_lock, NULL))) goto cleanup; char **coptions; SEXP_to_char_vector(options, &coptions); struct mg_callbacks callbacks; memset(&callbacks, 0, sizeof(callbacks)); callbacks.begin_request = begin_request; if ((ret = pthread_mutex_lock(&srv_data->process_lock))) goto cleanup; ctx = mg_start(&callbacks, srv_data, (const char **) coptions); if (ctx == NULL) goto cleanup; PROTECT(server = R_MakeExternalPtr(ctx, srv_data->requests, R_NilValue)); R_RegisterCFinalizer(server, webfakes_server_finalizer); #ifndef NDEBUG fprintf(stderr, "serv %p: hi everyone, ready to serve\n", (void*) ctx); #endif memset(srv_data->ports, 0, sizeof(srv_data->ports)); srv_data->num_ports = mg_get_server_ports( ctx, sizeof(srv_data->ports) / sizeof(struct mg_server_port), srv_data->ports ); if (srv_data->num_ports < 0) goto cleanup; UNPROTECT(2); return server; cleanup: #ifndef NDEBUG fprintf(stderr, "serv %p: failed to start new server\n", (void*) ctx); #endif /* This is unlocked in the finalizer, but that might be much later... */ if (ctx) mg_stop(ctx); pthread_mutex_unlock(&srv_data->process_lock); if (ret) { R_THROW_SYSTEM_ERROR_CODE(ret, "Cannot start webfakes web server"); } else { R_THROW_ERROR("Cannot start webfakes web server"); } /* Never reached */ return R_NilValue; } static void server_poll_cleanup(void *ptr) { #ifndef NDEBUG fprintf(stderr, "conn %p: oh-oh, forced cleanup\n", (void*) ptr); #endif struct mg_connection *conn = (struct mg_connection*) ptr; struct connection_user_data *conn_data = mg_get_user_connection_data(conn); struct mg_context *ctx = mg_get_context(conn); struct server_user_data *srv_data = mg_get_user_data(ctx); mg_cry(conn, "Cleaning up broken connection at %s:%d", __FILE__, __LINE__); pthread_mutex_lock(&conn_data->finish_lock); conn_data->req_todo = WEBFAKES_DONE; deregister_request(srv_data, conn_data->id); conn_data->req = R_NilValue; pthread_cond_signal(&conn_data->finish_cond); pthread_mutex_unlock(&conn_data->finish_lock); pthread_cond_signal(&srv_data->process_less); } SEXP server_poll(SEXP server, SEXP clean) { struct mg_context *ctx = R_ExternalPtrAddr(server); int cclean = LOGICAL(clean)[0]; #ifndef NDEBUG fprintf(stderr, "serv %p: polling\n", (void*) ctx); #endif if (ctx == NULL) R_THROW_ERROR("webfakes server has stopped already"); struct server_user_data *srv_data = mg_get_user_data(ctx); struct timespec limit; while (srv_data->nextconn == NULL) { webfakes_clock_gettime(CLOCK_REALTIME, &limit); limit.tv_nsec += 50 * 1000 * 1000; if (limit.tv_nsec >= 1000 * 1000 * 1000) { limit.tv_sec += 1; limit.tv_nsec %= 1000 * 1000 * 1000; } R_CheckUserInterrupt(); if (cclean && check_stdin()) R_THROW_ERROR("Cleaning up web server"); (void) pthread_cond_timedwait(&srv_data->process_more, &srv_data->process_lock, &limit); } struct mg_connection *conn = srv_data->nextconn; srv_data->nextconn = NULL; struct connection_user_data *conn_data = mg_get_user_connection_data(conn); #ifndef NDEBUG fprintf(stderr, "serv %p: processing conn %p\n", (void*) ctx, (void*) conn); #endif SEXP req = R_NilValue; switch(conn_data->main_todo) { case WEBFAKES_REQ: r_call_on_early_exit(server_poll_cleanup, conn); req = webfakes_create_request(conn); break; case WEBFAKES_WAIT: req = conn_data->req; break; default: break; } #ifndef NDEBUG fprintf(stderr, "serv %p: returning request from conn %p\n", (void*) ctx, (void*) conn); #endif return req; } SEXP server_stop(SEXP server) { webfakes_server_finalizer(server); return R_NilValue; } SEXP server_get_ports(SEXP server) { struct mg_context *ctx = R_ExternalPtrAddr(server); if (ctx == NULL) R_THROW_ERROR("webfakes server has stopped already"); struct server_user_data *srv_data = mg_get_user_data(ctx); int i, num_ports = srv_data->num_ports; SEXP ipv4 = PROTECT(allocVector(LGLSXP, num_ports)); SEXP ipv6 = PROTECT(allocVector(LGLSXP, num_ports)); SEXP port = PROTECT(allocVector(INTSXP, num_ports)); SEXP ssl = PROTECT(allocVector(LGLSXP, num_ports)); const char *res_names[] = { "ipv4", "ipv6", "port", "ssl", "" }; SEXP res = PROTECT(Rf_mkNamed(VECSXP, res_names)); for (i = 0; i < num_ports; i++) { LOGICAL(ipv4)[i] = (srv_data->ports[i].protocol) & 1; LOGICAL(ipv6)[i] = (srv_data->ports[i].protocol) & 2; INTEGER(port)[i] = srv_data->ports[i].port; LOGICAL(ssl )[i] = srv_data->ports[i].is_ssl == 1; } SET_VECTOR_ELT(res, 0, ipv4); SET_VECTOR_ELT(res, 1, ipv6); SET_VECTOR_ELT(res, 2, port); SET_VECTOR_ELT(res, 3, ssl); UNPROTECT(5); return res; } /* --------------------------------------------------------------------- */ /* request */ /* --------------------------------------------------------------------- */ SEXP webfakes_create_request(struct mg_connection *conn) { static char request_link[8192]; int i; SEXP x; #ifndef NDEBUG fprintf(stderr, "conn %p: creating an R request object\n", (void*) conn); #endif const struct mg_request_info *req_info = mg_get_request_info(conn); SEXP req = PROTECT(new_env()); x = PROTECT(mkString(req_info->request_method)); defineVar(Rf_install("method"), x, req); UNPROTECT(1); mg_get_request_link(conn, request_link, sizeof(request_link)); x = PROTECT(mkString(request_link)); defineVar(Rf_install("url"), x, req); UNPROTECT(1); x = PROTECT(mkString(req_info->request_uri)); defineVar(Rf_install("request_uri"), x, req); UNPROTECT(1); x = PROTECT(mkString(req_info->local_uri)); defineVar(Rf_install("path"), x, req); UNPROTECT(1); x = PROTECT(mkString(req_info->http_version)); defineVar(Rf_install("http_version"), x, req); UNPROTECT(1); x = PROTECT(req_info->query_string ? mkString(req_info->query_string) : mkString("")); defineVar(Rf_install("query_string"), x, req); UNPROTECT(1); x = PROTECT(mkString(req_info->remote_addr)); defineVar(Rf_install("remote_addr"), x, req); UNPROTECT(1); x = PROTECT(ScalarReal(req_info->content_length)); defineVar(Rf_install("content_length"), x, req); UNPROTECT(1); x = PROTECT(ScalarInteger(req_info->remote_port)); defineVar(Rf_install("remote_port"), x, req); UNPROTECT(1); SEXP hdr = PROTECT(allocVector(VECSXP, req_info->num_headers)); SEXP nms = PROTECT(allocVector(STRSXP, req_info->num_headers)); for (i = 0; i < req_info->num_headers; i++) { SET_VECTOR_ELT(hdr, i, mkString(req_info->http_headers[i].value)); SET_STRING_ELT(nms, i, mkChar(req_info->http_headers[i].name)); } Rf_setAttrib(hdr, R_NamesSymbol, nms); defineVar(Rf_install("headers"), hdr, req); if (req_info->content_length != -1) { SEXP body = PROTECT(allocVector(RAWSXP, req_info->content_length)); int ret = mg_read(conn, RAW(body), req_info->content_length); if (ret < 0) { mg_cry(conn, "ERROR @ %s %s:%d", __func__, __FILE__, __LINE__); R_THROW_ERROR("Cannot read from webfakes HTTP client"); } if (ret != req_info->content_length) { warning("Partial HTTP request body from client"); } defineVar(Rf_install(".body"), body, req); UNPROTECT(1); } else { defineVar(Rf_install(".body"), R_NilValue, req); } SEXP xreq = PROTECT(R_MakeExternalPtr(conn, R_NilValue, R_NilValue)); defineVar(Rf_install(".xconn"), xreq, req); UNPROTECT(1); struct connection_user_data *conn_data = mg_get_user_connection_data(conn); conn_data->req = req; struct mg_context *ctx = mg_get_context(conn); struct server_user_data *srv_data = mg_get_user_data(ctx); conn_data->id = register_request(srv_data, req); UNPROTECT(3); return req; } static void response_cleanup(void *ptr) { struct mg_connection *conn = (struct mg_connection*) ptr; struct connection_user_data *conn_data = mg_get_user_connection_data(conn); struct mg_context *ctx = mg_get_context(conn); struct server_user_data *srv_data = mg_get_user_data(ctx); if (conn_data) { #ifndef NDEBUG fprintf(stderr, "conn %p: oh-oh, emergency cleanup\n", (void*) ptr); #endif mg_set_user_connection_data(conn, NULL); mg_cry(conn, "Cleaning up broken connection %p at %s:%d", (void*) conn, __FILE__, __LINE__); pthread_mutex_lock(&conn_data->finish_lock); conn_data->req_todo = WEBFAKES_DONE; deregister_request(srv_data, conn_data->id); SEXP req = conn_data->req; SEXP xconn = Rf_findVar(Rf_install(".xconn"), req); R_ClearExternalPtr(xconn); conn_data->req = R_NilValue; pthread_cond_signal(&conn_data->finish_cond); pthread_mutex_unlock(&conn_data->finish_lock); } pthread_cond_signal(&srv_data->process_less); } SEXP response_delay(SEXP req, SEXP secs) { SEXP xconn = Rf_findVar(Rf_install(".xconn"), req); struct mg_connection *conn = R_ExternalPtrAddr(xconn); if (conn == 0) { #ifndef NDEBUG fprintf(stderr, "?? a connection was cleaned up already\n"); return R_NilValue; #endif } struct mg_context *ctx = mg_get_context(conn); #ifndef NDEBUG fprintf(stderr, "serv %p: telling conn %p to delay\n", (void*) ctx, (void*) conn); #endif struct connection_user_data *conn_data = mg_get_user_connection_data(conn); int ret; r_call_on_early_exit(response_cleanup, conn); pthread_mutex_lock(&conn_data->finish_lock); conn_data->secs = REAL(secs)[0]; conn_data->req_todo = WEBFAKES_WAIT; PTHCHK(pthread_cond_signal(&conn_data->finish_cond)); PTHCHK(pthread_mutex_unlock(&conn_data->finish_lock)); struct server_user_data *srv_data = mg_get_user_data(ctx); #ifndef NDEBUG fprintf(stderr, "serv %p: inviting request threads\n", (void*) ctx); #endif PTHCHK(pthread_cond_signal(&srv_data->process_less)); return R_NilValue; } SEXP response_send_headers(SEXP req) { SEXP xconn = Rf_findVar(Rf_install(".xconn"), req); struct mg_connection *conn = R_ExternalPtrAddr(xconn); if (conn == 0) { #ifndef NDEBUG fprintf(stderr, "?? a connection was cleaned up already\n"); return R_NilValue; #endif } #ifndef NDEBUG fprintf(stderr, "conn %p: sending response headers\n", (void*) conn); #endif r_call_on_early_exit(response_cleanup, conn); SEXP http_version = PROTECT(Rf_findVar(Rf_install("http_version"), req)); SEXP res = PROTECT(Rf_findVar(Rf_install("res"), req)); SEXP headers = PROTECT(Rf_findVar(Rf_install(".headers"), res)); SEXP names = PROTECT(Rf_getAttrib(headers, R_NamesSymbol)); SEXP status = PROTECT(Rf_findVar(Rf_install(".status"), res)); int ret, i, nh = isNull(headers) ? 0 : LENGTH(headers); CHK(mg_printf(conn, "HTTP/%s %d %s\r\n", CHAR(STRING_ELT(http_version, 0)), INTEGER(status)[0], mg_get_response_code_text(conn, INTEGER(status)[0]))); for (i = 0; i < nh; i++) { const char *k = CHAR(STRING_ELT(names, i)); const char *v = CHAR(STRING_ELT(VECTOR_ELT(headers, i), 0)); CHK(mg_printf(conn, "%s: %s\r\n", k, v)); } CHK(mg_printf(conn, "\r\n")); #ifndef NDEBUG fprintf(stderr, "conn %p: response headers sent\n", (void*) conn); #endif UNPROTECT(5); return R_NilValue; } SEXP response_send(SEXP req) { SEXP xconn = Rf_findVar(Rf_install(".xconn"), req); struct mg_connection *conn = R_ExternalPtrAddr(xconn); if (conn == 0) { #ifndef NDEBUG fprintf(stderr, "?? a connection was cleaned up already\n"); return R_NilValue; #endif } #ifndef NDEBUG fprintf(stderr, "conn %p: sending response body\n", (void*) conn); #endif SEXP res = PROTECT(Rf_findVar(Rf_install("res"), req)); SEXP headers_sent = Rf_findVar(Rf_install("headers_sent"), res); if (! LOGICAL(headers_sent)[0]) response_send_headers(req); struct connection_user_data *conn_data = mg_get_user_connection_data(conn); r_call_on_early_exit(response_cleanup, conn); SEXP body = Rf_findVar(Rf_install(".body"), res); int ret; if (TYPEOF(body) == RAWSXP) { CHK(mg_write(conn, RAW(body), LENGTH(body))); } else if (TYPEOF(body) == STRSXP) { const char *cbody = CHAR(STRING_ELT(body, 0)); CHK(mg_write(conn, cbody, strlen(cbody))); } struct mg_context *ctx = mg_get_context(conn); struct server_user_data *srv_data = mg_get_user_data(ctx); #ifndef NDEBUG fprintf(stderr, "conn %p: response body sent\n", (void*) conn); #endif pthread_mutex_lock(&conn_data->finish_lock); conn_data->req_todo = WEBFAKES_DONE; deregister_request(srv_data, conn_data->id); conn_data->req = R_NilValue; #ifndef NDEBUG fprintf(stderr, "serv %p: telling conn %p to quit\n", (void*) ctx, (void*) conn); #endif PTHCHK(pthread_cond_signal(&conn_data->finish_cond)); PTHCHK(pthread_mutex_unlock(&conn_data->finish_lock)); #ifndef NDEBUG fprintf(stderr, "serv %p: inviting request threads\n", (void*) ctx); #endif PTHCHK(pthread_cond_signal(&srv_data->process_less)); UNPROTECT(1); return R_NilValue; } SEXP response_write(SEXP req, SEXP data) { SEXP res = PROTECT(Rf_findVar(Rf_install("res"), req)); SEXP headers_sent = PROTECT(Rf_findVar(Rf_install("headers_sent"), res)); if (! LOGICAL(headers_sent)[0]) response_send_headers(req); SEXP xconn = Rf_findVar(Rf_install(".xconn"), req); struct mg_connection *conn = R_ExternalPtrAddr(xconn); if (conn == 0) { #ifndef NDEBUG fprintf(stderr, "?? a connection was cleaned up already\n"); return R_NilValue; #endif } r_call_on_early_exit(response_cleanup, conn); int ret = 0; int len = LENGTH(data); #ifndef NDEBUG fprintf(stderr, "conn %p: writing %d bytes\n", (void*) conn, len); #endif CHK(mg_write(conn, RAW(data), len)); UNPROTECT(2); return R_NilValue; } SEXP response_send_chunk(SEXP req, SEXP data) { SEXP res = PROTECT(Rf_findVar(Rf_install("res"), req)); SEXP headers_sent = PROTECT(Rf_findVar(Rf_install("headers_sent"), res)); if (! LOGICAL(headers_sent)[0]) response_send_headers(req); SEXP xconn = Rf_findVar(Rf_install(".xconn"), req); struct mg_connection *conn = R_ExternalPtrAddr(xconn); if (conn == 0) { #ifndef NDEBUG fprintf(stderr, "?? a connection was cleaned up already\n"); return R_NilValue; #endif } r_call_on_early_exit(response_cleanup, conn); int ret = 0; int len = LENGTH(data); #ifndef NDEBUG fprintf(stderr, "conn %p: sending chunk of %d bytes\n", (void*) conn, len); #endif CHK(mg_send_chunk(conn, (const char*) RAW(data), len)); UNPROTECT(2); return R_NilValue; } SEXP response_send_error(SEXP req, SEXP message, SEXP status) { #ifndef NDEBUG fprintf(stderr, "sending 500 response"); #endif SEXP res = PROTECT(Rf_findVar(Rf_install("res"), req)); Rf_defineVar(Rf_install(".body"), message, res); Rf_defineVar(Rf_install(".status"), status, res); UNPROTECT(1); return response_send(req); } webfakes/src/timer.h0000644000176200001440000001631714740430263014134 0ustar liggesusers/* This file is part of the CivetWeb web server. * See https://github.com/civetweb/civetweb/ * (C) 2014-2021 by the CivetWeb authors, MIT license. */ #if !defined(MAX_TIMERS) #define MAX_TIMERS MAX_WORKER_THREADS #endif #if !defined(TIMER_RESOLUTION) /* Timer resolution in ms */ #define TIMER_RESOLUTION (10) #endif typedef int (*taction)(void *arg); typedef void (*tcancelaction)(void *arg); struct ttimer { double time; double period; taction action; void *arg; tcancelaction cancel; }; struct ttimers { pthread_t threadid; /* Timer thread ID */ pthread_mutex_t mutex; /* Protects timer lists */ struct ttimer *timers; /* List of timers */ unsigned timer_count; /* Current size of timer list */ unsigned timer_capacity; /* Capacity of timer list */ #if defined(_WIN32) DWORD last_tick; uint64_t now_tick64; #endif }; TIMER_API double timer_getcurrenttime(struct mg_context *ctx) { #if defined(_WIN32) /* GetTickCount returns milliseconds since system start as * unsigned 32 bit value. It will wrap around every 49.7 days. * We need to use a 64 bit counter (will wrap in 500 mio. years), * by adding the 32 bit difference since the last call to a * 64 bit counter. This algorithm will only work, if this * function is called at least once every 7 weeks. */ uint64_t now_tick64 = 0; DWORD now_tick = GetTickCount(); if (ctx->timers) { pthread_mutex_lock(&ctx->timers->mutex); ctx->timers->now_tick64 += now_tick - ctx->timers->last_tick; now_tick64 = ctx->timers->now_tick64; ctx->timers->last_tick = now_tick; pthread_mutex_unlock(&ctx->timers->mutex); } return (double)now_tick64 * 1.0E-3; #else struct timespec now_ts; (void)ctx; clock_gettime(CLOCK_MONOTONIC, &now_ts); return (double)now_ts.tv_sec + (double)now_ts.tv_nsec * 1.0E-9; #endif } TIMER_API int timer_add(struct mg_context *ctx, double next_time, double period, int is_relative, taction action, void *arg, tcancelaction cancel) { int error = 0; double now; if (!ctx->timers) { return 1; } now = timer_getcurrenttime(ctx); /* HCP24: if is_relative = 0 and next_time < now * action will be called so fast as possible * if additional period > 0 * action will be called so fast as possible * n times until (next_time + (n * period)) > now * then the period is working * Solution: * if next_time < now then we set next_time = now. * The first callback will be so fast as possible (now) * but the next callback on period */ if (is_relative) { next_time += now; } /* You can not set timers into the past */ if (next_time < now) { next_time = now; } pthread_mutex_lock(&ctx->timers->mutex); if (ctx->timers->timer_count == MAX_TIMERS) { error = 1; } else if (ctx->timers->timer_count == ctx->timers->timer_capacity) { unsigned capacity = (ctx->timers->timer_capacity * 2) + 1; struct ttimer *timers = (struct ttimer *)mg_realloc_ctx(ctx->timers->timers, capacity * sizeof(struct ttimer), ctx); if (timers) { ctx->timers->timers = timers; ctx->timers->timer_capacity = capacity; } else { error = 1; } } if (!error) { /* Insert new timer into a sorted list. */ /* The linear list is still most efficient for short lists (small * number of timers) - if there are many timers, different * algorithms will work better. */ unsigned u = ctx->timers->timer_count; for (; (u > 0) && (ctx->timers->timers[u - 1].time > next_time); u--) { ctx->timers->timers[u] = ctx->timers->timers[u - 1]; } ctx->timers->timers[u].time = next_time; ctx->timers->timers[u].period = period; ctx->timers->timers[u].action = action; ctx->timers->timers[u].arg = arg; ctx->timers->timers[u].cancel = cancel; ctx->timers->timer_count++; } pthread_mutex_unlock(&ctx->timers->mutex); return error; } static void timer_thread_run(void *thread_func_param) { struct mg_context *ctx = (struct mg_context *)thread_func_param; double d; unsigned u; int action_res; struct ttimer t; mg_set_thread_name("timer"); if (ctx->callbacks.init_thread) { /* Timer thread */ ctx->callbacks.init_thread(ctx, 2); } /* Timer main loop */ d = timer_getcurrenttime(ctx); while (STOP_FLAG_IS_ZERO(&ctx->stop_flag)) { pthread_mutex_lock(&ctx->timers->mutex); if ((ctx->timers->timer_count > 0) && (d >= ctx->timers->timers[0].time)) { /* Timer list is sorted. First action should run now. */ /* Store active timer in "t" */ t = ctx->timers->timers[0]; /* Shift all other timers */ for (u = 1; u < ctx->timers->timer_count; u++) { ctx->timers->timers[u - 1] = ctx->timers->timers[u]; } ctx->timers->timer_count--; pthread_mutex_unlock(&ctx->timers->mutex); /* Call timer action */ action_res = t.action(t.arg); /* action_res == 1: reschedule */ /* action_res == 0: do not reschedule, free(arg) */ if ((action_res > 0) && (t.period > 0)) { /* Should schedule timer again */ timer_add(ctx, t.time + t.period, t.period, 0, t.action, t.arg, t.cancel); } else { /* Allow user to free timer argument */ if (t.cancel != NULL) { t.cancel(t.arg); } } continue; } else { pthread_mutex_unlock(&ctx->timers->mutex); } /* TIMER_RESOLUTION = 10 ms seems reasonable. * A faster loop (smaller sleep value) increases CPU load, * a slower loop (higher sleep value) decreases timer accuracy. */ mg_sleep(TIMER_RESOLUTION); d = timer_getcurrenttime(ctx); } /* Remove remaining timers */ for (u = 0; u < ctx->timers->timer_count; u++) { t = ctx->timers->timers[u]; if (t.cancel != NULL) { t.cancel(t.arg); } } } #if defined(_WIN32) static unsigned __stdcall timer_thread(void *thread_func_param) { timer_thread_run(thread_func_param); return 0; } #else static void * timer_thread(void *thread_func_param) { struct sigaction sa; /* Ignore SIGPIPE */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); timer_thread_run(thread_func_param); return NULL; } #endif /* _WIN32 */ TIMER_API int timers_init(struct mg_context *ctx) { /* Initialize timers data structure */ ctx->timers = (struct ttimers *)mg_calloc_ctx(sizeof(struct ttimers), 1, ctx); if (!ctx->timers) { return -1; } ctx->timers->timers = NULL; /* Initialize mutex */ if (0 != pthread_mutex_init(&ctx->timers->mutex, NULL)) { mg_free(ctx->timers); ctx->timers = NULL; return -1; } /* For some systems timer_getcurrenttime does some initialization * during the first call. Call it once now, ignore the result. */ (void)timer_getcurrenttime(ctx); /* Start timer thread */ if (mg_start_thread_with_id(timer_thread, ctx, &ctx->timers->threadid) != 0) { (void)pthread_mutex_destroy(&ctx->timers->mutex); mg_free(ctx->timers); ctx->timers = NULL; return -1; } return 0; } TIMER_API void timers_exit(struct mg_context *ctx) { if (ctx->timers) { mg_join_thread(ctx->timers->threadid); (void)pthread_mutex_destroy(&ctx->timers->mutex); mg_free(ctx->timers->timers); mg_free(ctx->timers); ctx->timers = NULL; } } /* End of timer.inl */ webfakes/src/errors.c0000644000176200001440000000415614740243712014322 0ustar liggesusers #include "errors.h" #include #include #define ERRORBUF_SIZE 4096 static char errorbuf[ERRORBUF_SIZE]; SEXP r_throw_error(const char *func, const char *filename, int line, const char *msg, ...) { va_list args; errorbuf[0] = '\0'; va_start(args, msg); vsnprintf(errorbuf, ERRORBUF_SIZE, msg, args); va_end (args); error("%s @%s:%d (%s)", errorbuf, filename, line, func); return R_NilValue; } #ifdef _WIN32 SEXP r_throw_system_error(const char *func, const char *filename, int line, DWORD errorcode, const char *sysmsg, const char *msg, ...) { va_list args; LPVOID lpMsgBuf; char *realsysmsg = sysmsg ? (char*) sysmsg : NULL; char *failmsg = "Formatting the system message failed :("; if (errorcode == -1) errorcode = GetLastError(); if (!realsysmsg) { DWORD ret = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorcode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); if (ret == 0) { realsysmsg = failmsg; } else { realsysmsg = R_alloc(1, strlen(lpMsgBuf) + 1); strcpy(realsysmsg, lpMsgBuf); LocalFree(lpMsgBuf); } } errorbuf[0] = '\0'; va_start(args, msg); vsnprintf(errorbuf, ERRORBUF_SIZE, msg, args); va_end(args); error("%s (system error %ld, %s) @%s:%d (%s)", errorbuf, errorcode, realsysmsg, filename, line, func); return R_NilValue; } #endif #ifdef _WIN32 SEXP r_throw_posix_error( #else SEXP r_throw_system_error( #endif const char *func, const char *filename, int line, int errorcode, const char *sysmsg, const char *msg, ...) { va_list args; if (!sysmsg) sysmsg = strerror(errorcode); errorbuf[0] = '\0'; va_start(args, msg); vsnprintf(errorbuf, ERRORBUF_SIZE, msg, args); va_end(args); error("%s (system error %d, %s) @%s:%d (%s)", errorbuf, errorcode, sysmsg, filename, line, func); return R_NilValue; } webfakes/src/civetweb.h0000644000176200001440000020542614740430263014625 0ustar liggesusers/* Copyright (c) 2013-2021 the Civetweb developers * Copyright (c) 2004-2013 Sergey Lyubka * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef CIVETWEB_HEADER_INCLUDED #define CIVETWEB_HEADER_INCLUDED #define CIVETWEB_VERSION "1.16" #define CIVETWEB_VERSION_MAJOR (1) #define CIVETWEB_VERSION_MINOR (16) #define CIVETWEB_VERSION_PATCH (0) #ifndef CIVETWEB_API #if defined(_WIN32) #if defined(CIVETWEB_DLL_EXPORTS) #define CIVETWEB_API __declspec(dllexport) #elif defined(CIVETWEB_DLL_IMPORTS) #define CIVETWEB_API __declspec(dllimport) #else #define CIVETWEB_API #endif #elif __GNUC__ >= 4 #define CIVETWEB_API __attribute__((visibility("default"))) #else #define CIVETWEB_API #endif #endif #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* Init Features */ enum { MG_FEATURES_DEFAULT = 0x0u, /* Support files from local directories */ /* Will only work, if NO_FILES is not set. */ MG_FEATURES_FILES = 0x1u, /* Support transport layer security (TLS). */ /* SSL is still often used synonymously for TLS. */ /* Will only work, if NO_SSL is not set. */ MG_FEATURES_TLS = 0x2u, MG_FEATURES_SSL = 0x2u, /* Support common gateway interface (CGI). */ /* Will only work, if NO_CGI is not set. */ MG_FEATURES_CGI = 0x4u, /* Support IPv6. */ /* Will only work, if USE_IPV6 is set. */ MG_FEATURES_IPV6 = 0x8u, /* Support WebSocket protocol. */ /* Will only work, if USE_WEBSOCKET is set. */ MG_FEATURES_WEBSOCKET = 0x10u, /* Support server side Lua scripting. */ /* Will only work, if USE_LUA is set. */ MG_FEATURES_LUA = 0x20u, /* Support server side JavaScript scripting. */ /* Will only work, if USE_DUKTAPE is set. */ MG_FEATURES_SSJS = 0x40u, /* Provide data required for caching files. */ /* Will only work, if NO_CACHING is not set. */ MG_FEATURES_CACHE = 0x80u, /* Collect server status information. */ /* Will only work, if USE_SERVER_STATS is set. */ MG_FEATURES_STATS = 0x100u, /* Support on-the-fly compression. */ /* Will only work, if USE_ZLIB is set. */ MG_FEATURES_COMPRESSION = 0x200u, /* HTTP/2 support enabled. */ MG_FEATURES_HTTP2 = 0x400u, /* Support unix domain sockets. */ MG_FEATURES_X_DOMAIN_SOCKET = 0x800u, /* Bit mask for all feature defines. */ MG_FEATURES_ALL = 0xFFFFu }; /* Initialize this library. This should be called once before any other * function from this library. This function is not guaranteed to be * thread safe. * Parameters: * features: bit mask for features to be initialized. * Note: The TLS libraries (like OpenSSL) is initialized * only if the MG_FEATURES_TLS bit is set. * Currently the other bits do not influence * initialization, but this may change in future * versions. * Return value: * initialized features * 0: error */ CIVETWEB_API unsigned mg_init_library(unsigned features); /* Un-initialize this library. * Return value: * 0: error */ CIVETWEB_API unsigned mg_exit_library(void); struct mg_context; /* Handle for the HTTP service itself */ struct mg_connection; /* Handle for the individual connection */ /* Maximum number of headers */ #define MG_MAX_HEADERS (64) struct mg_header { const char *name; /* HTTP header name */ const char *value; /* HTTP header value */ }; /* This structure contains information about the HTTP request. */ struct mg_request_info { const char *request_method; /* "GET", "POST", etc */ const char *request_uri; /* URL-decoded URI (absolute or relative, * as in the request) */ const char *local_uri_raw; /* URL-decoded URI (relative). Can be NULL * if the request_uri does not address a * resource at the server host. */ const char *local_uri; /* Same as local_uri_raw, however, cleaned * so a path like * allowed_dir/../forbidden_file * is not possible. */ const char *http_version; /* E.g. "1.0", "1.1" */ const char *query_string; /* URL part after '?', not including '?', or NULL */ const char *remote_user; /* Authenticated user, or NULL if no auth used */ char remote_addr[48]; /* Client's IP address as a string. */ long long content_length; /* Length (in bytes) of the request body, can be -1 if no length was given. */ int remote_port; /* Port at client side */ int server_port; /* Port at server side (one of the listening ports) */ int is_ssl; /* 1 if HTTPS or WS is used (SSL/TLS used), 0 if not */ void *user_data; /* User data pointer passed to mg_start() */ void *conn_data; /* Connection-specific user data */ int num_headers; /* Number of HTTP headers */ struct mg_header http_headers[MG_MAX_HEADERS]; /* Allocate maximum headers */ struct mg_client_cert *client_cert; /* Client certificate information */ const char *acceptedWebSocketSubprotocol; /* websocket subprotocol, * accepted during handshake */ }; /* This structure contains information about the HTTP request. */ /* This structure may be extended in future versions. */ struct mg_response_info { int status_code; /* E.g. 200 */ const char *status_text; /* E.g. "OK" */ const char *http_version; /* E.g. "1.0", "1.1" */ long long content_length; /* Length (in bytes) of the request body, can be -1 if no length was given. */ int num_headers; /* Number of HTTP headers */ struct mg_header http_headers[MG_MAX_HEADERS]; /* Allocate maximum headers */ }; /* Client certificate information (part of mg_request_info) */ struct mg_client_cert { void *peer_cert; const char *subject; const char *issuer; const char *serial; const char *finger; }; /* This structure needs to be passed to mg_start(), to let civetweb know which callbacks to invoke. For a detailed description, see https://github.com/civetweb/civetweb/blob/master/docs/UserManual.md */ struct mg_callbacks { /* Called when civetweb has received new HTTP request. If the callback returns one, it must process the request by sending valid HTTP headers and a body. Civetweb will not do any further processing. Otherwise it must return zero. Note that since V1.7 the "begin_request" function is called before an authorization check. If an authorization check is required, use a request_handler instead. Return value: 0: civetweb will process the request itself. In this case, the callback must not send any data to the client. 1-999: callback already processed the request. Civetweb will not send any data after the callback returned. The return code is stored as a HTTP status code for the access log. */ int (*begin_request)(struct mg_connection *); /* Called when civetweb has finished processing request. */ void (*end_request)(const struct mg_connection *, int reply_status_code); /* Called when civetweb is about to log a message. If callback returns non-zero, civetweb does not log anything. */ int (*log_message)(const struct mg_connection *, const char *message); /* Called when civetweb is about to log access. If callback returns non-zero, civetweb does not log anything. */ int (*log_access)(const struct mg_connection *, const char *message); /* Called when civetweb initializes SSL library. Parameters: ssl_ctx: SSL_CTX pointer. user_data: parameter user_data passed when starting the server. Return value: 0: civetweb will set up the SSL certificate. 1: civetweb assumes the callback already set up the certificate. -1: initializing ssl fails. */ int (*init_ssl)(void *ssl_ctx, void *user_data); /* Called when civetweb initializes SSL library for a domain. Parameters: server_domain: authentication_domain from the domain config. ssl_ctx: SSL_CTX pointer. user_data: parameter user_data passed when starting the server. Return value: 0: civetweb will set up the SSL certificate. 1: civetweb assumes the callback already set up the certificate. -1: initializing ssl fails. */ int (*init_ssl_domain)(const char *server_domain, void *ssl_ctx, void *user_data); /* Called when civetweb is about to create or free a SSL_CTX. Parameters: ssl_ctx: SSL_CTX pointer. NULL at creation time, Not NULL when mg_context will be freed user_data: parameter user_data passed when starting the server. Return value: 0: civetweb will continue to create the context, just as if the callback would not be present. The value in *ssl_ctx when the function returns is ignored. 1: civetweb will copy the value from *ssl_ctx to the civetweb context and doesn't create its own. -1: initializing ssl fails.*/ int (*external_ssl_ctx)(void **ssl_ctx, void *user_data); /* Called when civetweb is about to create or free a SSL_CTX for a domain. Parameters: server_domain: authentication_domain from the domain config. ssl_ctx: SSL_CTX pointer. NULL at creation time, Not NULL when mg_context will be freed user_data: parameter user_data passed when starting the server. Return value: 0: civetweb will continue to create the context, just as if the callback would not be present. The value in *ssl_ctx when the function returns is ignored. 1: civetweb will copy the value from *ssl_ctx to the civetweb context and doesn't create its own. -1: initializing ssl fails.*/ int (*external_ssl_ctx_domain)(const char *server_domain, void **ssl_ctx, void *user_data); #if defined(MG_EXPERIMENTAL_INTERFACES) /* 2019-11-03 */ /* Called when data frame has been received from the peer. Parameters: bits: first byte of the websocket frame, see websocket RFC at http://tools.ietf.org/html/rfc6455, section 5.2 data, data_len: payload, with mask (if any) already applied. Return value: 1: keep this websocket connection open. 0: close this websocket connection. This callback is deprecated: Use mg_set_websocket_handler instead. */ int (*websocket_data)(struct mg_connection *, int bits, char *data, size_t data_len); #endif /* MG_LEGACY_INTERFACE */ /* Called when civetweb is closing a connection. The per-context mutex is locked when this is invoked. Websockets: Before mg_set_websocket_handler has been added, it was primarily useful for noting when a websocket is closing, and used to remove it from any application-maintained list of clients. Using this callback for websocket connections is deprecated: Use mg_set_websocket_handler instead. */ void (*connection_close)(const struct mg_connection *); /* Called after civetweb has closed a connection. The per-context mutex is locked when this is invoked. Connection specific data: If memory has been allocated for the connection specific user data (mg_request_info->conn_data, mg_get_user_connection_data), this is the last chance to free it. */ void (*connection_closed)(const struct mg_connection *); /* init_lua is called when civetweb is about to serve Lua server page. exit_lua is called when the Lua processing is complete. Both will work only if Lua support is enabled. Parameters: conn: current connection. lua_context: "lua_State *" pointer. context_flags: context type information as bitmask: context_flags & 0x0F: (0-15) Lua environment type */ void (*init_lua)(const struct mg_connection *conn, void *lua_context, unsigned context_flags); void (*exit_lua)(const struct mg_connection *conn, void *lua_context, unsigned context_flags); /* Called when civetweb is about to send HTTP error to the client. Implementing this callback allows to create custom error pages. Parameters: conn: current connection. status: HTTP error status code. errmsg: error message text. Return value: 1: run civetweb error handler. 0: callback already handled the error. */ int (*http_error)(struct mg_connection *conn, int status, const char *errmsg); /* Called after civetweb context has been created, before requests are processed. Parameters: ctx: context handle */ void (*init_context)(const struct mg_context *ctx); /* Called when civetweb context is deleted. Parameters: ctx: context handle */ void (*exit_context)(const struct mg_context *ctx); /* Called when a new worker thread is initialized. * It is always called from the newly created thread and can be used to * initialize thread local storage data. * Parameters: * ctx: context handle * thread_type: * 0 indicates the master thread * 1 indicates a worker thread handling client connections * 2 indicates an internal helper thread (timer thread) * Return value: * This function returns a user supplied pointer. The pointer is assigned * to the thread and can be obtained from the mg_connection object using * mg_get_thread_pointer in all server callbacks. Note: A connection and * a thread are not directly related. Threads will serve several different * connections, and data from a single connection may call different * callbacks using different threads. The thread pointer can be obtained * in a callback handler, but should not be stored beyond the scope of * one call to one callback. */ void *(*init_thread)(const struct mg_context *ctx, int thread_type); /* Called when a worker exits. * The parameters "ctx" and "thread_type" correspond to the "init_thread" * call. The "thread_pointer" parameter is the value returned by * "init_thread". */ void (*exit_thread)(const struct mg_context *ctx, int thread_type, void *thread_pointer); /* Called when initializing a new connection object. * Can be used to initialize the connection specific user data * (mg_request_info->conn_data, mg_get_user_connection_data). * When the callback is called, it is not yet known if a * valid HTTP(S) request will be made. * Parameters: * conn: not yet fully initialized connection object * conn_data: output parameter, set to initialize the * connection specific user data * Return value: * must be 0 * Otherwise, the result is undefined */ int (*init_connection)(const struct mg_connection *conn, void **conn_data); }; /* Start web server. Parameters: callbacks: mg_callbacks structure with user-defined callbacks. options: NULL terminated list of option_name, option_value pairs that specify Civetweb configuration parameters. Side-effects: on UNIX, ignores SIGCHLD and SIGPIPE signals. If custom processing is required for these, signal handlers must be set up after calling mg_start(). Example: const char *options[] = { "document_root", "/var/www", "listening_ports", "80,443s", NULL }; struct mg_context *ctx = mg_start(&my_func, NULL, options); Refer to https://github.com/civetweb/civetweb/blob/master/docs/UserManual.md for the list of valid option and their possible values. Return: web server context, or NULL on error. */ CIVETWEB_API struct mg_context *mg_start(const struct mg_callbacks *callbacks, void *user_data, const char **configuration_options); /* Stop the web server. Must be called last, when an application wants to stop the web server and release all associated resources. This function blocks until all Civetweb threads are stopped. Context pointer becomes invalid. */ CIVETWEB_API void mg_stop(struct mg_context *); /* Add an additional domain to an already running web server. * * Parameters: * ctx: Context handle of a server started by mg_start. * options: NULL terminated list of option_name, option_value pairs that * specify CivetWeb configuration parameters. * * Return: * < 0 in case of an error * -1 for a parameter error * -2 invalid options * -3 initializing SSL failed * -4 mandatory domain option missing * -5 duplicate domain * -6 out of memory * > 0 index / handle of a new domain */ CIVETWEB_API int mg_start_domain(struct mg_context *ctx, const char **configuration_options); /* mg_request_handler Called when a new request comes in. This callback is URI based and configured with mg_set_request_handler(). Parameters: conn: current connection information. cbdata: the callback data configured with mg_set_request_handler(). Returns: 0: the handler could not handle the request, so fall through. 1 - 999: the handler processed the request. The return code is stored as a HTTP status code for the access log. */ typedef int (*mg_request_handler)(struct mg_connection *conn, void *cbdata); /* mg_set_request_handler Sets or removes a URI mapping for a request handler. This function waits until a removing/updating handler becomes unused, so do not call from the handler itself. URI's are ordered and prefixed URI's are supported. For example, consider two URIs: /a/b and /a /a matches /a /a/b matches /a/b /a/c matches /a Parameters: ctx: server context uri: the URI (exact or pattern) for the handler handler: the callback handler to use when the URI is requested. If NULL, an already registered handler for this URI will be removed. The URI used to remove a handler must match exactly the one used to register it (not only a pattern match). cbdata: the callback data to give to the handler when it is called. */ CIVETWEB_API void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata); /* Callback types for websocket handlers in C/C++. mg_websocket_connect_handler Is called when the client intends to establish a websocket connection, before websocket handshake. Return value: 0: civetweb proceeds with websocket handshake. 1: connection is closed immediately. mg_websocket_ready_handler Is called when websocket handshake is successfully completed, and connection is ready for data exchange. mg_websocket_data_handler Is called when a data frame has been received from the client. Parameters: bits: first byte of the websocket frame, see websocket RFC at http://tools.ietf.org/html/rfc6455, section 5.2 data, data_len: payload, with mask (if any) already applied. Return value: 1: keep this websocket connection open. 0: close this websocket connection. mg_connection_close_handler Is called, when the connection is closed.*/ typedef int (*mg_websocket_connect_handler)(const struct mg_connection *, void *); typedef void (*mg_websocket_ready_handler)(struct mg_connection *, void *); typedef int (*mg_websocket_data_handler)(struct mg_connection *, int, char *, size_t, void *); typedef void (*mg_websocket_close_handler)(const struct mg_connection *, void *); /* struct mg_websocket_subprotocols * * List of accepted subprotocols */ struct mg_websocket_subprotocols { int nb_subprotocols; const char **subprotocols; }; /* mg_set_websocket_handler Set or remove handler functions for websocket connections. This function works similar to mg_set_request_handler - see there. */ CIVETWEB_API void mg_set_websocket_handler(struct mg_context *ctx, const char *uri, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata); /* mg_set_websocket_handler Set or remove handler functions for websocket connections. This function works similar to mg_set_request_handler - see there. */ CIVETWEB_API void mg_set_websocket_handler_with_subprotocols( struct mg_context *ctx, const char *uri, struct mg_websocket_subprotocols *subprotocols, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata); /* mg_authorization_handler Callback function definition for mg_set_auth_handler Parameters: conn: current connection information. cbdata: the callback data configured with mg_set_request_handler(). Returns: 0: access denied 1: access granted */ typedef int (*mg_authorization_handler)(struct mg_connection *conn, void *cbdata); /* mg_set_auth_handler Sets or removes a URI mapping for an authorization handler. This function works similar to mg_set_request_handler - see there. */ CIVETWEB_API void mg_set_auth_handler(struct mg_context *ctx, const char *uri, mg_authorization_handler handler, void *cbdata); /* Get the value of particular configuration parameter. The value returned is read-only. Civetweb does not allow changing configuration at run time. If given parameter name is not valid, NULL is returned. For valid names, return value is guaranteed to be non-NULL. If parameter is not set, zero-length string is returned. */ CIVETWEB_API const char *mg_get_option(const struct mg_context *ctx, const char *name); /* Get context from connection. */ CIVETWEB_API struct mg_context * mg_get_context(const struct mg_connection *conn); /* Get user data passed to mg_start from context. */ CIVETWEB_API void *mg_get_user_data(const struct mg_context *ctx); /* Get user data passed to mg_start from connection. */ CIVETWEB_API void *mg_get_user_context_data(const struct mg_connection *conn); /* Get user defined thread pointer for server threads (see init_thread). */ CIVETWEB_API void *mg_get_thread_pointer(const struct mg_connection *conn); /* Set user data for the current connection. */ /* Note: CivetWeb callbacks use "struct mg_connection *conn" as input when mg_read/mg_write callbacks are allowed in the callback, while "const struct mg_connection *conn" is used as input in case calling mg_read/mg_write is not allowed. Setting the user connection data will modify the connection object represented by mg_connection *, but it will not read from or write to the connection. */ /* Note: An alternative is to use the init_connection callback instead to initialize the user connection data pointer. It is recommended to supply a pointer to some user defined data structure as conn_data initializer in init_connection. In case it is required to change some data after the init_connection call, store another data pointer in the user defined data structure and modify that pointer. In either case, after the init_connection callback, only calls to mg_get_user_connection_data should be required. */ CIVETWEB_API void mg_set_user_connection_data(const struct mg_connection *conn, void *data); /* Get user data set for the current connection. */ CIVETWEB_API void * mg_get_user_connection_data(const struct mg_connection *conn); /* Get a formatted link corresponding to the current request Parameters: conn: current connection information. buf: string buffer (out) buflen: length of the string buffer Returns: <0: error >=0: ok */ CIVETWEB_API int mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen); struct mg_option { const char *name; int type; const char *default_value; }; /* Configuration types */ enum { MG_CONFIG_TYPE_UNKNOWN = 0x0, MG_CONFIG_TYPE_NUMBER = 0x1, MG_CONFIG_TYPE_STRING = 0x2, MG_CONFIG_TYPE_FILE = 0x3, MG_CONFIG_TYPE_DIRECTORY = 0x4, MG_CONFIG_TYPE_BOOLEAN = 0x5, MG_CONFIG_TYPE_EXT_PATTERN = 0x6, MG_CONFIG_TYPE_STRING_LIST = 0x7, MG_CONFIG_TYPE_STRING_MULTILINE = 0x8, MG_CONFIG_TYPE_YES_NO_OPTIONAL = 0x9 }; /* Return array of struct mg_option, representing all valid configuration options of civetweb.c. The array is terminated by a NULL name option. */ CIVETWEB_API const struct mg_option *mg_get_valid_options(void); struct mg_server_port { int protocol; /* 1 = IPv4, 2 = IPv6, 3 = both */ int port; /* port number */ int is_ssl; /* https port: 0 = no, 1 = yes */ int is_redirect; /* redirect all requests: 0 = no, 1 = yes */ int _reserved1; int _reserved2; int _reserved3; int _reserved4; }; /* Legacy name */ #define mg_server_ports mg_server_port /* Get the list of ports that civetweb is listening on. The parameter size is the size of the ports array in elements. The caller is responsibility to allocate the required memory. This function returns the number of struct mg_server_port elements filled in, or <0 in case of an error. */ CIVETWEB_API int mg_get_server_ports(const struct mg_context *ctx, int size, struct mg_server_port *ports); /* Add, edit or delete the entry in the passwords file. * * This function allows an application to manipulate .htpasswd files on the * fly by adding, deleting and changing user records. This is one of the * several ways of implementing authentication on the server side. For another, * cookie-based way please refer to the examples/chat in the source tree. * * Parameter: * passwords_file_name: Path and name of a file storing multiple passwords * realm: HTTP authentication realm (authentication domain) name * user: User name * password: * If password is not NULL, entry modified or added. * If password is NULL, entry is deleted. * * Return: * 1 on success, 0 on error. */ CIVETWEB_API int mg_modify_passwords_file(const char *passwords_file_name, const char *realm, const char *user, const char *password); /* Same as mg_modify_passwords_file, but instead of the plain-text * password, the HA1 hash is specified. The plain-text password is * not made known to civetweb. * * The HA1 hash is the MD5 checksum of a "user:realm:password" string * in lower-case hex format. For example, if the user name is "myuser", * the realm is "myrealm", and the password is "secret", then the HA1 is * e67fd3248b58975c3e89ff18ecb75e2f. */ CIVETWEB_API int mg_modify_passwords_file_ha1(const char *passwords_file_name, const char *realm, const char *user, const char *ha1); /* Return information associated with the request. * Use this function to implement a server and get data about a request * from a HTTP/HTTPS client. * Note: Before CivetWeb 1.10, this function could be used to read * a response from a server, when implementing a client, although the * values were never returned in appropriate mg_request_info elements. * It is strongly advised to use mg_get_response_info for clients. */ CIVETWEB_API const struct mg_request_info * mg_get_request_info(const struct mg_connection *); /* Return information associated with a HTTP/HTTPS response. * Use this function in a client, to check the response from * the server. */ CIVETWEB_API const struct mg_response_info * mg_get_response_info(const struct mg_connection *); /* Send data to the client. Return: 0 when the connection has been closed -1 on error >0 number of bytes written on success */ CIVETWEB_API int mg_write(struct mg_connection *, const void *buf, size_t len); /* Send data to a websocket client wrapped in a websocket frame. Uses mg_lock_connection to ensure that the transmission is not interrupted, i.e., when the application is proactively communicating and responding to a request simultaneously. Send data to a websocket client wrapped in a websocket frame. This function is available when civetweb is compiled with -DUSE_WEBSOCKET Return: 0 when the connection has been closed -1 on error >0 number of bytes written on success */ CIVETWEB_API int mg_websocket_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len); /* Send data to a websocket server wrapped in a masked websocket frame. Uses mg_lock_connection to ensure that the transmission is not interrupted, i.e., when the application is proactively communicating and responding to a request simultaneously. Send data to a websocket server wrapped in a masked websocket frame. This function is available when civetweb is compiled with -DUSE_WEBSOCKET Return: 0 when the connection has been closed -1 on error >0 number of bytes written on success */ CIVETWEB_API int mg_websocket_client_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len); /* Blocks until unique access is obtained to this connection. Intended for use with websockets only. Invoke this before mg_write or mg_printf when communicating with a websocket if your code has server-initiated communication as well as communication in direct response to a message. Do not acquire this lock while holding mg_lock_context(). */ CIVETWEB_API void mg_lock_connection(struct mg_connection *conn); CIVETWEB_API void mg_unlock_connection(struct mg_connection *conn); /* Lock server context. This lock may be used to protect resources that are shared between different connection/worker threads. If the given context is not server, these functions do nothing. */ CIVETWEB_API void mg_lock_context(struct mg_context *ctx); CIVETWEB_API void mg_unlock_context(struct mg_context *ctx); /* WebSocket OpcCodes, from http://tools.ietf.org/html/rfc6455 */ enum { MG_WEBSOCKET_OPCODE_CONTINUATION = 0x0, MG_WEBSOCKET_OPCODE_TEXT = 0x1, MG_WEBSOCKET_OPCODE_BINARY = 0x2, MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8, MG_WEBSOCKET_OPCODE_PING = 0x9, MG_WEBSOCKET_OPCODE_PONG = 0xa }; /* Macros for enabling compiler-specific checks for printf-like arguments. */ #undef PRINTF_FORMAT_STRING #if defined(_MSC_VER) && _MSC_VER >= 1400 #include #if defined(_MSC_VER) && _MSC_VER > 1400 #define PRINTF_FORMAT_STRING(s) _Printf_format_string_ s #else #define PRINTF_FORMAT_STRING(s) __format_string s #endif #else #define PRINTF_FORMAT_STRING(s) s #endif #ifdef __GNUC__ #define PRINTF_ARGS(x, y) __attribute__((format(printf, x, y))) #else #define PRINTF_ARGS(x, y) #endif /* Send data to the client using printf() semantics. Works exactly like mg_write(), but allows to do message formatting. */ CIVETWEB_API int mg_printf(struct mg_connection *, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3); /* Send a part of the message body, if chunked transfer encoding is set. * Only use this function after sending a complete HTTP request or response * header with "Transfer-Encoding: chunked" set. */ CIVETWEB_API int mg_send_chunk(struct mg_connection *conn, const char *chunk, unsigned int chunk_len); /* Send contents of the entire file together with HTTP headers. * Parameters: * conn: Current connection information. * path: Full path to the file to send. * This function has been superseded by mg_send_mime_file */ CIVETWEB_API void mg_send_file(struct mg_connection *conn, const char *path); /* Send contents of the file without HTTP headers. * The code must send a valid HTTP response header before using this function. * * Parameters: * conn: Current connection information. * path: Full path to the file to send. * * Return: * < 0 Error */ CIVETWEB_API int mg_send_file_body(struct mg_connection *conn, const char *path); /* Send HTTP error reply. */ CIVETWEB_API int mg_send_http_error(struct mg_connection *conn, int status_code, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(3, 4); /* Send "HTTP 200 OK" response header. * After calling this function, use mg_write or mg_send_chunk to send the * response body. * Parameters: * conn: Current connection handle. * mime_type: Set Content-Type for the following content. * content_length: Size of the following content, if content_length >= 0. * Will set transfer-encoding to chunked, if set to -1. * Return: * < 0 Error */ CIVETWEB_API int mg_send_http_ok(struct mg_connection *conn, const char *mime_type, long long content_length); /* Send "HTTP 30x" redirect response. * The response has content-size zero: do not send any body data after calling * this function. * Parameters: * conn: Current connection handle. * target_url: New location. * redirect_code: HTTP redirect type. Could be 301, 302, 303, 307, 308. * Return: * < 0 Error (-1 send error, -2 parameter error) */ CIVETWEB_API int mg_send_http_redirect(struct mg_connection *conn, const char *target_url, int redirect_code); /* Send HTTP digest access authentication request. * Browsers will send a user name and password in their next request, showing * an authentication dialog if the password is not stored. * Parameters: * conn: Current connection handle. * realm: Authentication realm. If NULL is supplied, the sever domain * set in the authentication_domain configuration is used. * Return: * < 0 Error */ CIVETWEB_API int mg_send_digest_access_authentication_request(struct mg_connection *conn, const char *realm); /* Check if the current request has a valid authentication token set. * A file is used to provide a list of valid user names, realms and * password hashes. The file can be created and modified using the * mg_modify_passwords_file API function. * Parameters: * conn: Current connection handle. * realm: Authentication realm. If NULL is supplied, the sever domain * set in the authentication_domain configuration is used. * filename: Path and name of a file storing multiple password hashes. * Return: * > 0 Valid authentication * 0 Invalid authentication * < 0 Error (all values < 0 should be considered as invalid * authentication, future error codes will have negative * numbers) * -1 Parameter error * -2 File not found */ CIVETWEB_API int mg_check_digest_access_authentication(struct mg_connection *conn, const char *realm, const char *filename); /* Send contents of the entire file together with HTTP headers. * Parameters: * conn: Current connection handle. * path: Full path to the file to send. * mime_type: Content-Type for file. NULL will cause the type to be * looked up by the file extension. */ CIVETWEB_API void mg_send_mime_file(struct mg_connection *conn, const char *path, const char *mime_type); /* Send contents of the entire file together with HTTP headers. Parameters: conn: Current connection information. path: Full path to the file to send. mime_type: Content-Type for file. NULL will cause the type to be looked up by the file extension. additional_headers: Additional custom header fields appended to the header. Each header should start with an X-, to ensure it is not included twice. NULL does not append anything. */ CIVETWEB_API void mg_send_mime_file2(struct mg_connection *conn, const char *path, const char *mime_type, const char *additional_headers); /* Store body data into a file. */ CIVETWEB_API long long mg_store_body(struct mg_connection *conn, const char *path); /* Read entire request body and store it in a file "path". Return: < 0 Error >= 0 Number of bytes stored in file "path". */ /* Read data from the remote end, return number of bytes read. Return: 0 connection has been closed by peer. No more data could be read. < 0 read error. No more data could be read from the connection. > 0 number of bytes read into the buffer. */ CIVETWEB_API int mg_read(struct mg_connection *, void *buf, size_t len); /* Get the value of particular HTTP header. This is a helper function. It traverses request_info->http_headers array, and if the header is present in the array, returns its value. If it is not present, NULL is returned. */ CIVETWEB_API const char *mg_get_header(const struct mg_connection *, const char *name); /* Get a value of particular form variable. Parameters: data: pointer to form-uri-encoded buffer. This could be either POST data, or request_info.query_string. data_len: length of the encoded data. var_name: variable name to decode from the buffer dst: destination buffer for the decoded variable dst_len: length of the destination buffer Return: On success, length of the decoded variable. On error: -1 (variable not found). -2 (destination buffer is NULL, zero length or too small to hold the decoded variable). Destination buffer is guaranteed to be '\0' - terminated if it is not NULL or zero length. */ CIVETWEB_API int mg_get_var(const char *data, size_t data_len, const char *var_name, char *dst, size_t dst_len); /* Get a value of particular form variable. Parameters: data: pointer to form-uri-encoded buffer. This could be either POST data, or request_info.query_string. data_len: length of the encoded data. var_name: variable name to decode from the buffer dst: destination buffer for the decoded variable dst_len: length of the destination buffer occurrence: which occurrence of the variable, 0 is the 1st, 1 the 2nd, ... this makes it possible to parse a query like b=x&a=y&a=z which will have occurrence values b:0, a:0 and a:1 Return: On success, length of the decoded variable. On error: -1 (variable not found). -2 (destination buffer is NULL, zero length or too small to hold the decoded variable). Destination buffer is guaranteed to be '\0' - terminated if it is not NULL or zero length. */ CIVETWEB_API int mg_get_var2(const char *data, size_t data_len, const char *var_name, char *dst, size_t dst_len, size_t occurrence); /* Split form encoded data into a list of key value pairs. A form encoded input might be a query string, the body of a x-www-form-urlencoded POST request or any other data with this structure: "keyName1=value1&keyName2=value2&keyName3=value3". Values might be percent-encoded - this function will transform them to the unencoded characters. The input string is modified by this function: To split the "query_string" member of struct request_info, create a copy first (e.g., using strdup). The function itself does not allocate memory. Thus, it is not required to free any pointer returned from this function. The output list of is limited to MG_MAX_FORM_FIELDS name-value- pairs. The default value is reasonably oversized for typical applications, however, for special purpose systems it might be required to increase this value at compile time. Parameters: data: form encoded input string. Will be modified by this function. form_fields: output list of name/value-pairs. A buffer with a size specified by num_form_fields must be provided by the caller. num_form_fields: Size of provided form_fields buffer in number of "struct mg_header" elements. Return: On success: number of form_fields filled On error: -1 (parameter error). */ CIVETWEB_API int mg_split_form_urlencoded(char *data, struct mg_header *form_fields, unsigned num_form_fields); /* Fetch value of certain cookie variable into the destination buffer. Destination buffer is guaranteed to be '\0' - terminated. In case of failure, dst[0] == '\0'. Note that RFC allows many occurrences of the same parameter. This function returns only first occurrence. Return: On success, value length. On error: -1 (either "Cookie:" header is not present at all or the requested parameter is not found). -2 (destination buffer is NULL, zero length or too small to hold the value). */ CIVETWEB_API int mg_get_cookie(const char *cookie, const char *var_name, char *buf, size_t buf_len); /* Download data from the remote web server. host: host name to connect to, e.g. "foo.com", or "10.12.40.1". port: port number, e.g. 80. use_ssl: whether to use SSL connection. error_buffer, error_buffer_size: error message placeholder. request_fmt,...: HTTP request. Return: On success, valid pointer to the new connection, suitable for mg_read(). On error, NULL. error_buffer contains error message. Example: char ebuf[100]; struct mg_connection *conn; conn = mg_download("google.com", 80, 0, ebuf, sizeof(ebuf), "%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n"); mg_download is equivalent to calling mg_connect_client followed by mg_printf and mg_get_response. Using these three functions directly may allow more control as compared to using mg_download. */ CIVETWEB_API struct mg_connection * mg_download(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, PRINTF_FORMAT_STRING(const char *request_fmt), ...) PRINTF_ARGS(6, 7); /* Close the connection opened by mg_download(). */ CIVETWEB_API void mg_close_connection(struct mg_connection *conn); /* This structure contains callback functions for handling form fields. It is used as an argument to mg_handle_form_request. */ struct mg_form_data_handler { /* This callback function is called, if a new field has been found. * The return value of this callback is used to define how the field * should be processed. * * Parameters: * key: Name of the field ("name" property of the HTML input field). * filename: Name of a file to upload, at the client computer. * Only set for input fields of type "file", otherwise NULL. * path: Output parameter: File name (incl. path) to store the file * at the server computer. Only used if FORM_FIELD_STORAGE_STORE * is returned by this callback. Existing files will be * overwritten. * pathlen: Length of the buffer for path. * user_data: Value of the member user_data of mg_form_data_handler * * Return value: * The callback must return the intended storage for this field * (See FORM_FIELD_STORAGE_*). */ int (*field_found)(const char *key, const char *filename, char *path, size_t pathlen, void *user_data); /* If the "field_found" callback returned FORM_FIELD_STORAGE_GET, * this callback will receive the field data. * * Parameters: * key: Name of the field ("name" property of the HTML input field). * value: Value of the input field. * user_data: Value of the member user_data of mg_form_data_handler * * Return value: * The return code determines how the server should continue processing * the current request (See MG_FORM_FIELD_HANDLE_*). */ int (*field_get)(const char *key, const char *value, size_t valuelen, void *user_data); /* If the "field_found" callback returned FORM_FIELD_STORAGE_STORE, * the data will be stored into a file. If the file has been written * successfully, this callback will be called. This callback will * not be called for only partially uploaded files. The * mg_handle_form_request function will either store the file completely * and call this callback, or it will remove any partial content and * not call this callback function. * * Parameters: * path: Path of the file stored at the server. * file_size: Size of the stored file in bytes. * user_data: Value of the member user_data of mg_form_data_handler * * Return value: * The return code determines how the server should continue processing * the current request (See MG_FORM_FIELD_HANDLE_*). */ int (*field_store)(const char *path, long long file_size, void *user_data); /* User supplied argument, passed to all callback functions. */ void *user_data; }; /* Return values definition for the "field_found" callback in * mg_form_data_handler. */ enum { /* Skip this field (neither get nor store it). Continue with the * next field. */ MG_FORM_FIELD_STORAGE_SKIP = 0x0, /* Get the field value. */ MG_FORM_FIELD_STORAGE_GET = 0x1, /* Store the field value into a file. */ MG_FORM_FIELD_STORAGE_STORE = 0x2, /* Stop parsing this request. Skip the remaining fields. */ MG_FORM_FIELD_STORAGE_ABORT = 0x10 }; /* Return values for "field_get" and "field_store" */ enum { /* Only "field_get": If there is more data in this field, get the next * chunk. Otherwise: handle the next field. */ MG_FORM_FIELD_HANDLE_GET = 0x1, /* Handle the next field */ MG_FORM_FIELD_HANDLE_NEXT = 0x8, /* Stop parsing this request */ MG_FORM_FIELD_HANDLE_ABORT = 0x10 }; /* Process form data. * Returns the number of fields handled, or < 0 in case of an error. * Note: It is possible that several fields are already handled successfully * (e.g., stored into files), before the request handling is stopped with an * error. In this case a number < 0 is returned as well. * In any case, it is the duty of the caller to remove files once they are * no longer required. */ CIVETWEB_API int mg_handle_form_request(struct mg_connection *conn, struct mg_form_data_handler *fdh); /* Convenience function -- create detached thread. Return: 0 on success, non-0 on error. */ typedef void *(*mg_thread_func_t)(void *); CIVETWEB_API int mg_start_thread(mg_thread_func_t f, void *p); /* Return builtin mime type for the given file name. For unrecognized extensions, "text/plain" is returned. */ CIVETWEB_API const char *mg_get_builtin_mime_type(const char *file_name); /* Get text representation of HTTP status code. */ CIVETWEB_API const char * mg_get_response_code_text(const struct mg_connection *conn, int response_code); /* Return CivetWeb version. */ CIVETWEB_API const char *mg_version(void); /* URL-decode input buffer into destination buffer. 0-terminate the destination buffer. form-url-encoded data differs from URI encoding in a way that it uses '+' as character for space, see RFC 1866 section 8.2.1 http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt Return: length of the decoded data, or -1 if dst buffer is too small. */ CIVETWEB_API int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded); /* URL-encode input buffer into destination buffer. returns the length of the resulting buffer or -1 is the buffer is too small. */ CIVETWEB_API int mg_url_encode(const char *src, char *dst, size_t dst_len); /* BASE64-encode input buffer into destination buffer. returns -1 on OK. */ CIVETWEB_API int mg_base64_encode(const unsigned char *src, size_t src_len, char *dst, size_t *dst_len); /* BASE64-decode input buffer into destination buffer. returns -1 on OK. */ CIVETWEB_API int mg_base64_decode(const char *src, size_t src_len, unsigned char *dst, size_t *dst_len); /* MD5 hash given strings. Buffer 'buf' must be 33 bytes long. Varargs is a NULL terminated list of ASCIIz strings. When function returns, buf will contain human-readable MD5 hash. Example: char buf[33]; mg_md5(buf, "aa", "bb", NULL); */ CIVETWEB_API char *mg_md5(char buf[33], ...); #if !defined(MG_MATCH_CONTEXT_MAX_MATCHES) #define MG_MATCH_CONTEXT_MAX_MATCHES (32) #endif struct mg_match_element { const char *str; /* First character matching wildcard */ size_t len; /* Number of character matching wildcard */ }; struct mg_match_context { int case_sensitive; /* Input: 1 (case sensitive) or 0 (insensitive) */ size_t num_matches; /* Output: Number of wildcard matches returned. */ struct mg_match_element match[MG_MATCH_CONTEXT_MAX_MATCHES]; /* Output */ }; #if defined(MG_EXPERIMENTAL_INTERFACES) /* Pattern matching and extraction function. Parameters: pat: Pattern string (see UserManual.md) str: String to search for match patterns. mcx: Match context (optional, can be NULL). Return: Number of characters matched. -1 if no valid match was found. Note: 0 characters might be a valid match for some patterns. */ CIVETWEB_API ptrdiff_t mg_match(const char *pat, const char *str, struct mg_match_context *mcx); #endif /* Print error message to the opened error log stream. This utilizes the provided logging configuration. conn: connection (not used for sending data, but to get perameters) fmt: format string without the line return ...: variable argument list Example: mg_cry(conn,"i like %s", "logging"); */ CIVETWEB_API void mg_cry(const struct mg_connection *conn, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3); /* utility methods to compare two buffers, case insensitive. */ CIVETWEB_API int mg_strcasecmp(const char *s1, const char *s2); CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len); /* Connect to a websocket as a client Parameters: host: host to connect to, i.e. "echo.websocket.org" or "192.168.1.1" or "localhost" port: server port use_ssl: make a secure connection to server error_buffer, error_buffer_size: buffer for an error message path: server path you are trying to connect to, i.e. if connection to localhost/app, path should be "/app" origin: value of the Origin HTTP header data_func: callback that should be used when data is received from the server user_data: user supplied argument Return: On success, valid mg_connection object. On error, NULL. Se error_buffer for details. */ CIVETWEB_API struct mg_connection * mg_connect_websocket_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data); CIVETWEB_API struct mg_connection * mg_connect_websocket_client_extensions(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, const char *extensions, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data); /* Connect to a TCP server as a client (can be used to connect to a HTTP server) Parameters: host: host to connect to, i.e. "www.wikipedia.org" or "192.168.1.1" or "localhost" port: server port use_ssl: make a secure connection to server error_buffer, error_buffer_size: buffer for an error message Return: On success, valid mg_connection object. On error, NULL. Se error_buffer for details. */ CIVETWEB_API struct mg_connection *mg_connect_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size); struct mg_client_options { const char *host; int port; const char *client_cert; const char *server_cert; const char *host_name; /* TODO: add more data */ }; CIVETWEB_API struct mg_connection * mg_connect_client_secure(const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size); CIVETWEB_API struct mg_connection *mg_connect_websocket_client_secure( const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data); CIVETWEB_API struct mg_connection * mg_connect_websocket_client_secure_extensions( const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, const char *extensions, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data); #if defined(MG_LEGACY_INTERFACE) /* 2019-11-02 */ enum { TIMEOUT_INFINITE = -1 }; #endif enum { MG_TIMEOUT_INFINITE = -1 }; /* Wait for a response from the server Parameters: conn: connection ebuf, ebuf_len: error message placeholder. timeout: time to wait for a response in milliseconds (if < 0 then wait forever) Return: On success, >= 0 On error/timeout, < 0 */ CIVETWEB_API int mg_get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int timeout); /* mg_response_header_* functions can be used from server callbacks * to prepare HTTP server response headers. Using this function will * allow a callback to work with HTTP/1.x and HTTP/2. */ /* Initialize a new HTTP response * Parameters: * conn: Current connection handle. * status: HTTP status code (e.g., 200 for "OK"). * Return: * 0: ok * -1: parameter error * -2: invalid connection type * -3: invalid connection status * -4: network error (only if built with NO_RESPONSE_BUFFERING) */ CIVETWEB_API int mg_response_header_start(struct mg_connection *conn, int status); /* Add a new HTTP response header line * Parameters: * conn: Current connection handle. * header: Header name. * value: Header value. * value_len: Length of header value, excluding the terminating zero. * Use -1 for "strlen(value)". * Return: * 0: ok * -1: parameter error * -2: invalid connection type * -3: invalid connection status * -4: too many headers * -5: out of memory */ CIVETWEB_API int mg_response_header_add(struct mg_connection *conn, const char *header, const char *value, int value_len); /* Add a complete header string (key + value). * This function is less efficient as compared to mg_response_header_add, * and should only be used to convert complete HTTP/1.x header lines. * Parameters: * conn: Current connection handle. * http1_headers: Header line(s) in the form "name: value\r\n". * Return: * >=0: no error, number of header lines added * -1: parameter error * -2: invalid connection type * -3: invalid connection status * -4: too many headers * -5: out of memory */ CIVETWEB_API int mg_response_header_add_lines(struct mg_connection *conn, const char *http1_headers); /* Send http response * Parameters: * conn: Current connection handle. * Return: * 0: ok * -1: parameter error * -2: invalid connection type * -3: invalid connection status * -4: sending failed (network error) */ CIVETWEB_API int mg_response_header_send(struct mg_connection *conn); /* Check which features where set when the civetweb library has been compiled. The function explicitly addresses compile time defines used when building the library - it does not mean, the feature has been initialized using a mg_init_library call. mg_check_feature can be called anytime, even before mg_init_library has been called. Parameters: feature: specifies which feature should be checked The value is a bit mask. The individual bits are defined as: 1 serve files (NO_FILES not set) 2 support HTTPS (NO_SSL not set) 4 support CGI (NO_CGI not set) 8 support IPv6 (USE_IPV6 set) 16 support WebSocket (USE_WEBSOCKET set) 32 support Lua scripts and Lua server pages (USE_LUA is set) 64 support server side JavaScript (USE_DUKTAPE is set) 128 support caching (NO_CACHING not set) 256 support server statistics (USE_SERVER_STATS is set) 512 support for on the fly compression (USE_ZLIB is set) These values are defined as MG_FEATURES_* The result is undefined, if bits are set that do not represent a defined feature (currently: feature >= 1024). The result is undefined, if no bit is set (feature == 0). Return: If a feature is available, the corresponding bit is set If a feature is not available, the bit is 0 */ CIVETWEB_API unsigned mg_check_feature(unsigned feature); /* Get information on the system. Useful for support requests. Parameters: buffer: Store system information as string here. buflen: Length of buffer (including a byte required for a terminating 0). Return: Available size of system information, excluding a terminating 0. The information is complete, if the return value is smaller than buflen. The result is a JSON formatted string, the exact content may vary. Note: It is possible to determine the required buflen, by first calling this function with buffer = NULL and buflen = NULL. The required buflen is one byte more than the returned value. */ CIVETWEB_API int mg_get_system_info(char *buffer, int buflen); /* Get context information. Useful for server diagnosis. Parameters: ctx: Context handle buffer: Store context information here. buflen: Length of buffer (including a byte required for a terminating 0). Return: Available size of system information, excluding a terminating 0. The information is complete, if the return value is smaller than buflen. The result is a JSON formatted string, the exact content may vary. Note: It is possible to determine the required buflen, by first calling this function with buffer = NULL and buflen = NULL. The required buflen is one byte more than the returned value. However, since the available context information changes, you should allocate a few bytes more. */ CIVETWEB_API int mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen); /* Disable HTTP keep-alive on a per-connection basis. Reference: https://github.com/civetweb/civetweb/issues/727 Parameters: conn: Current connection handle. */ CIVETWEB_API void mg_disable_connection_keep_alive(struct mg_connection *conn); #if defined(MG_EXPERIMENTAL_INTERFACES) /* Get connection information. Useful for server diagnosis. Parameters: ctx: Context handle idx: Connection index buffer: Store context information here. buflen: Length of buffer (including a byte required for a terminating 0). Return: Available size of system information, excluding a terminating 0. The information is complete, if the return value is smaller than buflen. The result is a JSON formatted string, the exact content may vary. Note: It is possible to determine the required buflen, by first calling this function with buffer = NULL and buflen = NULL. The required buflen is one byte more than the returned value. However, since the available context information changes, you should allocate a few bytes more. */ CIVETWEB_API int mg_get_connection_info(const struct mg_context *ctx, int idx, char *buffer, int buflen); #endif /* New APIs for enhanced option and error handling. These mg_*2 API functions have the same purpose as their original versions, but provide additional options and/or provide improved error diagnostics. Note: Experimental interfaces may change */ struct mg_error_data { unsigned code; /* error code (number) */ unsigned code_sub; /* error sub code (number) */ char *text; /* buffer for error text */ size_t text_buffer_size; /* size of buffer of "text" */ }; /* Values for error "code" in mg_error_data */ enum { /* No error */ MG_ERROR_DATA_CODE_OK = 0u, /* Caller provided invalid parameter */ MG_ERROR_DATA_CODE_INVALID_PARAM = 1u, /* "configuration_option" contains invalid element */ MG_ERROR_DATA_CODE_INVALID_OPTION = 2u, /* Initializen TLS / SSL library failed */ MG_ERROR_DATA_CODE_INIT_TLS_FAILED = 3u, /* Mandatory "configuration_option" missing */ MG_ERROR_DATA_CODE_MISSING_OPTION = 4u, /* Duplicate "authentication_domain" option */ MG_ERROR_DATA_CODE_DUPLICATE_DOMAIN = 5u, /* Not enough memory */ MG_ERROR_DATA_CODE_OUT_OF_MEMORY = 6u, /* Server already stopped */ MG_ERROR_DATA_CODE_SERVER_STOPPED = 7u, /* mg_init_library must be called first */ MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED = 8u, /* Operating system function failed */ MG_ERROR_DATA_CODE_OS_ERROR = 9u, /* Failed to bind to server ports */ MG_ERROR_DATA_CODE_INIT_PORTS_FAILED = 10u, /* Failed to switch user (option "run_as_user") */ MG_ERROR_DATA_CODE_INIT_USER_FAILED = 11u, /* Access Control List error */ MG_ERROR_DATA_CODE_INIT_ACL_FAILED = 12u, /* Global password file error */ MG_ERROR_DATA_CODE_INVALID_PASS_FILE = 13u, /* Lua background script init error */ MG_ERROR_DATA_CODE_SCRIPT_ERROR = 14u, /* Client: Host not found, invalid IP to connect */ MG_ERROR_DATA_CODE_HOST_NOT_FOUND = 15u, /* Client: TCP connect timeout */ MG_ERROR_DATA_CODE_CONNECT_TIMEOUT = 16u, /* Client: TCP connect failed */ MG_ERROR_DATA_CODE_CONNECT_FAILED = 17u, /* Error using TLS client certificate */ MG_ERROR_DATA_CODE_TLS_CLIENT_CERT_ERROR = 18u, /* Error setting trusted TLS server certificate for client connection */ MG_ERROR_DATA_CODE_TLS_SERVER_CERT_ERROR = 19u, /* Error establishing TLS connection to HTTPS server */ MG_ERROR_DATA_CODE_TLS_CONNECT_ERROR = 20u }; struct mg_init_data { const struct mg_callbacks *callbacks; /* callback function pointer */ void *user_data; /* data */ const char **configuration_options; }; #if defined(MG_EXPERIMENTAL_INTERFACES) CIVETWEB_API struct mg_connection * mg_connect_client2(const char *host, const char *protocol, int port, const char *path, struct mg_init_data *init, struct mg_error_data *error); CIVETWEB_API int mg_get_response2(struct mg_connection *conn, struct mg_error_data *error, int timeout); #endif CIVETWEB_API struct mg_context *mg_start2(struct mg_init_data *init, struct mg_error_data *error); CIVETWEB_API int mg_start_domain2(struct mg_context *ctx, const char **configuration_options, struct mg_error_data *error); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* CIVETWEB_HEADER_INCLUDED */ webfakes/src/http2.h0000644000176200001440000020000114740430263014036 0ustar liggesusers/* Prototype implementation for HTTP2. Do not use in production. * There may be memory leaks, security vulnerabilities, ... */ /***********************************************************************/ /*** HPACK ***/ /***********************************************************************/ /* hpack predefined table. See: * https://tools.ietf.org/html/rfc7541#appendix-A */ static struct mg_header hpack_predefined[62] = {{NULL, NULL}, {":authority", NULL}, {":method", "GET"}, {":method", "POST"}, {":path", "/"}, {":path", "/index.html"}, {":scheme", "http"}, {":scheme", "https"}, {":status", "200"}, {":status", "204"}, {":status", "206"}, {":status", "304"}, {":status", "400"}, {":status", "404"}, {":status", "500"}, {"accept-charset", NULL}, {"accept-encoding", NULL}, {"accept-language", NULL}, {"accept-ranges", NULL}, {"accept", NULL}, {"access-control-allow-origin", NULL}, {"age", NULL}, {"allow", NULL}, {"authorization", NULL}, {"cache-control", NULL}, {"content-encoding", NULL}, {"content-disposition", NULL}, {"content-language", NULL}, {"content-length", NULL}, {"content-location", NULL}, {"content-range", NULL}, {"content-type", NULL}, {"cookie", NULL}, {"date", NULL}, {"etag", NULL}, {"expect", NULL}, {"expires", NULL}, {"from", NULL}, {"host", NULL}, {"if-match", NULL}, {"if-modified-since", NULL}, {"if-none-match", NULL}, {"if-range", NULL}, {"if-unmodified-since", NULL}, {"last-modified", NULL}, {"link", NULL}, {"location", NULL}, {"max-forwards", NULL}, {"proxy-authenticate", NULL}, {"proxy-authorization", NULL}, {"range", NULL}, {"referer", NULL}, {"refresh", NULL}, {"retry-after", NULL}, {"server", NULL}, {"set-cookie", NULL}, {"strict-transport-security", NULL}, {"transfer-encoding", NULL}, {"user-agent", NULL}, {"vary", NULL}, {"via", NULL}, {"www-authenticate", NULL}}; /* Huffman decoding: https://tools.ietf.org/html/rfc7541#appendix-B '0' ( 48) |00000 0 [ 5] '1' ( 49) |00001 1 [ 5] '2' ( 50) |00010 2 [ 5] 'a' ( 97) |00011 3 [ 5] 'c' ( 99) |00100 4 [ 5] 'e' (101) |00101 5 [ 5] 'i' (105) |00110 6 [ 5] 'o' (111) |00111 7 [ 5] 's' (115) |01000 8 [ 5] 't' (116) |01001 9 [ 5] ' ' ( 32) |010100 14 [ 6] '%' ( 37) |010101 15 [ 6] '-' ( 45) |010110 16 [ 6] '.' ( 46) |010111 17 [ 6] '/' ( 47) |011000 18 [ 6] '3' ( 51) |011001 19 [ 6] '4' ( 52) |011010 1a [ 6] '5' ( 53) |011011 1b [ 6] '6' ( 54) |011100 1c [ 6] '7' ( 55) |011101 1d [ 6] '8' ( 56) |011110 1e [ 6] '9' ( 57) |011111 1f [ 6] '=' ( 61) |100000 20 [ 6] 'A' ( 65) |100001 21 [ 6] '_' ( 95) |100010 22 [ 6] 'b' ( 98) |100011 23 [ 6] 'd' (100) |100100 24 [ 6] 'f' (102) |100101 25 [ 6] 'g' (103) |100110 26 [ 6] 'h' (104) |100111 27 [ 6] 'l' (108) |101000 28 [ 6] 'm' (109) |101001 29 [ 6] 'n' (110) |101010 2a [ 6] 'p' (112) |101011 2b [ 6] 'r' (114) |101100 2c [ 6] 'u' (117) |101101 2d [ 6] ':' ( 58) |1011100 5c [ 7] 'B' ( 66) |1011101 5d [ 7] 'C' ( 67) |1011110 5e [ 7] 'D' ( 68) |1011111 5f [ 7] 'E' ( 69) |1100000 60 [ 7] 'F' ( 70) |1100001 61 [ 7] 'G' ( 71) |1100010 62 [ 7] 'H' ( 72) |1100011 63 [ 7] 'I' ( 73) |1100100 64 [ 7] 'J' ( 74) |1100101 65 [ 7] 'K' ( 75) |1100110 66 [ 7] 'L' ( 76) |1100111 67 [ 7] 'M' ( 77) |1101000 68 [ 7] 'N' ( 78) |1101001 69 [ 7] 'O' ( 79) |1101010 6a [ 7] 'P' ( 80) |1101011 6b [ 7] 'Q' ( 81) |1101100 6c [ 7] 'R' ( 82) |1101101 6d [ 7] 'S' ( 83) |1101110 6e [ 7] 'T' ( 84) |1101111 6f [ 7] 'U' ( 85) |1110000 70 [ 7] 'V' ( 86) |1110001 71 [ 7] 'W' ( 87) |1110010 72 [ 7] 'Y' ( 89) |1110011 73 [ 7] 'j' (106) |1110100 74 [ 7] 'k' (107) |1110101 75 [ 7] 'q' (113) |1110110 76 [ 7] 'v' (118) |1110111 77 [ 7] 'w' (119) |1111000 78 [ 7] 'x' (120) |1111001 79 [ 7] 'y' (121) |1111010 7a [ 7] 'z' (122) |1111011 7b [ 7] '&' ( 38) |11111000 f8 [ 8] '*' ( 42) |11111001 f9 [ 8] ',' ( 44) |11111010 fa [ 8] ';' ( 59) |11111011 fb [ 8] 'X' ( 88) |11111100 fc [ 8] 'Z' ( 90) |11111101 fd [ 8] '!' ( 33) |11111110|00 3f8 [10] '"' ( 34) |11111110|01 3f9 [10] '(' ( 40) |11111110|10 3fa [10] ')' ( 41) |11111110|11 3fb [10] '?' ( 63) |11111111|00 3fc [10] ''' ( 39) |11111111|010 7fa [11] '+' ( 43) |11111111|011 7fb [11] '|' (124) |11111111|100 7fc [11] '#' ( 35) |11111111|1010 ffa [12] '>' ( 62) |11111111|1011 ffb [12] ( 0) |11111111|11000 1ff8 [13] '$' ( 36) |11111111|11001 1ff9 [13] '@' ( 64) |11111111|11010 1ffa [13] '[' ( 91) |11111111|11011 1ffb [13] ']' ( 93) |11111111|11100 1ffc [13] '~' (126) |11111111|11101 1ffd [13] '^' ( 94) |11111111|111100 3ffc [14] '}' (125) |11111111|111101 3ffd [14] '<' ( 60) |11111111|1111100 7ffc [15] '`' ( 96) |11111111|1111101 7ffd [15] '{' (123) |11111111|1111110 7ffe [15] '\' ( 92) |11111111|11111110|000 7fff0 [19] (195) |11111111|11111110|001 7fff1 [19] (208) |11111111|11111110|010 7fff2 [19] (128) |11111111|11111110|0110 fffe6 [20] (130) |11111111|11111110|0111 fffe7 [20] (131) |11111111|11111110|1000 fffe8 [20] (162) |11111111|11111110|1001 fffe9 [20] (184) |11111111|11111110|1010 fffea [20] (194) |11111111|11111110|1011 fffeb [20] (224) |11111111|11111110|1100 fffec [20] (226) |11111111|11111110|1101 fffed [20] (153) |11111111|11111110|11100 1fffdc [21] (161) |11111111|11111110|11101 1fffdd [21] (167) |11111111|11111110|11110 1fffde [21] (172) |11111111|11111110|11111 1fffdf [21] (176) |11111111|11111111|00000 1fffe0 [21] (177) |11111111|11111111|00001 1fffe1 [21] (179) |11111111|11111111|00010 1fffe2 [21] (209) |11111111|11111111|00011 1fffe3 [21] (216) |11111111|11111111|00100 1fffe4 [21] (217) |11111111|11111111|00101 1fffe5 [21] (227) |11111111|11111111|00110 1fffe6 [21] (229) |11111111|11111111|00111 1fffe7 [21] (230) |11111111|11111111|01000 1fffe8 [21] (129) |11111111|11111111|010010 3fffd2 [22] (132) |11111111|11111111|010011 3fffd3 [22] (133) |11111111|11111111|010100 3fffd4 [22] (134) |11111111|11111111|010101 3fffd5 [22] (136) |11111111|11111111|010110 3fffd6 [22] (146) |11111111|11111111|010111 3fffd7 [22] (154) |11111111|11111111|011000 3fffd8 [22] (156) |11111111|11111111|011001 3fffd9 [22] (160) |11111111|11111111|011010 3fffda [22] (163) |11111111|11111111|011011 3fffdb [22] (164) |11111111|11111111|011100 3fffdc [22] (169) |11111111|11111111|011101 3fffdd [22] (170) |11111111|11111111|011110 3fffde [22] (173) |11111111|11111111|011111 3fffdf [22] (178) |11111111|11111111|100000 3fffe0 [22] (181) |11111111|11111111|100001 3fffe1 [22] (185) |11111111|11111111|100010 3fffe2 [22] (186) |11111111|11111111|100011 3fffe3 [22] (187) |11111111|11111111|100100 3fffe4 [22] (189) |11111111|11111111|100101 3fffe5 [22] (190) |11111111|11111111|100110 3fffe6 [22] (196) |11111111|11111111|100111 3fffe7 [22] (198) |11111111|11111111|101000 3fffe8 [22] (228) |11111111|11111111|101001 3fffe9 [22] (232) |11111111|11111111|101010 3fffea [22] (233) |11111111|11111111|101011 3fffeb [22] ( 1) |11111111|11111111|1011000 7fffd8 [23] (135) |11111111|11111111|1011001 7fffd9 [23] (137) |11111111|11111111|1011010 7fffda [23] (138) |11111111|11111111|1011011 7fffdb [23] (139) |11111111|11111111|1011100 7fffdc [23] (140) |11111111|11111111|1011101 7fffdd [23] (141) |11111111|11111111|1011110 7fffde [23] (143) |11111111|11111111|1011111 7fffdf [23] (147) |11111111|11111111|1100000 7fffe0 [23] (149) |11111111|11111111|1100001 7fffe1 [23] (150) |11111111|11111111|1100010 7fffe2 [23] (151) |11111111|11111111|1100011 7fffe3 [23] (152) |11111111|11111111|1100100 7fffe4 [23] (155) |11111111|11111111|1100101 7fffe5 [23] (157) |11111111|11111111|1100110 7fffe6 [23] (158) |11111111|11111111|1100111 7fffe7 [23] (165) |11111111|11111111|1101000 7fffe8 [23] (166) |11111111|11111111|1101001 7fffe9 [23] (168) |11111111|11111111|1101010 7fffea [23] (174) |11111111|11111111|1101011 7fffeb [23] (175) |11111111|11111111|1101100 7fffec [23] (180) |11111111|11111111|1101101 7fffed [23] (182) |11111111|11111111|1101110 7fffee [23] (183) |11111111|11111111|1101111 7fffef [23] (188) |11111111|11111111|1110000 7ffff0 [23] (191) |11111111|11111111|1110001 7ffff1 [23] (197) |11111111|11111111|1110010 7ffff2 [23] (231) |11111111|11111111|1110011 7ffff3 [23] (239) |11111111|11111111|1110100 7ffff4 [23] ( 9) |11111111|11111111|11101010 ffffea [24] (142) |11111111|11111111|11101011 ffffeb [24] (144) |11111111|11111111|11101100 ffffec [24] (145) |11111111|11111111|11101101 ffffed [24] (148) |11111111|11111111|11101110 ffffee [24] (159) |11111111|11111111|11101111 ffffef [24] (171) |11111111|11111111|11110000 fffff0 [24] (206) |11111111|11111111|11110001 fffff1 [24] (215) |11111111|11111111|11110010 fffff2 [24] (225) |11111111|11111111|11110011 fffff3 [24] (236) |11111111|11111111|11110100 fffff4 [24] (237) |11111111|11111111|11110101 fffff5 [24] (199) |11111111|11111111|11110110|0 1ffffec [25] (207) |11111111|11111111|11110110|1 1ffffed [25] (234) |11111111|11111111|11110111|0 1ffffee [25] (235) |11111111|11111111|11110111|1 1ffffef [25] (192) |11111111|11111111|11111000|00 3ffffe0 [26] (193) |11111111|11111111|11111000|01 3ffffe1 [26] (200) |11111111|11111111|11111000|10 3ffffe2 [26] (201) |11111111|11111111|11111000|11 3ffffe3 [26] (202) |11111111|11111111|11111001|00 3ffffe4 [26] (205) |11111111|11111111|11111001|01 3ffffe5 [26] (210) |11111111|11111111|11111001|10 3ffffe6 [26] (213) |11111111|11111111|11111001|11 3ffffe7 [26] (218) |11111111|11111111|11111010|00 3ffffe8 [26] (219) |11111111|11111111|11111010|01 3ffffe9 [26] (238) |11111111|11111111|11111010|10 3ffffea [26] (240) |11111111|11111111|11111010|11 3ffffeb [26] (242) |11111111|11111111|11111011|00 3ffffec [26] (243) |11111111|11111111|11111011|01 3ffffed [26] (255) |11111111|11111111|11111011|10 3ffffee [26] (203) |11111111|11111111|11111011|110 7ffffde [27] (204) |11111111|11111111|11111011|111 7ffffdf [27] (211) |11111111|11111111|11111100|000 7ffffe0 [27] (212) |11111111|11111111|11111100|001 7ffffe1 [27] (214) |11111111|11111111|11111100|010 7ffffe2 [27] (221) |11111111|11111111|11111100|011 7ffffe3 [27] (222) |11111111|11111111|11111100|100 7ffffe4 [27] (223) |11111111|11111111|11111100|101 7ffffe5 [27] (241) |11111111|11111111|11111100|110 7ffffe6 [27] (244) |11111111|11111111|11111100|111 7ffffe7 [27] (245) |11111111|11111111|11111101|000 7ffffe8 [27] (246) |11111111|11111111|11111101|001 7ffffe9 [27] (247) |11111111|11111111|11111101|010 7ffffea [27] (248) |11111111|11111111|11111101|011 7ffffeb [27] (250) |11111111|11111111|11111101|100 7ffffec [27] (251) |11111111|11111111|11111101|101 7ffffed [27] (252) |11111111|11111111|11111101|110 7ffffee [27] (253) |11111111|11111111|11111101|111 7ffffef [27] (254) |11111111|11111111|11111110|000 7fffff0 [27] ( 2) |11111111|11111111|11111110|0010 fffffe2 [28] ( 3) |11111111|11111111|11111110|0011 fffffe3 [28] ( 4) |11111111|11111111|11111110|0100 fffffe4 [28] ( 5) |11111111|11111111|11111110|0101 fffffe5 [28] ( 6) |11111111|11111111|11111110|0110 fffffe6 [28] ( 7) |11111111|11111111|11111110|0111 fffffe7 [28] ( 8) |11111111|11111111|11111110|1000 fffffe8 [28] ( 11) |11111111|11111111|11111110|1001 fffffe9 [28] ( 12) |11111111|11111111|11111110|1010 fffffea [28] ( 14) |11111111|11111111|11111110|1011 fffffeb [28] ( 15) |11111111|11111111|11111110|1100 fffffec [28] ( 16) |11111111|11111111|11111110|1101 fffffed [28] ( 17) |11111111|11111111|11111110|1110 fffffee [28] ( 18) |11111111|11111111|11111110|1111 fffffef [28] ( 19) |11111111|11111111|11111111|0000 ffffff0 [28] ( 20) |11111111|11111111|11111111|0001 ffffff1 [28] ( 21) |11111111|11111111|11111111|0010 ffffff2 [28] ( 23) |11111111|11111111|11111111|0011 ffffff3 [28] ( 24) |11111111|11111111|11111111|0100 ffffff4 [28] ( 25) |11111111|11111111|11111111|0101 ffffff5 [28] ( 26) |11111111|11111111|11111111|0110 ffffff6 [28] ( 27) |11111111|11111111|11111111|0111 ffffff7 [28] ( 28) |11111111|11111111|11111111|1000 ffffff8 [28] ( 29) |11111111|11111111|11111111|1001 ffffff9 [28] ( 30) |11111111|11111111|11111111|1010 ffffffa [28] ( 31) |11111111|11111111|11111111|1011 ffffffb [28] (127) |11111111|11111111|11111111|1100 ffffffc [28] (220) |11111111|11111111|11111111|1101 ffffffd [28] (249) |11111111|11111111|11111111|1110 ffffffe [28] ( 10) |11111111|11111111|11111111|111100 3ffffffc [30] ( 13) |11111111|11111111|11111111|111101 3ffffffd [30] ( 22) |11111111|11111111|11111111|111110 3ffffffe [30] (256) |11111111|11111111|11111111|111111 3fffffff [30] */ struct { uint8_t decoded; uint8_t bitcount; uint32_t encoded; } hpack_huff_dec[] = { {48, 5, 0x0}, {49, 5, 0x1}, {50, 5, 0x2}, {97, 5, 0x3}, {99, 5, 0x4}, {101, 5, 0x5}, {105, 5, 0x6}, {111, 5, 0x7}, {115, 5, 0x8}, {116, 5, 0x9}, {32, 6, 0x14}, {37, 6, 0x15}, {45, 6, 0x16}, {46, 6, 0x17}, {47, 6, 0x18}, {51, 6, 0x19}, {52, 6, 0x1a}, {53, 6, 0x1b}, {54, 6, 0x1c}, {55, 6, 0x1d}, {56, 6, 0x1e}, {57, 6, 0x1f}, {61, 6, 0x20}, {65, 6, 0x21}, {95, 6, 0x22}, {98, 6, 0x23}, {100, 6, 0x24}, {102, 6, 0x25}, {103, 6, 0x26}, {104, 6, 0x27}, {108, 6, 0x28}, {109, 6, 0x29}, {110, 6, 0x2a}, {112, 6, 0x2b}, {114, 6, 0x2c}, {117, 6, 0x2d}, {58, 7, 0x5c}, {66, 7, 0x5d}, {67, 7, 0x5e}, {68, 7, 0x5f}, {69, 7, 0x60}, {70, 7, 0x61}, {71, 7, 0x62}, {72, 7, 0x63}, {73, 7, 0x64}, {74, 7, 0x65}, {75, 7, 0x66}, {76, 7, 0x67}, {77, 7, 0x68}, {78, 7, 0x69}, {79, 7, 0x6a}, {80, 7, 0x6b}, {81, 7, 0x6c}, {82, 7, 0x6d}, {83, 7, 0x6e}, {84, 7, 0x6f}, {85, 7, 0x70}, {86, 7, 0x71}, {87, 7, 0x72}, {89, 7, 0x73}, {106, 7, 0x74}, {107, 7, 0x75}, {113, 7, 0x76}, {118, 7, 0x77}, {119, 7, 0x78}, {120, 7, 0x79}, {121, 7, 0x7a}, {122, 7, 0x7b}, {38, 8, 0xf8}, {42, 8, 0xf9}, {44, 8, 0xfa}, {59, 8, 0xfb}, {88, 8, 0xfc}, {90, 8, 0xfd}, {33, 10, 0x3f8}, {34, 10, 0x3f9}, {40, 10, 0x3fa}, {41, 10, 0x3fb}, {63, 10, 0x3fc}, {39, 11, 0x7fa}, {43, 11, 0x7fb}, {124, 11, 0x7fc}, {35, 12, 0xffa}, {62, 12, 0xffb}, {0, 13, 0x1ff8}, {36, 13, 0x1ff9}, {64, 13, 0x1ffa}, {91, 13, 0x1ffb}, {93, 13, 0x1ffc}, {126, 13, 0x1ffd}, {94, 14, 0x3ffc}, {125, 14, 0x3ffd}, {60, 15, 0x7ffc}, {96, 15, 0x7ffd}, {123, 15, 0x7ffe}, {92, 19, 0x7fff0}, {195, 19, 0x7fff1}, {208, 19, 0x7fff2}, {128, 20, 0xfffe6}, {130, 20, 0xfffe7}, {131, 20, 0xfffe8}, {162, 20, 0xfffe9}, {184, 20, 0xfffea}, {194, 20, 0xfffeb}, {224, 20, 0xfffec}, {226, 20, 0xfffed}, {153, 21, 0x1fffdc}, {161, 21, 0x1fffdd}, {167, 21, 0x1fffde}, {172, 21, 0x1fffdf}, {176, 21, 0x1fffe0}, {177, 21, 0x1fffe1}, {179, 21, 0x1fffe2}, {209, 21, 0x1fffe3}, {216, 21, 0x1fffe4}, {217, 21, 0x1fffe5}, {227, 21, 0x1fffe6}, {229, 21, 0x1fffe7}, {230, 21, 0x1fffe8}, {129, 22, 0x3fffd2}, {132, 22, 0x3fffd3}, {133, 22, 0x3fffd4}, {134, 22, 0x3fffd5}, {136, 22, 0x3fffd6}, {146, 22, 0x3fffd7}, {154, 22, 0x3fffd8}, {156, 22, 0x3fffd9}, {160, 22, 0x3fffda}, {163, 22, 0x3fffdb}, {164, 22, 0x3fffdc}, {169, 22, 0x3fffdd}, {170, 22, 0x3fffde}, {173, 22, 0x3fffdf}, {178, 22, 0x3fffe0}, {181, 22, 0x3fffe1}, {185, 22, 0x3fffe2}, {186, 22, 0x3fffe3}, {187, 22, 0x3fffe4}, {189, 22, 0x3fffe5}, {190, 22, 0x3fffe6}, {196, 22, 0x3fffe7}, {198, 22, 0x3fffe8}, {228, 22, 0x3fffe9}, {232, 22, 0x3fffea}, {233, 22, 0x3fffeb}, {1, 23, 0x7fffd8}, {135, 23, 0x7fffd9}, {137, 23, 0x7fffda}, {138, 23, 0x7fffdb}, {139, 23, 0x7fffdc}, {140, 23, 0x7fffdd}, {141, 23, 0x7fffde}, {143, 23, 0x7fffdf}, {147, 23, 0x7fffe0}, {149, 23, 0x7fffe1}, {150, 23, 0x7fffe2}, {151, 23, 0x7fffe3}, {152, 23, 0x7fffe4}, {155, 23, 0x7fffe5}, {157, 23, 0x7fffe6}, {158, 23, 0x7fffe7}, {165, 23, 0x7fffe8}, {166, 23, 0x7fffe9}, {168, 23, 0x7fffea}, {174, 23, 0x7fffeb}, {175, 23, 0x7fffec}, {180, 23, 0x7fffed}, {182, 23, 0x7fffee}, {183, 23, 0x7fffef}, {188, 23, 0x7ffff0}, {191, 23, 0x7ffff1}, {197, 23, 0x7ffff2}, {231, 23, 0x7ffff3}, {239, 23, 0x7ffff4}, {9, 24, 0xffffea}, {142, 24, 0xffffeb}, {144, 24, 0xffffec}, {145, 24, 0xffffed}, {148, 24, 0xffffee}, {159, 24, 0xffffef}, {171, 24, 0xfffff0}, {206, 24, 0xfffff1}, {215, 24, 0xfffff2}, {225, 24, 0xfffff3}, {236, 24, 0xfffff4}, {237, 24, 0xfffff5}, {199, 25, 0x1ffffec}, {207, 25, 0x1ffffed}, {234, 25, 0x1ffffee}, {235, 25, 0x1ffffef}, {192, 26, 0x3ffffe0}, {193, 26, 0x3ffffe1}, {200, 26, 0x3ffffe2}, {201, 26, 0x3ffffe3}, {202, 26, 0x3ffffe4}, {205, 26, 0x3ffffe5}, {210, 26, 0x3ffffe6}, {213, 26, 0x3ffffe7}, {218, 26, 0x3ffffe8}, {219, 26, 0x3ffffe9}, {238, 26, 0x3ffffea}, {240, 26, 0x3ffffeb}, {242, 26, 0x3ffffec}, {243, 26, 0x3ffffed}, {255, 26, 0x3ffffee}, {203, 27, 0x7ffffde}, {204, 27, 0x7ffffdf}, {211, 27, 0x7ffffe0}, {212, 27, 0x7ffffe1}, {214, 27, 0x7ffffe2}, {221, 27, 0x7ffffe3}, {222, 27, 0x7ffffe4}, {223, 27, 0x7ffffe5}, {241, 27, 0x7ffffe6}, {244, 27, 0x7ffffe7}, {245, 27, 0x7ffffe8}, {246, 27, 0x7ffffe9}, {247, 27, 0x7ffffea}, {248, 27, 0x7ffffeb}, {250, 27, 0x7ffffec}, {251, 27, 0x7ffffed}, {252, 27, 0x7ffffee}, {253, 27, 0x7ffffef}, {254, 27, 0x7fffff0}, {2, 28, 0xfffffe2}, {3, 28, 0xfffffe3}, {4, 28, 0xfffffe4}, {5, 28, 0xfffffe5}, {6, 28, 0xfffffe6}, {7, 28, 0xfffffe7}, {8, 28, 0xfffffe8}, {11, 28, 0xfffffe9}, {12, 28, 0xfffffea}, {14, 28, 0xfffffeb}, {15, 28, 0xfffffec}, {16, 28, 0xfffffed}, {17, 28, 0xfffffee}, {18, 28, 0xfffffef}, {19, 28, 0xffffff0}, {20, 28, 0xffffff1}, {21, 28, 0xffffff2}, {23, 28, 0xffffff3}, {24, 28, 0xffffff4}, {25, 28, 0xffffff5}, {26, 28, 0xffffff6}, {27, 28, 0xffffff7}, {28, 28, 0xffffff8}, {29, 28, 0xffffff9}, {30, 28, 0xffffffa}, {31, 28, 0xffffffb}, {127, 28, 0xffffffc}, {220, 28, 0xffffffd}, {249, 28, 0xffffffe}, {10, 30, 0x3ffffffc}, {13, 30, 0x3ffffffd}, {22, 30, 0x3ffffffe}, {(uint8_t)256, 30, 0x3fffffff} /* filling/termination */ }; /* highest value with 5, 6, 7, ... 28, 29, 30 and all (32) bits */ uint32_t hpack_huff_end_code[] = {0x9, 0x2d, 0x7b, 0xfd, 0, 0x3fc, 0x7fc, 0xffb, 0x1ffd, 0x3ffd, 0x7ffe, 0, 0, 0, 0x7fff2, 0xfffed, 0x1fffe8, 0x3fffeb, 0x7ffff4, 0xfffff5, 0x1ffffef, 0x3ffffee, 0x7fffff0, 0xffffffe, 0, 0x3ffffffe, 0xFFFFFFFFu}; /* lowest index with 5, 6, 7, ... 28, 29, 30 and all (32) bits */ uint8_t hpack_huff_start_index[] = {0, 10, 36, 68, 0, 74, 79, 82, 84, 90, 92, 0, 0, 0, 95, 98, 106, 119, 145, 174, 186, 190, 205, 224, 0, 253, 0}; /* Function to decode an integer from a HPACK encoded block */ /* Integers have a variable size encoding, according to the RFC. * The integer starts at index *i, idx_mask masks the available bits in * the first byte. The index *i is advanced until the end of the * encoded integer. */ static uint64_t hpack_getnum(const uint8_t *buf, int *i, uint8_t idx_mask, struct mg_context *ctx) { uint64_t num = (buf[*i] & idx_mask); (void)ctx; if (num == idx_mask) { /* Algorithm from https://tools.ietf.org/html/rfc7541#section-5.1 */ uint32_t M = 0; do { (*i)++; num = num + ((buf[*i] & 0x7F) << M); M += 7; } while ((buf[*i] & 0x80) == 0x80); } (*i)++; return num; } /* Function to decode a string from a HPACK encoded block */ /* Strings have a variable size and can be either encoded directly (8 bits * per char), or using huffman encoding (variable bits per char). * The string starts at index *i. This index is advanced until the end of * the encoded string. */ static char * hpack_decode(const uint8_t *buf, int *i, int max_i, struct mg_context *ctx) { uint64_t byte_len64; int byte_len; int bit_len; uint8_t is_huff = ((buf[*i] & 0x80) == 0x80); /* Get length of string in bytes */ byte_len64 = hpack_getnum(buf, i, 0x7f, ctx); if (byte_len64 > 1024) { /* TODO */ return NULL; } byte_len = (int)byte_len64; bit_len = byte_len * 8; /* check size */ if ((*i) + byte_len > max_i) { return NULL; } /* Now read the string */ if (!is_huff) { /* Not huffman encoded: Copy directly */ char *result = (char *)mg_malloc_ctx(byte_len + 1, ctx); if (result) { memcpy(result, buf + (*i), byte_len); result[byte_len] = 0; } (*i) += byte_len; return result; } else { /* Huffman encoded: need to decode bitwise */ const uint8_t *pData = buf + (*i); /* begin pointer of bit input string */ int bitRead = 0; /* number of encoded bits read */ uint32_t bytesStored = 0; /* number of decoded bytes stored */ uint8_t str[2048]; /* storage buffer for decoded string */ for (;;) { uint32_t accu = 0; /* accu register: collect bits */ uint8_t bc = 0; /* number of bits collected */ int n; /* Collect bits in this loop, until we have a valid huff code in * accu */ do { accu <<= 1; accu |= (pData[bitRead / 8] >> (7 - (bitRead & 7))) & 1; bitRead++; bc++; if (bitRead > bit_len) { /* We used all bits. Return the decoded string. */ str[bytesStored] = 0; /* Terminate string */ (*i) += byte_len; /* Advance parsing index */ return mg_strdup_ctx((char *)str, ctx); /* Return a string copy */ } } while ((bc < 5) || (accu > hpack_huff_end_code[bc - 5])); /* Find matching code in huffman encoding table */ for (n = hpack_huff_start_index[bc - 5]; n < 256; n++) { if (accu == hpack_huff_dec[n].encoded) { str[bytesStored] = hpack_huff_dec[n].decoded; bytesStored++; break; } } if (bytesStored == sizeof(str)) { /* too long */ return 0; } } } } static void append_bits(uint8_t *target, uint32_t offset, uint32_t value, uint8_t value_bits) { uint32_t offset_bytes = offset / 8; uint32_t offset_bits = offset % 8; uint32_t remaining_bits, ac; value &= ~(0xFFFFFFFF << value_bits); remaining_bits = 8 - offset_bits; if (value_bits <= remaining_bits) { ac = value << (remaining_bits - value_bits); target[offset_bytes] |= ac; return; } ac = value >> (value_bits - remaining_bits); target[offset_bytes] |= ac; append_bits(target, offset + remaining_bits, value, value_bits - remaining_bits); } static int hpack_encode(uint8_t *store, const char *load, int lower) { uint32_t nohuff_len = strlen(load); uint32_t len_bits = 0; uint32_t len_bytes; uint32_t spare_bits; uint32_t i; memset(store, 0, nohuff_len + 1); for (i = 0; i < nohuff_len; i++) { uint8_t b = (uint8_t)((char)(lower ? tolower(load[i]) : load[i])); int idx; for (idx = 0; idx <= 255; idx++) { if (hpack_huff_dec[idx].decoded == b) { append_bits((uint8_t *)store + 1, len_bits, hpack_huff_dec[idx].encoded, hpack_huff_dec[idx].bitcount); len_bits += hpack_huff_dec[idx].bitcount; break; } } } len_bytes = (len_bits + 7) / 8; spare_bits = len_bytes * 8 - len_bits; if (spare_bits) { append_bits((uint8_t *)store + 1, len_bits, 0xFFFFFFFF, spare_bits); } if (len_bytes >= 127) { // TODO: Shift string and encode len in more bytes return 0; } *store = 0x80 + (uint8_t)len_bytes; if ((len_bytes >= nohuff_len) && (0)) { *store = (uint8_t)nohuff_len; if (lower) { for (i = 1; i <= nohuff_len; i++) { store[i] = tolower(load[i]); } } else { memcpy(store + 1, load, nohuff_len); } return nohuff_len + 1; } else { /* int i = 0; char *test = hpack_decode(store, &i, NULL); i = i; // breakpoint for debugging / testing */ } return len_bytes + 1; } /***********************************************************************/ /*** HTTP 2 ***/ /***********************************************************************/ static const char http2_pri[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; static const unsigned char http2_pri_len = 24; /* = strlen(http2_pri) */ /* Read and check the HTTP/2 primer/preface: * See https://tools.ietf.org/html/rfc7540#section-3.5 */ static int is_valid_http2_primer(struct mg_connection *conn) { size_t pri_len = http2_pri_len; char buf[32]; /* Buffer must hold 24 bytes primer */ int read_pri_len = mg_read(conn, buf, pri_len); if (read_pri_len != (int)pri_len) { /* Size does not match. * This includes cases where mg_read returns error codes */ return 0; } if (0 != memcmp(buf, http2_pri, pri_len)) { /* Primer does not match */ return 0; } /* Primer does match */ return 1; } #define mg_xwrite(conn, data, len) \ push_all((conn)->phys_ctx, \ NULL, \ (conn)->client.sock, \ (conn)->ssl, \ (const char *)(data), \ (int)(len)) static void http2_settings_acknowledge(struct mg_connection *conn) { unsigned char http2_set_ackn_frame[9] = {0, 0, 0, 4, 1, 0, 0, 0, 0}; DEBUG_TRACE("%s", "Sending settings frame"); mg_xwrite(conn, http2_set_ackn_frame, 9); } struct http2_settings { uint32_t settings_header_table_size; uint32_t settings_enable_push; uint32_t settings_max_concurrent_streams; uint32_t settings_initial_window_size; uint32_t settings_max_frame_size; uint32_t settings_max_header_list_size; }; const struct http2_settings http2_default_settings = {4096, 1, UINT32_MAX, 65535, 16384, UINT32_MAX}; const struct http2_settings http2_civetweb_server_settings = {4096, 0, 100, 65535, 16384, 65535}; enum { HTTP2_ERR_NO_ERROR = 0, HTTP2_ERR_PROTOCOL_ERROR, HTTP2_ERR_INTERNAL_ERROR, HTTP2_ERR_FLOW_CONTROL_ERROR, HTTP2_ERR_SETTINGS_TIMEOUT, HTTP2_ERR_STREAM_CLOSED, HTTP2_ERR_FRAME_SIZE_ERROR, HTTP2_ERR_REFUSED_STREAM, HTTP2_ERR_CANCEL, HTTP2_ERR_COMPRESSION_ERROR, HTTP2_ERR_CONNECT_ERROR, HTTP2_ERR_ENHANCE_YOUR_CALM, HTTP2_ERR_INADEQUATE_SECURITY, HTTP2_ERR_HTTP_1_1_REQUIRED }; static void http2_send_settings(struct mg_connection *conn, const struct http2_settings *set) { uint16_t id; uint32_t data; uint8_t http2_settings_frame[9] = {0, 0, 36, 4, 0, 0, 0, 0, 0}; mg_xwrite(conn, http2_settings_frame, 9); id = htons(1); data = htonl(set->settings_header_table_size); mg_xwrite(conn, &id, 2); mg_xwrite(conn, &data, 4); id = htons(1); data = htonl(set->settings_enable_push); mg_xwrite(conn, &id, 2); mg_xwrite(conn, &data, 4); id = htons(1); data = htonl(set->settings_max_concurrent_streams); mg_xwrite(conn, &id, 2); mg_xwrite(conn, &data, 4); id = htons(1); data = htonl(set->settings_initial_window_size); mg_xwrite(conn, &id, 2); mg_xwrite(conn, &data, 4); id = htons(1); data = htonl(set->settings_max_frame_size); mg_xwrite(conn, &id, 2); mg_xwrite(conn, &data, 4); id = htons(1); data = htonl(set->settings_max_header_list_size); mg_xwrite(conn, &id, 2); mg_xwrite(conn, &data, 4); DEBUG_TRACE("%s", "HTTP2 settings sent"); } static int http2_send_response_headers(struct mg_connection *conn) { unsigned char http2_header_frame[9] = {0, 0, 0, 1, 4, 0, 0, 0, 0}; uint8_t header_bin[1024]; uint16_t header_len = 0; int has_date = 0; int has_connection_header = 0; int i, ok; if ((conn->status_code < 100) || (conn->status_code > 999)) { /* Invalid status: Set status to "Internal Server Error" */ conn->status_code = 500; } switch (conn->status_code) { case 200: header_bin[header_len++] = 0x88; break; case 204: header_bin[header_len++] = 0x89; break; case 206: header_bin[header_len++] = 0x8A; break; case 304: header_bin[header_len++] = 0x8B; break; case 400: header_bin[header_len++] = 0x8C; break; case 404: header_bin[header_len++] = 0x8D; break; case 500: header_bin[header_len++] = 0x8E; break; default: header_bin[header_len++] = 0x48; header_bin[header_len++] = 0x03; header_bin[header_len++] = 0x30 + (conn->status_code / 100); header_bin[header_len++] = 0x30 + ((conn->status_code / 10) % 10); header_bin[header_len++] = 0x30 + (conn->status_code % 10); break; } /* Add all headers */ for (i = 0; i < conn->response_info.num_headers; i++) { uint16_t predef = 0; uint16_t j; /* Filter headers not valid in HTTP/2 */ if (!mg_strcasecmp("Connection", conn->response_info.http_headers[i].name)) { has_connection_header = 1; continue; /* do not send */ } /* Check if this header is known in HPACK (static table index 15 to 61) * see https://tools.ietf.org/html/rfc7541#appendix-A */ for (j = 15; j <= 61; j++) { if (!mg_strcasecmp(hpack_predefined[j].name, conn->response_info.http_headers[i].name)) { predef = j; break; } } if (predef) { /* Predefined header found */ header_bin[header_len++] = 0x40 + predef; } else { /* Rare header, do not index */ header_bin[header_len++] = 0x10; j = hpack_encode(header_bin + header_len, conn->response_info.http_headers[i].name, 1); header_len += j; } j = hpack_encode(header_bin + header_len, conn->response_info.http_headers[i].value, 0); header_len += j; /* Mark required headers as sent */ if (!mg_strcasecmp("Date", conn->response_info.http_headers[i].name)) { has_date = 1; } } /* Add required headers, if they have not been sent yet */ if (!has_date) { /* Create header frame */ char date[64]; uint8_t date_len; time_t curtime = time(NULL); gmt_time_string(date, sizeof(date), &curtime); date_len = (uint8_t)strlen(date); header_bin[header_len++] = 0x61; /* "Date" predefined HPACK index 33 (0x21) + 0x40 */ header_bin[header_len++] = date_len; memcpy(header_bin + header_len, date, date_len); header_len += date_len; } http2_header_frame[1] = (header_len & 0xFF00) >> 8; http2_header_frame[2] = (header_len & 0xFF); http2_header_frame[5] = (conn->http2.stream_id & 0xFF000000u) >> 24; http2_header_frame[6] = (conn->http2.stream_id & 0xFF0000u) >> 16; http2_header_frame[7] = (conn->http2.stream_id & 0xFF00u) >> 8; http2_header_frame[8] = (conn->http2.stream_id & 0xFFu); /* Send header frame */ ok = 1; if (mg_xwrite(conn, http2_header_frame, 9) != 9) { ok = 0; } else if (mg_xwrite(conn, header_bin, header_len) != header_len) { ok = 0; } if (ok) { DEBUG_TRACE("HTTP2 response header sent: stream %u", conn->http2.stream_id); } else { DEBUG_TRACE("HTTP2 response header sending error: stream %u", conn->http2.stream_id); } (void)has_connection_header; /* ignore for the moment */ return ok; } static void http2_data_frame_head(struct mg_connection *conn, uint32_t frame_size, int is_final) { unsigned char http2_data_frame[9]; uint32_t stream_id = conn->http2.stream_id; http2_data_frame[0] = (frame_size & 0xFF0000) >> 16; http2_data_frame[1] = (frame_size & 0xFF00) >> 8; http2_data_frame[2] = (frame_size & 0xFF); http2_data_frame[3] = 0; /* frame type "DATA" */ http2_data_frame[4] = (is_final ? 1 : 0); http2_data_frame[5] = (stream_id & 0xFF000000u) >> 24; http2_data_frame[6] = (stream_id & 0xFF0000u) >> 16; http2_data_frame[7] = (stream_id & 0xFF00u) >> 8; http2_data_frame[8] = (stream_id & 0xFFu); DEBUG_TRACE("HTTP2 begin data frame: stream %u, frame_size %u (final: %i)", stream_id, frame_size, is_final); mg_xwrite(conn, http2_data_frame, 9); } static void http2_send_window(struct mg_connection *conn, uint32_t stream_id, uint32_t window_size) { unsigned char http2_window_frame[9] = {0, 0, 4, 8, 0, 0, 0, 0, 0}; uint32_t data = htonl(window_size); DEBUG_TRACE("HTTP2 send window_size: stream %u, error %u", stream_id, window_size); http2_window_frame[5] = (stream_id & 0xFF000000u) >> 24; http2_window_frame[6] = (stream_id & 0xFF0000u) >> 16; http2_window_frame[7] = (stream_id & 0xFF00u) >> 8; http2_window_frame[8] = (stream_id & 0xFFu); mg_xwrite(conn, http2_window_frame, 9); mg_xwrite(conn, &data, 4); } static void http2_reset_stream(struct mg_connection *conn, uint32_t stream_id, uint32_t error_id) { unsigned char http2_reset_frame[9] = {0, 0, 4, 3, 0, 0, 0, 0, 0}; uint32_t val = htonl(error_id); DEBUG_TRACE("HTTP2 send reset: stream %u, error %u", stream_id, error_id); http2_reset_frame[5] = (stream_id & 0xFF000000u) >> 24; http2_reset_frame[6] = (stream_id & 0xFF0000u) >> 16; http2_reset_frame[7] = (stream_id & 0xFF00u) >> 8; http2_reset_frame[8] = (stream_id & 0xFFu); mg_xwrite(conn, http2_reset_frame, 9); mg_xwrite(conn, &val, 4); } static void http2_must_use_http1(struct mg_connection *conn) { DEBUG_TRACE("HTTP2 not available for this URL (%s)", conn->path_info); http2_reset_stream(conn, conn->http2.stream_id, 0xd); } /* The HTTP2 implementation collects request headers as array of dynamically * allocated string values. This array must be freed once the request is * handled. * This is different to the HTTP/1.x implementation: For HTTP/1.x, the header * list is implemented as pointers into an existing buffer, so free must not * be called for HTTP/1.x. * Thus free_buffered_request_header_list is in mod_http2.inl. */ #if defined(DEBUG) static int mem_h_count = 0; static int mem_d_count = 0; #define CHECK_LEAK_HDR_ALLOC(ptr) \ DEBUG_TRACE("H NEW %p (%i): %s", ptr, ++mem_h_count, (const char *)ptr) #define CHECK_LEAK_HDR_FREE(ptr) \ DEBUG_TRACE("H DEL %p (%i): %s", ptr, --mem_h_count, (const char *)ptr) #define CHECK_LEAK_DYN_ALLOC(ptr) \ DEBUG_TRACE("D NEW %p (%i): %s", ptr, ++mem_d_count, (const char *)ptr) #define CHECK_LEAK_DYN_FREE(ptr) \ DEBUG_TRACE("D DEL %p (%i): %s", ptr, --mem_d_count, (const char *)ptr) #else #define CHECK_LEAK_HDR_ALLOC(ptr) #define CHECK_LEAK_HDR_FREE(ptr) #define CHECK_LEAK_DYN_ALLOC(ptr) #define CHECK_LEAK_DYN_FREE(ptr) #endif /* The dynamic header table may be resized on a HTTP2 client request. * A tablesize=0 will free all memory. */ static void purge_dynamic_header_table(struct mg_connection *conn, uint32_t tableSize) { DEBUG_TRACE("HTTP2 dynamic header table set to %u", tableSize); while (conn->http2.dyn_table_size > tableSize) { conn->http2.dyn_table_size--; CHECK_LEAK_DYN_FREE( conn->http2.dyn_table[conn->http2.dyn_table_size].name); CHECK_LEAK_DYN_FREE( conn->http2.dyn_table[conn->http2.dyn_table_size].value); mg_free((void *)conn->http2.dyn_table[conn->http2.dyn_table_size].name); conn->http2.dyn_table[conn->http2.dyn_table_size].name = 0; mg_free( (void *)conn->http2.dyn_table[conn->http2.dyn_table_size].value); conn->http2.dyn_table[conn->http2.dyn_table_size].value = 0; } } /* Internal function to free request header list. * Not to be confused with the response header list. */ static void free_buffered_request_header_list(struct mg_connection *conn) { while (conn->request_info.num_headers > 0) { conn->request_info.num_headers--; CHECK_LEAK_HDR_FREE( conn->request_info.http_headers[conn->request_info.num_headers] .name); CHECK_LEAK_HDR_FREE( conn->request_info.http_headers[conn->request_info.num_headers] .value); mg_free((void *)conn->request_info .http_headers[conn->request_info.num_headers] .name); conn->request_info.http_headers[conn->request_info.num_headers].name = 0; mg_free((void *)conn->request_info .http_headers[conn->request_info.num_headers] .value); conn->request_info.http_headers[conn->request_info.num_headers].value = 0; } } /* HTTP2 requires a different handling loop */ static void handle_http2(struct mg_connection *conn) { unsigned char http2_frame_head[9]; uint32_t http2_frame_size; uint8_t http2_frame_type; uint8_t http2_frame_flags; uint32_t http2_frame_stream_id; uint32_t http_window_length = 0; int bytes_read; uint8_t *buf; int my_settings_accepted = 0; const char *my_hpack_headers[128]; struct http2_settings client_settings = http2_default_settings; struct http2_settings server_settings = http2_default_settings; /* Send own settings */ http2_send_settings(conn, &http2_civetweb_server_settings); // http2_send_window(conn, 0, /* 0x3fff0001 */ 1024*1024); /* initialize hpack header table with predefined header fields */ memset((void *)my_hpack_headers, 0, sizeof(my_hpack_headers)); memcpy((void *)my_hpack_headers, hpack_predefined, sizeof(hpack_predefined)); buf = (uint8_t *)mg_malloc_ctx(server_settings.settings_max_frame_size, conn->phys_ctx); if (!buf) { /* Out of memory */ DEBUG_TRACE("%s", "Out of memory for HTTP2 frame"); return; } for (;;) { /* HTTP/2 is handled frame by frame */ int frame_is_end_stream = 0; int frame_is_end_headers = 0; int frame_is_padded = 0; int frame_is_priority = 0; #if defined(USE_SERVER_STATS) conn->conn_state = 3; /* HTTP/2 ready */ #endif bytes_read = mg_read(conn, http2_frame_head, sizeof(http2_frame_head)); if (bytes_read != sizeof(http2_frame_head)) { /* TODO: errormsg */ goto clean_http2; } /* Extract data from frame header */ http2_frame_size = ((uint32_t)http2_frame_head[0] * 0x10000u) + ((uint32_t)http2_frame_head[1] * 0x100u) + ((uint32_t)http2_frame_head[2]); http2_frame_type = http2_frame_head[3]; http2_frame_flags = http2_frame_head[4]; http2_frame_stream_id = ((uint32_t)http2_frame_head[5] * 0x1000000u) + ((uint32_t)http2_frame_head[6] * 0x10000u) + ((uint32_t)http2_frame_head[7] * 0x100u) + ((uint32_t)http2_frame_head[8]); frame_is_end_stream = (0 != (http2_frame_flags & 0x01)); frame_is_end_headers = (0 != (http2_frame_flags & 0x04)); frame_is_padded = (0 != (http2_frame_flags & 0x08)); frame_is_priority = (0 != (http2_frame_flags & 0x20)); if (http2_frame_size > server_settings.settings_max_frame_size) { /* TODO: Error Message */ DEBUG_TRACE("HTTP2 frame too large (%lu)", (unsigned long)http2_frame_size); goto clean_http2; } bytes_read = mg_read(conn, buf, http2_frame_size); if (bytes_read != (int)http2_frame_size) { /* TODO: Error Message - or read again? */ DEBUG_TRACE("HTTP2 read error (%li != %li)", (signed long int)bytes_read, (signed long int)http2_frame_size); goto clean_http2; } DEBUG_TRACE("HTTP2 frame type %u, size %u, stream %u, flags %02x", http2_frame_type, http2_frame_size, http2_frame_stream_id, http2_frame_flags); /* Further processing according to frame type. See definition: */ /* https://tools.ietf.org/html/rfc7540#section-6 */ switch (http2_frame_type) { case 0: /* DATA */ { /* TODO */ DEBUG_TRACE("%s", "HTTP2 DATA frame?"); } break; case 1: /* HEADERS */ { int i = 0; uint8_t padding = 0; uint32_t dependency = 0; uint8_t weight = 0; uint8_t exclusive = 0; /* Request start time */ clock_gettime(CLOCK_MONOTONIC, &(conn->req_time)); if (frame_is_padded) { padding = buf[i]; i++; DEBUG_TRACE("HTTP2 frame padded by %u bytes", padding); } if (frame_is_priority) { uint32_t val = ((uint32_t)buf[0 + i] * 0x1000000u) + ((uint32_t)buf[1 + i] * 0x10000u) + ((uint32_t)buf[2 + i] * 0x100u) + ((uint32_t)buf[3 + i]); dependency = (val & 0x7FFFFFFFu); exclusive = ((val & 0x80000000u) != 0); weight = buf[4 + i]; i += 5; DEBUG_TRACE( "HTTP2 frame weight %u, dependency %u (exclusive: %i)", weight, dependency, exclusive); } conn->request_info.num_headers = 0; while (i < (int)http2_frame_size - (int)padding) { const char *key = 0; const char *val = 0; uint8_t idx_mask = 0; uint8_t value_known = 0; uint8_t indexing = 0; uint64_t idx = 0; /* Classify next entry by checking the bit mask */ if ((buf[i] & 0x80u) == 0x80u) { /* Indexed Header Field Representation: * https://tools.ietf.org/html/rfc7541#section-6.1 */ idx_mask = 0x7fu; value_known = 1; } else if ((buf[i] & 0xC0u) == 0x40u) { /* Literal Header Field with Incremental Indexing: * https://tools.ietf.org/html/rfc7541#section-6.2.1 */ idx_mask = 0x3fu; indexing = 1; } else if ((buf[i] & 0xF0u) == 0x00u) { /* Literal Header Field without Indexing: * https://tools.ietf.org/html/rfc7541#section-6.2.2 */ idx_mask = 0x0fu; } else if ((buf[i] & 0xF0u) == 0x10u) { /* Literal Header Field Never Indexed: * https://tools.ietf.org/html/rfc7541#section-6.2.3 */ idx_mask = 0x0fu; } else if ((buf[i] & 0xE0u) == 0x20u) { uint64_t tableSize; /* Dynamic Table Size Update: * https://tools.ietf.org/html/rfc7541#section-6.3 */ idx_mask = 0x1fu; tableSize = hpack_getnum(buf, &i, idx_mask, conn->phys_ctx); /* TODO: check if tablesize > allowed table size */ /* Purge additional table entries */ purge_dynamic_header_table(conn, (uint32_t)tableSize); /* Process next frame */ continue; } else { DEBUG_TRACE("HTTP2 unknown start pattern %02x", buf[i]); goto clean_http2; } /* Get the header name table index */ idx = hpack_getnum(buf, &i, idx_mask, conn->phys_ctx); /* Get Header name "key" */ if (idx == 0) { /* Index 0: Header name encoded in following bytes */ key = hpack_decode(buf, &i, (int)bytes_read, conn->phys_ctx); CHECK_LEAK_HDR_ALLOC(key); if (!key) { DEBUG_TRACE("HTTP2 key decoding error"); goto clean_http2; } } else if (/*(idx >= 15) &&*/ (idx <= 61)) { /* Take key name from predefined header table */ key = mg_strdup_ctx(hpack_predefined[idx].name, conn->phys_ctx); /* leak? */ CHECK_LEAK_HDR_ALLOC(key); } else if ((idx >= 62) && ((idx - 61) <= conn->http2.dyn_table_size)) { /* Take from dynamic header table */ uint32_t local_table_idx = (uint32_t)idx - 62; key = mg_strdup_ctx( conn->http2.dyn_table[local_table_idx].name, conn->phys_ctx); CHECK_LEAK_HDR_ALLOC(key); } else { /* protocol violation */ DEBUG_TRACE("HTTP2 invalid index %lu", (unsigned long)idx); goto clean_http2; } /* key is allocated now and must be freed later */ /* Get header value */ if (value_known) { /* Server must already know the value */ if (idx <= 61) { if (hpack_predefined[idx].value) { val = mg_strdup_ctx(hpack_predefined[idx].value, conn->phys_ctx); /* leak? */ CHECK_LEAK_HDR_ALLOC(val); } else { /* protocol violation */ DEBUG_TRACE("HTTP2 indexed header %lu has no value " "(key: %s)", (unsigned long)idx, key); CHECK_LEAK_HDR_FREE(key); mg_free((void *)key); goto clean_http2; } } else if ((idx >= 62) && ((idx - 61) <= conn->http2.dyn_table_size)) { uint32_t local_table_idx = (uint32_t)idx - 62; val = mg_strdup_ctx( conn->http2.dyn_table[local_table_idx].value, conn->phys_ctx); CHECK_LEAK_HDR_ALLOC(val); } else { /* protocol violation */ DEBUG_TRACE( "HTTP2 indexed header %lu out of range (key: %s)", (unsigned long)idx, key); CHECK_LEAK_HDR_FREE(key); mg_free((void *)key); goto clean_http2; } } else { /* Read value from HTTP2 stream */ val = hpack_decode(buf, &i, (int)bytes_read, conn->phys_ctx); /* leak? */ CHECK_LEAK_HDR_ALLOC(val); if (!val) { DEBUG_TRACE("HTTP2 value decoding error"); mg_free((void *)key); goto clean_http2; } if (indexing) { /* Add to index */ if (conn->http2.dyn_table_size >= HTTP2_DYN_TABLE_SIZE) { /* Too many elements */ DEBUG_TRACE("HTTP2 index table is full (key: %s, " "value: %s)", key, val); CHECK_LEAK_HDR_FREE(key); CHECK_LEAK_HDR_FREE(val); mg_free((void *)key); mg_free((void *)val); goto clean_http2; } /* Add to table of dynamic headers */ conn->http2.dyn_table[conn->http2.dyn_table_size].name = mg_strdup_ctx(key, conn->phys_ctx); /* leak */ conn->http2.dyn_table[conn->http2.dyn_table_size] .value = mg_strdup_ctx(val, conn->phys_ctx); /* leak */ CHECK_LEAK_DYN_ALLOC( conn->http2.dyn_table[conn->http2.dyn_table_size] .name); CHECK_LEAK_DYN_ALLOC( conn->http2.dyn_table[conn->http2.dyn_table_size] .value); conn->http2.dyn_table_size++; DEBUG_TRACE("HTTP2 new dynamic header table entry %i " "(key: %s, value: %s)", (int)conn->http2.dyn_table_size, key, val); } } /* val and key are allocated now and must be freed later */ /* Store these pointers in conn->request_info[].http_headers, * free_buffered_header_list(conn) will clean up later. */ /* Add header for this request */ if ((key != NULL) && (val != NULL) && (conn->request_info.num_headers < MG_MAX_HEADERS)) { conn->request_info .http_headers[conn->request_info.num_headers] .name = key; conn->request_info .http_headers[conn->request_info.num_headers] .value = val; conn->request_info.num_headers++; /* Some headers need to be stored in the request structure */ if (!strcmp(":method", key)) { conn->request_info.request_method = val; } else if (!strcmp(":path", key)) { conn->request_info.local_uri = val; conn->request_info.request_uri = val; conn->request_info.local_uri_raw = val; } else if (!strcmp(":status", key)) { conn->status_code = atoi(val); } DEBUG_TRACE("HTTP2 request header (key: %s, value: %s)", key, val); } else { /* - either key or value are NULL (out of memory) * - or the max. number of headers is reached * in both cases free all memory */ DEBUG_TRACE("%s", "HTTP2 cannot add header"); CHECK_LEAK_HDR_FREE(key); CHECK_LEAK_HDR_FREE(val); mg_free((void *)key); key = NULL; mg_free((void *)val); val = NULL; } } /* stream id */ conn->http2.stream_id = http2_frame_stream_id; /* header parsed */ DEBUG_TRACE("HTTP2 handle_request (stream %u)", http2_frame_stream_id); handle_request_stat_log(conn); /* Send "final" frame */ DEBUG_TRACE("HTTP2 handle_request done (stream %u)", http2_frame_stream_id); http2_data_frame_head(conn, 0, 1); free_buffered_response_header_list(conn); free_buffered_request_header_list(conn); } break; case 2: /* PRIORITY */ { uint32_t dependStream = ((uint32_t)buf[0] * 0x1000000u) + ((uint32_t)buf[1] * 0x10000u) + ((uint32_t)buf[2] * 0x100u) + ((uint32_t)buf[3]); uint8_t weight = buf[4]; DEBUG_TRACE("HTTP2 priority %u dependent stream %u", weight, dependStream); } break; case 3: /* RST_STREAM */ { uint32_t errorId = ((uint32_t)buf[0] * 0x1000000u) + ((uint32_t)buf[1] * 0x10000u) + ((uint32_t)buf[2] * 0x100u) + ((uint32_t)buf[3]); DEBUG_TRACE("HTTP2 reset with error %u", errorId); } break; case 4: /* SETTINGS */ if (http2_frame_stream_id != 0) { /* Send protocol error */ http2_reset_stream(conn, http2_frame_stream_id, HTTP2_ERR_PROTOCOL_ERROR); DEBUG_TRACE("%s", "HTTP2 received invalid settings frame"); } else if (http2_frame_flags) { /* ACK frame. Do not reply. */ my_settings_accepted++; DEBUG_TRACE("%s", "CivetWeb settings confirmed by peer"); } else { int i; for (i = 0; i < (int)http2_frame_size; i += 6) { uint16_t id = ((uint16_t)buf[i] * 0x100u) + ((uint16_t)buf[i + 1]); uint32_t val = ((uint32_t)buf[i + 2] * 0x1000000u) + ((uint32_t)buf[i + 3] * 0x10000u) + ((uint32_t)buf[i + 4] * 0x100u) + ((uint32_t)buf[i + 5]); switch (id) { case 1: client_settings.settings_header_table_size = val; DEBUG_TRACE("Received settings header_table_size: %u", val); break; case 2: client_settings.settings_enable_push = (val != 0); DEBUG_TRACE("Received settings enable_push: %u", val); break; case 3: client_settings.settings_max_concurrent_streams = val; DEBUG_TRACE( "Received settings max_concurrent_streams: %u", val); break; case 4: client_settings.settings_initial_window_size = val; DEBUG_TRACE("Received settings initial_window_size: %u", val); break; case 5: client_settings.settings_max_frame_size = val; DEBUG_TRACE("Received settings max_frame_size: %u", val); break; case 6: client_settings.settings_max_header_list_size = val; DEBUG_TRACE( "Received settings max_header_list_size: %u", val); break; default: /* Unknown setting. Ignore it. */ DEBUG_TRACE("Received unknown settings id=%u: %u", id, val); break; } } /* Every settings frame must be acknowledged */ http2_settings_acknowledge(conn); } break; case 5: /* PUSH_PROMISE */ DEBUG_TRACE("%s", "Push promise not supported"); break; case 6: /* PING */ if (http2_frame_flags == 0) { /* Set "reply" flag, and send same data back */ DEBUG_TRACE("%s", "Replying to ping"); http2_frame_head[4] = 1; mg_xwrite(conn, http2_frame_head, sizeof(http2_frame_head)); mg_xwrite(conn, buf, http2_frame_size); } break; case 7: /* GOAWAY */ { uint32_t lastStream = ((uint32_t)buf[0] * 0x1000000u) + ((uint32_t)buf[1] * 0x10000u) + ((uint32_t)buf[2] * 0x100u) + ((uint32_t)buf[3]); uint32_t errorId = ((uint32_t)buf[4] * 0x1000000u) + ((uint32_t)buf[5] * 0x10000u) + ((uint32_t)buf[6] * 0x100u) + ((uint32_t)buf[7]); ; /* followed by debug data */ uint32_t debugDataLen = http2_frame_size - 8; char *debugData = (char *)buf + 8; DEBUG_TRACE("HTTP2 goaway stream %u, error %u (%.*s)", lastStream, errorId, debugDataLen, debugData); } break; case 8: /* WINDOW_UPDATE */ { uint32_t val = ((uint32_t)buf[0] * 0x1000000u) + ((uint32_t)buf[1] * 0x10000u) + ((uint32_t)buf[2] * 0x100u) + ((uint32_t)buf[3]); http_window_length = (val & 0x7FFFFFFFu); DEBUG_TRACE("HTTP2 window update stream %u, length %u", http2_frame_stream_id, http_window_length); } break; case 9: /* CONTINUATION */ DEBUG_TRACE("%s", "HTTP2 Continue"); break; default: /* TODO: Error Message */ DEBUG_TRACE("%s", "Unknown frame type"); goto clean_http2; } /* not used in the moment */ (void)frame_is_end_stream; (void)frame_is_end_headers; (void)client_settings; } clean_http2: DEBUG_TRACE("%s", "HTTP2 free buffer, connection handler finished"); mg_free(buf); } #if 0 static void HPACK_TEST() { uint64_t test; for (test = 0;; test++) { char in[32] = {0}; uint8_t out[32] = {0}; char *check; int i; int l; memcpy(in, &test, sizeof(test)); l = hpack_encode(out, in, 0); i = 0; check = hpack_decode(out, &i, NULL); if (strcmp(in, check)) { printf("Error\n"); } mg_free(check); } } static void HPACK_TABLE_TEST() { int i; uint32_t hpack_huff_end_code_expected[32] = { 0 }; uint8_t hpack_huff_start_index_expected[32] = { 0 }; int reverse_map[256] = { 0 }; for (i = 0; i < 256; i++) { reverse_map[i] = -1; } for (i = 0; i < 256; i++) { uint8_t bits = hpack_huff_dec[i].bitcount; uint8_t dec = hpack_huff_dec[i].decoded; if (bits > hpack_huff_dec[i + 1].bitcount) { ck_abort_msg("hpack_huff_dec disorder at index %i", i); } if (hpack_huff_dec[i].encoded & (0xFFFFFFFFul << bits)) { ck_abort_msg("hpack_huff_dec bits inconsistent at index %i", i); } if ((bits < 5) || (bits > 30)) { ck_abort_msg("hpack_huff_dec bits out of range at index %i", i); } if (reverse_map[dec] != -1) { ck_abort_msg("hpack_huff_dec duplicate: %i", hpack_huff_dec[i].decoded); } reverse_map[dec] = i; hpack_huff_end_code_expected[bits - 5] = hpack_huff_dec[i].encoded; } for (i = 255; i >= 0; i--) { uint8_t bits = hpack_huff_dec[i].bitcount; hpack_huff_start_index_expected[bits - 5] = i; } for (i = 0; i < 256; i++) { if (reverse_map[i] == -1) { ck_abort_msg("reverse map at %i missing", i); } } i = sizeof(hpack_huff_start_index) / sizeof(hpack_huff_start_index[0]); if (i != 27) { ck_abort_msg("hpack_huff_start_index size error: ", i); } i = sizeof(hpack_huff_end_code) / sizeof(hpack_huff_end_code[0]); if (i != 27) { ck_abort_msg("hpack_huff_end_code size error: ", i); } for (i = 0; i < 27; i++) { if (hpack_huff_start_index_expected[i] != hpack_huff_start_index[i]) { ck_abort_msg("hpack_huff_start_index error at %i", i); } if (hpack_huff_end_code_expected[i] != hpack_huff_end_code[i]) { ck_abort_msg("hpack_huff_end_code error at %i", i); } } } #endif static void process_new_http2_connection(struct mg_connection *conn) { if (!is_valid_http2_primer(conn)) { /* Primer does not match expectation from RFC. * See https://tools.ietf.org/html/rfc7540#section-3.5 */ DEBUG_TRACE("%s", "No valid HTTP2 primer"); mg_send_http_error(conn, 400, "%s", "Invalid HTTP/2 primer"); } else { /* Valid HTTP/2 primer received */ DEBUG_TRACE("%s", "Start handling HTTP2"); handle_http2(conn); /* Free memory allocated for headers, if not done yet */ DEBUG_TRACE("%s", "Free remaining HTTP2 header memory"); free_buffered_response_header_list(conn); free_buffered_request_header_list(conn); purge_dynamic_header_table(conn, 0); } } webfakes/src/match.h0000644000176200001440000001432714740430263014107 0ustar liggesusers/* Reimplementation of pattern matching */ /* This file is part of the CivetWeb web server. * See https://github.com/civetweb/civetweb/ */ /* Initialize structure with 0 matches */ static void match_context_reset(struct mg_match_context *mcx) { mcx->num_matches = 0; memset(mcx->match, 0, sizeof(mcx->match)); } /* Add a new match to the list of matches */ static void match_context_push(const char *str, size_t len, struct mg_match_context *mcx) { if (mcx->num_matches < MG_MATCH_CONTEXT_MAX_MATCHES) { mcx->match[mcx->num_matches].str = str; mcx->match[mcx->num_matches].len = len; mcx->num_matches++; } } static ptrdiff_t mg_match_impl(const char *pat, size_t pat_len, const char *str, struct mg_match_context *mcx) { /* Parse string */ size_t i_pat = 0; /* Pattern index */ size_t i_str = 0; /* Pattern index */ int case_sensitive = ((mcx != NULL) ? mcx->case_sensitive : 0); /* 0 or 1 */ while (i_pat < pat_len) { /* Pattern ? matches one character, except / and NULL character */ if ((pat[i_pat] == '?') && (str[i_str] != '\0') && (str[i_str] != '/')) { size_t i_str_start = i_str; do { /* Advance as long as there are ? */ i_pat++; i_str++; } while ((pat[i_pat] == '?') && (str[i_str] != '\0') && (str[i_str] != '/') && (i_pat < pat_len)); /* If we have a match context, add the substring we just found */ if (mcx) { match_context_push(str + i_str_start, i_str - i_str_start, mcx); } /* Reached end of pattern ? */ if (i_pat == pat_len) { return (ptrdiff_t)i_str; } } /* Pattern $ matches end of string */ if (pat[i_pat] == '$') { return (str[i_str] == '\0') ? (ptrdiff_t)i_str : -1; } /* Pattern * or ** matches multiple characters */ if (pat[i_pat] == '*') { size_t len; /* length matched by "*" or "**" */ ptrdiff_t ret; i_pat++; if ((pat[i_pat] == '*') && (i_pat < pat_len)) { /* Pattern ** matches all */ i_pat++; len = strlen(str + i_str); } else { /* Pattern * matches all except / character */ len = strcspn(str + i_str, "/"); } if (i_pat == pat_len) { /* End of pattern reached. Add all to match context. */ if (mcx) { match_context_push(str + i_str, len, mcx); } return ((ptrdiff_t)(i_str + len)); } /* This loop searches for the longest possible match */ do { ret = mg_match_impl(pat + i_pat, (pat_len - (size_t)i_pat), str + i_str + len, mcx); } while ((ret == -1) && (len-- > 0)); /* If we have a match context, add the substring we just found */ if (ret >= 0) { if (mcx) { match_context_push(str + i_str, len, mcx); } return ((ptrdiff_t)i_str + ret + (ptrdiff_t)len); } return -1; } /* Single character compare */ if (case_sensitive) { if (pat[i_pat] != str[i_str]) { /* case sensitive compare: mismatch */ return -1; } } else if (lowercase(&pat[i_pat]) != lowercase(&str[i_str])) { /* case insensitive compare: mismatch */ return -1; } i_pat++; i_str++; } return (ptrdiff_t)i_str; } static ptrdiff_t mg_match_alternatives(const char *pat, size_t pat_len, const char *str, struct mg_match_context *mcx) { const char *match_alternative = (const char *)memchr(pat, '|', pat_len); if (mcx != NULL) { match_context_reset(mcx); } while (match_alternative != NULL) { /* Split at | for alternative match */ size_t left_size = (size_t)(match_alternative - pat); /* Try left string first */ ptrdiff_t ret = mg_match_impl(pat, left_size, str, mcx); if (ret >= 0) { /* A 0-byte match is also valid */ return ret; } /* Reset possible incomplete match data */ if (mcx != NULL) { match_context_reset(mcx); } /* If no match: try right side */ pat += left_size + 1; pat_len -= left_size + 1; match_alternative = (const char *)memchr(pat, '|', pat_len); } /* Handled all | operators. This is the final string. */ return mg_match_impl(pat, pat_len, str, mcx); } static int match_compare(const void *p1, const void *p2, void *user) { const struct mg_match_element *e1 = (const struct mg_match_element *)p1; const struct mg_match_element *e2 = (const struct mg_match_element *)p2; /* unused */ (void)user; if (e1->str > e2->str) { return +1; } if (e1->str < e2->str) { return -1; } return 0; } #if defined(MG_EXPERIMENTAL_INTERFACES) CIVETWEB_API #else static #endif ptrdiff_t mg_match(const char *pat, const char *str, struct mg_match_context *mcx) { size_t pat_len = strlen(pat); ptrdiff_t ret = mg_match_alternatives(pat, pat_len, str, mcx); if (mcx != NULL) { if (ret < 0) { /* Remove possible incomplete data */ match_context_reset(mcx); } else { /* Join "?*" to one pattern. */ size_t i, j; /* Use difference of two array elements instead of sizeof, since * there may be some additional padding bytes. */ size_t elmsize = (size_t)(&mcx->match[1]) - (size_t)(&mcx->match[0]); /* First sort the matches by address ("str" begin to end) */ mg_sort(mcx->match, mcx->num_matches, elmsize, match_compare, NULL); /* Join consecutive matches */ i = 1; while (i < mcx->num_matches) { if ((mcx->match[i - 1].str + mcx->match[i - 1].len) == mcx->match[i].str) { /* Two matches are consecutive. Join length. */ mcx->match[i - 1].len += mcx->match[i].len; /* Shift all list elements. */ for (j = i + 1; j < mcx->num_matches; j++) { mcx->match[j - 1].len = mcx->match[j].len; mcx->match[j - 1].str = mcx->match[j].str; } /* Remove/blank last list element. */ mcx->num_matches--; mcx->match[mcx->num_matches].str = NULL; mcx->match[mcx->num_matches].len = 0; } else { i++; } } } } return ret; } static ptrdiff_t match_prefix(const char *pattern, size_t pattern_len, const char *str) { if (pattern == NULL) { return -1; } return mg_match_alternatives(pattern, pattern_len, str, NULL); } static ptrdiff_t match_prefix_strlen(const char *pattern, const char *str) { if (pattern == NULL) { return -1; } return mg_match_alternatives(pattern, strlen(pattern), str, NULL); } /* End of match.inl */ webfakes/src/mod_mbedtls.h0000644000176200001440000001564414740430263015307 0ustar liggesusers#if defined(USE_MBEDTLS) // USE_MBEDTLS used with NO_SSL #include "mbedtls/ctr_drbg.h" #include "mbedtls/debug.h" #include "mbedtls/entropy.h" #include "mbedtls/error.h" #if MBEDTLS_VERSION_NUMBER >= 0x03000000 // The file include/mbedtls/net.h was removed in v3.0.0 because its only // function was to include mbedtls/net_sockets.h which now should be included // directly. #include "mbedtls/net_sockets.h" #else #include "mbedtls/net.h" #endif #include "mbedtls/pk.h" #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "mbedtls/x509.h" #include "mbedtls/x509_crt.h" #include typedef mbedtls_ssl_context SSL; typedef struct { mbedtls_ssl_config conf; /* SSL configuration */ mbedtls_x509_crt cert; /* Certificate */ mbedtls_ctr_drbg_context ctr; /* Counter random generator state */ mbedtls_entropy_context entropy; /* Entropy context */ mbedtls_pk_context pkey; /* Private key */ } SSL_CTX; /* public api */ int mbed_sslctx_init(SSL_CTX *ctx, const char *crt); void mbed_sslctx_uninit(SSL_CTX *ctx); void mbed_ssl_close(mbedtls_ssl_context *ssl); int mbed_ssl_accept(mbedtls_ssl_context **ssl, SSL_CTX *ssl_ctx, int *sock, struct mg_context *phys_ctx); int mbed_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, int len); int mbed_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, int len); static void mbed_debug(void *context, int level, const char *file, int line, const char *str); static int mbed_ssl_handshake(mbedtls_ssl_context *ssl); int mbed_sslctx_init(SSL_CTX *ctx, const char *crt) { mbedtls_ssl_config *conf; int rc; if (ctx == NULL || crt == NULL) { return -1; } DEBUG_TRACE("%s", "Initializing MbedTLS SSL"); mbedtls_entropy_init(&ctx->entropy); conf = &ctx->conf; mbedtls_ssl_config_init(conf); /* Set mbedTLS debug level by defining MG_CONFIG_MBEDTLS_DEBUG: * 0 No debug = mbedTLS DEFAULT * 1 Error (default if "DEBUG" is set for CivetWeb) * 2 State change * 3 Informational * 4 Verbose */ #if defined(DEBUG) || defined(MG_CONFIG_MBEDTLS_DEBUG) #if defined(MG_CONFIG_MBEDTLS_DEBUG) mbedtls_debug_set_threshold(MG_CONFIG_MBEDTLS_DEBUG); #else mbedtls_debug_set_threshold(1); #endif mbedtls_ssl_conf_dbg(conf, mbed_debug, (void *)ctx); #endif /* Initialize TLS key and cert */ mbedtls_pk_init(&ctx->pkey); mbedtls_ctr_drbg_init(&ctx->ctr); mbedtls_x509_crt_init(&ctx->cert); rc = mbedtls_ctr_drbg_seed(&ctx->ctr, mbedtls_entropy_func, &ctx->entropy, (unsigned char *)"CivetWeb", strlen("CivetWeb")); if (rc != 0) { DEBUG_TRACE("TLS random seed failed (%i)", rc); return -1; } #if MBEDTLS_VERSION_NUMBER >= 0x03000000 // mbedtls_pk_parse_keyfile() has changed in mbedTLS 3.0. You now need // to pass a properly seeded, cryptographically secure RNG when calling // these functions. It is used for blinding, a countermeasure against // side-channel attacks. // https://github.com/Mbed-TLS/mbedtls/blob/development/docs/3.0-migration-guide.md#some-functions-gained-an-rng-parameter rc = mbedtls_pk_parse_keyfile( &ctx->pkey, crt, NULL, mbedtls_ctr_drbg_random, &ctx->ctr); #else rc = mbedtls_pk_parse_keyfile(&ctx->pkey, crt, NULL); #endif if (rc != 0) { DEBUG_TRACE("TLS parse key file failed (%i)", rc); return -1; } rc = mbedtls_x509_crt_parse_file(&ctx->cert, crt); if (rc != 0) { DEBUG_TRACE("TLS parse crt file failed (%i)", rc); return -1; } rc = mbedtls_ssl_config_defaults(conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (rc != 0) { DEBUG_TRACE("TLS set defaults failed (%i)", rc); return -1; } mbedtls_ssl_conf_rng(conf, mbedtls_ctr_drbg_random, &ctx->ctr); /* Set auth mode if peer cert should be verified */ mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_ca_chain(conf, NULL, NULL); /* Configure server cert and key */ rc = mbedtls_ssl_conf_own_cert(conf, &ctx->cert, &ctx->pkey); if (rc != 0) { DEBUG_TRACE("TLS cannot set certificate and private key (%i)", rc); return -1; } return 0; } void mbed_sslctx_uninit(SSL_CTX *ctx) { mbedtls_ctr_drbg_free(&ctx->ctr); mbedtls_pk_free(&ctx->pkey); mbedtls_x509_crt_free(&ctx->cert); mbedtls_entropy_free(&ctx->entropy); mbedtls_ssl_config_free(&ctx->conf); } int mbed_ssl_accept(mbedtls_ssl_context **ssl, SSL_CTX *ssl_ctx, int *sock, struct mg_context *phys_ctx) { int rc; (void)phys_ctx; /* unused, if server statistics is not turned on */ DEBUG_TRACE("TLS accept processing %p", ssl); *ssl = (mbedtls_ssl_context *)mg_calloc_ctx(1, sizeof(mbedtls_ssl_context), phys_ctx); if (*ssl == NULL) { DEBUG_TRACE("TLS accept: malloc ssl failed (%i)", (int)sizeof(mbedtls_ssl_context)); return -1; } mbedtls_ssl_init(*ssl); mbedtls_ssl_setup(*ssl, &ssl_ctx->conf); mbedtls_ssl_set_bio(*ssl, sock, mbedtls_net_send, mbedtls_net_recv, NULL); rc = mbed_ssl_handshake(*ssl); if (rc != 0) { DEBUG_TRACE("TLS handshake failed (%i)", rc); mbedtls_ssl_free(*ssl); mg_free(*ssl); *ssl = NULL; return -1; } DEBUG_TRACE("TLS connection %p accepted, state: %d", ssl, (*ssl)->state); return 0; } void mbed_ssl_close(mbedtls_ssl_context *ssl) { DEBUG_TRACE("TLS connection %p closed", ssl); mbedtls_ssl_close_notify(ssl); mbedtls_ssl_free(ssl); mg_free(ssl); /* mg_free for mg_calloc in mbed_ssl_accept */ } static int mbed_ssl_handshake(mbedtls_ssl_context *ssl) { int rc; while ((rc = mbedtls_ssl_handshake(ssl)) != 0) { if (rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE && rc != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { break; } } DEBUG_TRACE("TLS handshake rc: %d, state: %d", rc, ssl->state); return rc; } int mbed_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, int len) { int rc = mbedtls_ssl_read(ssl, buf, len); /* DEBUG_TRACE("mbedtls_ssl_read: %d", rc); */ return rc; } int mbed_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, int len) { int rc = mbedtls_ssl_write(ssl, buf, len); /* DEBUG_TRACE("mbedtls_ssl_write: %d", rc); */ return rc; } static void mbed_debug(void *user_param, int level, const char *file, int line, const char *str) { (void)level; /* Ignored. Limit is set using mbedtls_debug_set_threshold */ (void)user_param; /* Ignored. User parameter (context) is set using mbedtls_ssl_conf_dbg */ DEBUG_TRACE("mbedTLS DEBUG: file: [%s] line: [%d] str: [%s]", file, line, str); } #endif /* USE_MBEDTLS */ webfakes/src/sort.h0000644000176200001440000000251414740430263013775 0ustar liggesusers/* Sort function. */ /* from https://github.com/bel2125/sort_r */ static void mg_sort(void *data, size_t elemcount, size_t elemsize, int (*compfunc)(const void *data1, const void *data2, void *userarg), void *userarg) { /* We cannot use qsort_r here. For a detailed reason, see * https://github.com/civetweb/civetweb/issues/1048#issuecomment-1047093014 * https://stackoverflow.com/questions/39560773/different-declarations-of-qsort-r-on-mac-and-linux */ /* We use ShellSort here with this gap sequence: https://oeis.org/A102549 */ size_t A102549[9] = {1, 4, 10, 23, 57, 132, 301, 701, 1750}; size_t gap, i, j, k; int Aidx; void *tmp = alloca(elemsize); for (Aidx = 8; Aidx >= 0; Aidx--) { gap = A102549[Aidx]; if (gap > (elemcount / 2)) { continue; } for (i = 0; i < gap; i++) { for (j = i; j < elemcount; j += gap) { memcpy(tmp, (void *)((size_t)data + elemsize * j), elemsize); for (k = j; k >= gap; k -= gap) { void *cmp = (void *)((size_t)data + elemsize * (k - gap)); int cmpres = compfunc(cmp, tmp, userarg); if (cmpres > 0) { memcpy((void *)((size_t)data + elemsize * k), cmp, elemsize); } else { break; } } memcpy((void *)((size_t)data + elemsize * k), tmp, elemsize); } } } } /* end if sort.inl */ webfakes/src/handle_form.h0000644000176200001440000007511414740430263015272 0ustar liggesusers/* Copyright (c) 2016-2021 the Civetweb developers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ static int url_encoded_field_found(const struct mg_connection *conn, const char *key, size_t key_len, const char *filename, size_t filename_len, char *path, size_t path_len, struct mg_form_data_handler *fdh) { char key_dec[1024]; char filename_dec[1024]; int key_dec_len; int filename_dec_len; int ret; key_dec_len = mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1); if (((size_t)key_dec_len >= (size_t)sizeof(key_dec)) || (key_dec_len < 0)) { return MG_FORM_FIELD_STORAGE_SKIP; } if (filename) { filename_dec_len = mg_url_decode(filename, (int)filename_len, filename_dec, (int)sizeof(filename_dec), 1); if (((size_t)filename_dec_len >= (size_t)sizeof(filename_dec)) || (filename_dec_len < 0)) { /* Log error message and skip this field. */ mg_cry_internal(conn, "%s: Cannot decode filename", __func__); return MG_FORM_FIELD_STORAGE_SKIP; } remove_dot_segments(filename_dec); } else { filename_dec[0] = 0; } ret = fdh->field_found(key_dec, filename_dec, path, path_len, fdh->user_data); if ((ret & 0xF) == MG_FORM_FIELD_STORAGE_GET) { if (fdh->field_get == NULL) { mg_cry_internal(conn, "%s: Function \"Get\" not available", __func__); return MG_FORM_FIELD_STORAGE_SKIP; } } if ((ret & 0xF) == MG_FORM_FIELD_STORAGE_STORE) { if (fdh->field_store == NULL) { mg_cry_internal(conn, "%s: Function \"Store\" not available", __func__); return MG_FORM_FIELD_STORAGE_SKIP; } } return ret; } static int url_encoded_field_get( const struct mg_connection *conn, const char *key, size_t key_len, const char *value, size_t *value_len, /* IN: number of bytes available in "value", OUT: number of bytes processed */ struct mg_form_data_handler *fdh) { char key_dec[1024]; char *value_dec = (char *)mg_malloc_ctx(*value_len + 1, conn->phys_ctx); int value_dec_len, ret; if (!value_dec) { /* Log error message and stop parsing the form data. */ mg_cry_internal(conn, "%s: Not enough memory (required: %lu)", __func__, (unsigned long)(*value_len + 1)); return MG_FORM_FIELD_STORAGE_ABORT; } mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1); if (*value_len >= 2 && value[*value_len - 2] == '%') *value_len -= 2; else if (*value_len >= 1 && value[*value_len - 1] == '%') (*value_len)--; value_dec_len = mg_url_decode( value, (int)*value_len, value_dec, ((int)*value_len) + 1, 1); ret = fdh->field_get(key_dec, value_dec, (size_t)value_dec_len, fdh->user_data); mg_free(value_dec); return ret; } static int unencoded_field_get(const struct mg_connection *conn, const char *key, size_t key_len, const char *value, size_t value_len, struct mg_form_data_handler *fdh) { char key_dec[1024]; (void)conn; mg_url_decode(key, (int)key_len, key_dec, (int)sizeof(key_dec), 1); return fdh->field_get(key_dec, value, value_len, fdh->user_data); } static int field_stored(const struct mg_connection *conn, const char *path, long long file_size, struct mg_form_data_handler *fdh) { /* Equivalent to "upload" callback of "mg_upload". */ (void)conn; /* we do not need mg_cry here, so conn is currently unused */ return fdh->field_store(path, file_size, fdh->user_data); } static const char * search_boundary(const char *buf, size_t buf_len, const char *boundary, size_t boundary_len) { /* We must do a binary search here, not a string search, since the buffer * may contain '\x00' bytes, if binary data is transferred. */ int clen = (int)buf_len - (int)boundary_len - 4; int i; for (i = 0; i <= clen; i++) { if (!memcmp(buf + i, "\r\n--", 4)) { if (!memcmp(buf + i + 4, boundary, boundary_len)) { return buf + i; } } } return NULL; } int mg_handle_form_request(struct mg_connection *conn, struct mg_form_data_handler *fdh) { const char *content_type; char path[512]; char buf[MG_BUF_LEN]; /* Must not be smaller than ~900 */ int field_storage; int buf_fill = 0; int r; int field_count = 0; struct mg_file fstore = STRUCT_FILE_INITIALIZER; int64_t file_size = 0; /* init here, to a avoid a false positive "uninitialized variable used" warning */ int has_body_data = (conn->request_info.content_length > 0) || (conn->is_chunked); /* Unused without filesystems */ (void)fstore; (void)file_size; /* There are three ways to encode data from a HTML form: * 1) method: GET (default) * The form data is in the HTTP query string. * 2) method: POST, enctype: "application/x-www-form-urlencoded" * The form data is in the request body. * The body is url encoded (the default encoding for POST). * 3) method: POST, enctype: "multipart/form-data". * The form data is in the request body of a multipart message. * This is the typical way to handle file upload from a form. */ if (!has_body_data) { const char *data; if (0 != strcmp(conn->request_info.request_method, "GET")) { /* No body data, but not a GET request. * This is not a valid form request. */ return -1; } /* GET request: form data is in the query string. */ /* The entire data has already been loaded, so there is no need to * call mg_read. We just need to split the query string into key-value * pairs. */ data = conn->request_info.query_string; if (!data) { /* No query string. */ return -1; } /* Split data in a=1&b=xy&c=3&c=4 ... */ while (*data) { const char *val = strchr(data, '='); const char *next; ptrdiff_t keylen, vallen; if (!val) { break; } keylen = val - data; /* In every "field_found" callback we ask what to do with the * data ("field_storage"). This could be: * MG_FORM_FIELD_STORAGE_SKIP (0): * ignore the value of this field * MG_FORM_FIELD_STORAGE_GET (1): * read the data and call the get callback function * MG_FORM_FIELD_STORAGE_STORE (2): * store the data in a file * MG_FORM_FIELD_STORAGE_READ (3): * let the user read the data (for parsing long data on the fly) * MG_FORM_FIELD_STORAGE_ABORT (flag): * stop parsing */ memset(path, 0, sizeof(path)); field_count++; field_storage = url_encoded_field_found(conn, data, (size_t)keylen, NULL, 0, path, sizeof(path) - 1, fdh); val++; next = strchr(val, '&'); if (next) { vallen = next - val; } else { vallen = (ptrdiff_t)strlen(val); } if (field_storage == MG_FORM_FIELD_STORAGE_GET) { /* Call callback */ r = url_encoded_field_get( conn, data, (size_t)keylen, val, (size_t *)&vallen, fdh); if (r == MG_FORM_FIELD_HANDLE_ABORT) { /* Stop request handling */ break; } if (r == MG_FORM_FIELD_HANDLE_NEXT) { /* Skip to next field */ field_storage = MG_FORM_FIELD_STORAGE_SKIP; } } if (next) { next++; } else { /* vallen may have been modified by url_encoded_field_get */ next = val + vallen; } #if !defined(NO_FILESYSTEMS) if (field_storage == MG_FORM_FIELD_STORAGE_STORE) { /* Store the content to a file */ if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fstore) == 0) { fstore.access.fp = NULL; } file_size = 0; if (fstore.access.fp != NULL) { size_t n = (size_t) fwrite(val, 1, (size_t)vallen, fstore.access.fp); if ((n != (size_t)vallen) || (ferror(fstore.access.fp))) { mg_cry_internal(conn, "%s: Cannot write file %s", __func__, path); (void)mg_fclose(&fstore.access); remove_bad_file(conn, path); } file_size += (int64_t)n; if (fstore.access.fp) { r = mg_fclose(&fstore.access); if (r == 0) { /* stored successfully */ r = field_stored(conn, path, file_size, fdh); if (r == MG_FORM_FIELD_HANDLE_ABORT) { /* Stop request handling */ break; } } else { mg_cry_internal(conn, "%s: Error saving file %s", __func__, path); remove_bad_file(conn, path); } fstore.access.fp = NULL; } } else { mg_cry_internal(conn, "%s: Cannot create file %s", __func__, path); } } #endif /* NO_FILESYSTEMS */ /* if (field_storage == MG_FORM_FIELD_STORAGE_READ) { */ /* The idea of "field_storage=read" is to let the API user read * data chunk by chunk and to some data processing on the fly. * This should avoid the need to store data in the server: * It should neither be stored in memory, like * "field_storage=get" does, nor in a file like * "field_storage=store". * However, for a "GET" request this does not make any much * sense, since the data is already stored in memory, as it is * part of the query string. */ /* } */ if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT) == MG_FORM_FIELD_STORAGE_ABORT) { /* Stop parsing the request */ break; } /* Proceed to next entry */ data = next; } return field_count; } content_type = mg_get_header(conn, "Content-Type"); if (!content_type || !mg_strncasecmp(content_type, "APPLICATION/X-WWW-FORM-URLENCODED", 33) || !mg_strncasecmp(content_type, "APPLICATION/WWW-FORM-URLENCODED", 31)) { /* The form data is in the request body data, encoded in key/value * pairs. */ int all_data_read = 0; /* Read body data and split it in keys and values. * The encoding is like in the "GET" case above: a=1&b&c=3&c=4. * Here we use "POST", and read the data from the request body. * The data read on the fly, so it is not required to buffer the * entire request in memory before processing it. */ for (;;) { const char *val; const char *next; ptrdiff_t keylen, vallen; ptrdiff_t used; int end_of_key_value_pair_found = 0; int get_block; if ((size_t)buf_fill < (sizeof(buf) - 1)) { size_t to_read = sizeof(buf) - 1 - (size_t)buf_fill; r = mg_read(conn, buf + (size_t)buf_fill, to_read); if ((r < 0) || ((r == 0) && all_data_read)) { /* read error */ return -1; } if (r == 0) { /* TODO: Create a function to get "all_data_read" from * the conn object. All data is read if the Content-Length * has been reached, or if chunked encoding is used and * the end marker has been read, or if the connection has * been closed. */ all_data_read = (buf_fill == 0); } buf_fill += r; buf[buf_fill] = 0; if (buf_fill < 1) { break; } } val = strchr(buf, '='); if (!val) { break; } keylen = val - buf; val++; /* Call callback */ memset(path, 0, sizeof(path)); field_count++; field_storage = url_encoded_field_found(conn, buf, (size_t)keylen, NULL, 0, path, sizeof(path) - 1, fdh); if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT) == MG_FORM_FIELD_STORAGE_ABORT) { /* Stop parsing the request */ break; } #if !defined(NO_FILESYSTEMS) if (field_storage == MG_FORM_FIELD_STORAGE_STORE) { if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fstore) == 0) { fstore.access.fp = NULL; } file_size = 0; if (!fstore.access.fp) { mg_cry_internal(conn, "%s: Cannot create file %s", __func__, path); } } #endif /* NO_FILESYSTEMS */ get_block = 0; /* Loop to read values larger than sizeof(buf)-keylen-2 */ do { next = strchr(val, '&'); if (next) { vallen = next - val; end_of_key_value_pair_found = 1; } else { vallen = (ptrdiff_t)strlen(val); end_of_key_value_pair_found = all_data_read; } if (field_storage == MG_FORM_FIELD_STORAGE_GET) { #if 0 if (!end_of_key_value_pair_found && !all_data_read) { /* This callback will deliver partial contents */ } #endif /* Call callback */ r = url_encoded_field_get(conn, ((get_block > 0) ? NULL : buf), ((get_block > 0) ? 0 : (size_t)keylen), val, (size_t *)&vallen, fdh); get_block++; if (r == MG_FORM_FIELD_HANDLE_ABORT) { /* Stop request handling */ break; } if (r == MG_FORM_FIELD_HANDLE_NEXT) { /* Skip to next field */ field_storage = MG_FORM_FIELD_STORAGE_SKIP; } } if (next) { next++; } else { /* vallen may have been modified by url_encoded_field_get */ next = val + vallen; } #if !defined(NO_FILESYSTEMS) if (fstore.access.fp) { size_t n = (size_t) fwrite(val, 1, (size_t)vallen, fstore.access.fp); if ((n != (size_t)vallen) || (ferror(fstore.access.fp))) { mg_cry_internal(conn, "%s: Cannot write file %s", __func__, path); mg_fclose(&fstore.access); remove_bad_file(conn, path); } file_size += (int64_t)n; } #endif /* NO_FILESYSTEMS */ if (!end_of_key_value_pair_found) { used = next - buf; memmove(buf, buf + (size_t)used, sizeof(buf) - (size_t)used); next = buf; buf_fill -= (int)used; if ((size_t)buf_fill < (sizeof(buf) - 1)) { size_t to_read = sizeof(buf) - 1 - (size_t)buf_fill; r = mg_read(conn, buf + (size_t)buf_fill, to_read); if ((r < 0) || ((r == 0) && all_data_read)) { #if !defined(NO_FILESYSTEMS) /* read error */ if (fstore.access.fp) { mg_fclose(&fstore.access); remove_bad_file(conn, path); } return -1; #endif /* NO_FILESYSTEMS */ } if (r == 0) { /* TODO: Create a function to get "all_data_read" * from the conn object. All data is read if the * Content-Length has been reached, or if chunked * encoding is used and the end marker has been * read, or if the connection has been closed. */ all_data_read = (buf_fill == 0); } buf_fill += r; buf[buf_fill] = 0; if (buf_fill < 1) { break; } val = buf; } } } while (!end_of_key_value_pair_found); #if !defined(NO_FILESYSTEMS) if (fstore.access.fp) { r = mg_fclose(&fstore.access); if (r == 0) { /* stored successfully */ r = field_stored(conn, path, file_size, fdh); if (r == MG_FORM_FIELD_HANDLE_ABORT) { /* Stop request handling */ break; } } else { mg_cry_internal(conn, "%s: Error saving file %s", __func__, path); remove_bad_file(conn, path); } fstore.access.fp = NULL; } #endif /* NO_FILESYSTEMS */ if (all_data_read && (buf_fill == 0)) { /* nothing more to process */ break; } /* Proceed to next entry */ used = next - buf; memmove(buf, buf + (size_t)used, sizeof(buf) - (size_t)used); buf_fill -= (int)used; } return field_count; } if (!mg_strncasecmp(content_type, "MULTIPART/FORM-DATA;", 20)) { /* The form data is in the request body data, encoded as multipart * content (see https://www.ietf.org/rfc/rfc1867.txt, * https://www.ietf.org/rfc/rfc2388.txt). */ char *boundary; size_t bl; ptrdiff_t used; struct mg_request_info part_header; char *hbuf; const char *content_disp, *hend, *fbeg, *fend, *nbeg, *nend; const char *next; unsigned part_no; int all_data_read = 0; memset(&part_header, 0, sizeof(part_header)); /* Skip all spaces between MULTIPART/FORM-DATA; and BOUNDARY= */ bl = 20; while (content_type[bl] == ' ') { bl++; } /* There has to be a BOUNDARY definition in the Content-Type header */ if (mg_strncasecmp(content_type + bl, "BOUNDARY=", 9)) { /* Malformed request */ return -1; } /* Copy boundary string to variable "boundary" */ fbeg = content_type + bl + 9; bl = strlen(fbeg); boundary = (char *)mg_malloc(bl + 1); if (!boundary) { /* Out of memory */ mg_cry_internal(conn, "%s: Cannot allocate memory for boundary [%lu]", __func__, (unsigned long)bl); return -1; } memcpy(boundary, fbeg, bl); boundary[bl] = 0; /* RFC 2046 permits the boundary string to be quoted. */ /* If the boundary is quoted, trim the quotes */ if (boundary[0] == '"') { hbuf = strchr(boundary + 1, '"'); if ((!hbuf) || (*hbuf != '"')) { /* Malformed request */ mg_free(boundary); return -1; } *hbuf = 0; memmove(boundary, boundary + 1, bl); bl = strlen(boundary); } /* Do some sanity checks for boundary lengths */ if (bl > 70) { /* From RFC 2046: * Boundary delimiters must not appear within the * encapsulated material, and must be no longer * than 70 characters, not counting the two * leading hyphens. */ /* The algorithm can not work if bl >= sizeof(buf), or if buf * can not hold the multipart header plus the boundary. * Requests with long boundaries are not RFC compliant, maybe they * are intended attacks to interfere with this algorithm. */ mg_free(boundary); return -1; } if (bl < 4) { /* Sanity check: A boundary string of less than 4 bytes makes * no sense either. */ mg_free(boundary); return -1; } for (part_no = 0;; part_no++) { size_t towrite, fnlen, n; int get_block; size_t to_read = sizeof(buf) - 1 - (size_t)buf_fill; /* Unused without filesystems */ (void)n; r = mg_read(conn, buf + (size_t)buf_fill, to_read); if ((r < 0) || ((r == 0) && all_data_read)) { /* read error */ mg_free(boundary); return -1; } if (r == 0) { all_data_read = (buf_fill == 0); } buf_fill += r; buf[buf_fill] = 0; if (buf_fill < 1) { /* No data */ mg_free(boundary); return -1; } if (part_no == 0) { int d = 0; while ((d < buf_fill) && (buf[d] != '-')) { d++; } if ((d > 0) && (buf[d] == '-')) { memmove(buf, buf + d, (unsigned)buf_fill - (unsigned)d); buf_fill -= d; buf[buf_fill] = 0; } } if (buf[0] != '-' || buf[1] != '-') { /* Malformed request */ mg_free(boundary); return -1; } if (0 != strncmp(buf + 2, boundary, bl)) { /* Malformed request */ mg_free(boundary); return -1; } if (buf[bl + 2] != '\r' || buf[bl + 3] != '\n') { /* Every part must end with \r\n, if there is another part. * The end of the request has an extra -- */ if (((size_t)buf_fill != (size_t)(bl + 6)) || (strncmp(buf + bl + 2, "--\r\n", 4))) { /* Malformed request */ mg_free(boundary); return -1; } /* End of the request */ break; } /* Next, we need to get the part header: Read until \r\n\r\n */ hbuf = buf + bl + 4; hend = strstr(hbuf, "\r\n\r\n"); if (!hend) { /* Malformed request */ mg_free(boundary); return -1; } part_header.num_headers = parse_http_headers(&hbuf, part_header.http_headers); if ((hend + 2) != hbuf) { /* Malformed request */ mg_free(boundary); return -1; } /* Skip \r\n\r\n */ hend += 4; /* According to the RFC, every part has to have a header field like: * Content-Disposition: form-data; name="..." */ content_disp = get_header(part_header.http_headers, part_header.num_headers, "Content-Disposition"); if (!content_disp) { /* Malformed request */ mg_free(boundary); return -1; } /* Get the mandatory name="..." part of the Content-Disposition * header. */ nbeg = strstr(content_disp, "name=\""); while ((nbeg != NULL) && (strcspn(nbeg - 1, ":,; \t") != 0)) { /* It could be somethingname= instead of name= */ nbeg = strstr(nbeg + 1, "name=\""); } /* This line is not required, but otherwise some compilers * generate spurious warnings. */ nend = nbeg; /* And others complain, the result is unused. */ (void)nend; /* If name=" is found, search for the closing " */ if (nbeg) { nbeg += 6; nend = strchr(nbeg, '\"'); if (!nend) { /* Malformed request */ mg_free(boundary); return -1; } } else { /* name= without quotes is also allowed */ nbeg = strstr(content_disp, "name="); while ((nbeg != NULL) && (strcspn(nbeg - 1, ":,; \t") != 0)) { /* It could be somethingname= instead of name= */ nbeg = strstr(nbeg + 1, "name="); } if (!nbeg) { /* Malformed request */ mg_free(boundary); return -1; } nbeg += 5; /* RFC 2616 Sec. 2.2 defines a list of allowed * separators, but many of them make no sense * here, e.g. various brackets or slashes. * If they are used, probably someone is * trying to attack with curious hand made * requests. Only ; , space and tab seem to be * reasonable here. Ignore everything else. */ nend = nbeg + strcspn(nbeg, ",; \t"); } /* Get the optional filename="..." part of the Content-Disposition * header. */ fbeg = strstr(content_disp, "filename=\""); while ((fbeg != NULL) && (strcspn(fbeg - 1, ":,; \t") != 0)) { /* It could be somethingfilename= instead of filename= */ fbeg = strstr(fbeg + 1, "filename=\""); } /* This line is not required, but otherwise some compilers * generate spurious warnings. */ fend = fbeg; /* If filename=" is found, search for the closing " */ if (fbeg) { fbeg += 10; fend = strchr(fbeg, '\"'); if (!fend) { /* Malformed request (the filename field is optional, but if * it exists, it needs to be terminated correctly). */ mg_free(boundary); return -1; } /* TODO: check Content-Type */ /* Content-Type: application/octet-stream */ } if (!fbeg) { /* Try the same without quotes */ fbeg = strstr(content_disp, "filename="); while ((fbeg != NULL) && (strcspn(fbeg - 1, ":,; \t") != 0)) { /* It could be somethingfilename= instead of filename= */ fbeg = strstr(fbeg + 1, "filename="); } if (fbeg) { fbeg += 9; fend = fbeg + strcspn(fbeg, ",; \t"); } } if (!fbeg || !fend) { fbeg = NULL; fend = NULL; fnlen = 0; } else { fnlen = (size_t)(fend - fbeg); } /* In theory, it could be possible that someone crafts * a request like name=filename=xyz. Check if name and * filename do not overlap. */ if (!(((ptrdiff_t)fbeg > (ptrdiff_t)nend) || ((ptrdiff_t)nbeg > (ptrdiff_t)fend))) { mg_free(boundary); return -1; } /* Call callback for new field */ memset(path, 0, sizeof(path)); field_count++; field_storage = url_encoded_field_found(conn, nbeg, (size_t)(nend - nbeg), ((fnlen > 0) ? fbeg : NULL), fnlen, path, sizeof(path) - 1, fdh); /* If the boundary is already in the buffer, get the address, * otherwise next will be NULL. */ next = search_boundary(hbuf, (size_t)((buf - hbuf) + buf_fill), boundary, bl); #if !defined(NO_FILESYSTEMS) if (field_storage == MG_FORM_FIELD_STORAGE_STORE) { /* Store the content to a file */ if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fstore) == 0) { fstore.access.fp = NULL; } file_size = 0; if (!fstore.access.fp) { mg_cry_internal(conn, "%s: Cannot create file %s", __func__, path); } } #endif /* NO_FILESYSTEMS */ get_block = 0; while (!next) { /* Set "towrite" to the number of bytes available * in the buffer */ towrite = (size_t)(buf - hend + buf_fill); if (towrite < bl + 4) { /* Not enough data stored. */ /* Incomplete request. */ mg_free(boundary); return -1; } /* Subtract the boundary length, to deal with * cases the boundary is only partially stored * in the buffer. */ towrite -= bl + 4; if (field_storage == MG_FORM_FIELD_STORAGE_GET) { r = unencoded_field_get(conn, ((get_block > 0) ? NULL : nbeg), ((get_block > 0) ? 0 : (size_t)(nend - nbeg)), hend, towrite, fdh); get_block++; if (r == MG_FORM_FIELD_HANDLE_ABORT) { /* Stop request handling */ break; } if (r == MG_FORM_FIELD_HANDLE_NEXT) { /* Skip to next field */ field_storage = MG_FORM_FIELD_STORAGE_SKIP; } } #if !defined(NO_FILESYSTEMS) if (field_storage == MG_FORM_FIELD_STORAGE_STORE) { if (fstore.access.fp) { /* Store the content of the buffer. */ n = (size_t)fwrite(hend, 1, towrite, fstore.access.fp); if ((n != towrite) || (ferror(fstore.access.fp))) { mg_cry_internal(conn, "%s: Cannot write file %s", __func__, path); mg_fclose(&fstore.access); remove_bad_file(conn, path); } file_size += (int64_t)n; } } #endif /* NO_FILESYSTEMS */ memmove(buf, hend + towrite, bl + 4); buf_fill = (int)(bl + 4); hend = buf; /* Read new data */ to_read = sizeof(buf) - 1 - (size_t)buf_fill; r = mg_read(conn, buf + (size_t)buf_fill, to_read); if ((r < 0) || ((r == 0) && all_data_read)) { #if !defined(NO_FILESYSTEMS) /* read error */ if (fstore.access.fp) { mg_fclose(&fstore.access); remove_bad_file(conn, path); } #endif /* NO_FILESYSTEMS */ mg_free(boundary); return -1; } /* r==0 already handled, all_data_read is false here */ buf_fill += r; buf[buf_fill] = 0; /* buf_fill is at least 8 here */ /* Find boundary */ next = search_boundary(buf, (size_t)buf_fill, boundary, bl); if (!next && (r == 0)) { /* incomplete request */ all_data_read = 1; } } towrite = (next ? (size_t)(next - hend) : 0); if (field_storage == MG_FORM_FIELD_STORAGE_GET) { /* Call callback */ r = unencoded_field_get(conn, ((get_block > 0) ? NULL : nbeg), ((get_block > 0) ? 0 : (size_t)(nend - nbeg)), hend, towrite, fdh); if (r == MG_FORM_FIELD_HANDLE_ABORT) { /* Stop request handling */ break; } if (r == MG_FORM_FIELD_HANDLE_NEXT) { /* Skip to next field */ field_storage = MG_FORM_FIELD_STORAGE_SKIP; } } #if !defined(NO_FILESYSTEMS) if (field_storage == MG_FORM_FIELD_STORAGE_STORE) { if (fstore.access.fp) { n = (size_t)fwrite(hend, 1, towrite, fstore.access.fp); if ((n != towrite) || (ferror(fstore.access.fp))) { mg_cry_internal(conn, "%s: Cannot write file %s", __func__, path); mg_fclose(&fstore.access); remove_bad_file(conn, path); } else { file_size += (int64_t)n; r = mg_fclose(&fstore.access); if (r == 0) { /* stored successfully */ r = field_stored(conn, path, file_size, fdh); if (r == MG_FORM_FIELD_HANDLE_ABORT) { /* Stop request handling */ break; } } else { mg_cry_internal(conn, "%s: Error saving file %s", __func__, path); remove_bad_file(conn, path); } } fstore.access.fp = NULL; } } #endif /* NO_FILESYSTEMS */ if ((field_storage & MG_FORM_FIELD_STORAGE_ABORT) == MG_FORM_FIELD_STORAGE_ABORT) { /* Stop parsing the request */ break; } /* Remove from the buffer */ if (next) { used = next - buf + 2; memmove(buf, buf + (size_t)used, sizeof(buf) - (size_t)used); buf_fill -= (int)used; } else { buf_fill = 0; } } /* All parts handled */ mg_free(boundary); return field_count; } /* Unknown Content-Type */ return -1; } /* End of handle_form.inl */ webfakes/src/Makevars.in0000644000176200001440000000042215026557545014745 0ustar liggesusers # PKG_CPPFLAGS=-UNDEBUG PKG_CPPFLAGS=-DUSE_MBEDTLS -Imbedtls/include PKG_CFLAGS=-DNO_CGI -DNO_FILES PKG_LIBS=libmbedtls.a @LIBS@ OBJECTS=@OBJECTS@ all: $(SHLIB) mrproper $(SHLIB): libmbedtls.a libmbedtls.a: @MBED@ $(AR) r $@ $^ mrproper: $(SHLIB) rm -f libmbedtls.a webfakes/src/crc32.c0000644000176200001440000001021414172041777013720 0ustar liggesusers #include #include static uint32_t crc32_tab[] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; static char hexa[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /* crc32 hash */ SEXP webfakes_crc32(SEXP v) { int len = LENGTH(v); Rbyte *begin = RAW(v), *end = begin + len; uint32_t crc = 0xffffffff; char str[9]; for (; begin < end; begin++) { crc = crc32_tab[(crc ^ *begin) & 0xff] ^ ((crc >> 8) & 0x00ffffff); } crc ^= 0xffffffff; str[0] = hexa[(crc >> 28)]; str[1] = hexa[(crc >> 24) & 0xf]; str[2] = hexa[(crc >> 20) & 0xf]; str[3] = hexa[(crc >> 16) & 0xf]; str[4] = hexa[(crc >> 12) & 0xf]; str[5] = hexa[(crc >> 8) & 0xf]; str[6] = hexa[(crc >> 4) & 0xf]; str[7] = hexa[crc & 0xf]; str[8] = '\0'; return mkString(str); } webfakes/src/sha1.h0000644000176200001440000002117114740430263013642 0ustar liggesusers/* SHA-1 in C By Steve Reid 100% Public Domain ----------------- Modified 7/98 By James H. Brown Still 100% Public Domain Corrected a problem which generated improper hash values on 16 bit machines Routine SHA1Update changed from void SHA1Update(SHA_CTX* context, unsigned char* data, unsigned int len) to void SHA1Update(SHA_CTX* context, unsigned char* data, unsigned long len) The 'len' parameter was declared an int which works fine on 32 bit machines. However, on 16 bit machines an int is too small for the shifts being done against it. This caused the hash function to generate incorrect values if len was greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). Since the file IO in main() reads 16K at a time, any file 8K or larger would be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million "a"s). I also changed the declaration of variables i & j in SHA1Update to unsigned long from unsigned int for the same reason. These changes should make no difference to any 32 bit implementations since an int and a long are the same size in those environments. -- I also corrected a few compiler warnings generated by Borland C. 1. Added #include for exit() prototype 2. Removed unused variable 'j' in SHA1Final 3. Changed exit(0) to return(0) at end of main. ALL changes I made can be located by searching for comments containing 'JHB' ----------------- Modified 8/98 By Steve Reid Still 100% public domain 1- Removed #include and used return() instead of exit() 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net ----------------- Modified 4/01 By Saul Kravitz Still 100% PD Modified to run on Compaq Alpha hardware. ----------------- Modified 07/2002 By Ralph Giles Still 100% public domain modified for use with stdint types, autoconf code cleanup, removed attribution comments switched SHA1Final() argument order for consistency use SHA1_ prefix for public api move public api to sha1.h */ /* 11/2016 adapted for CivetWeb: include sha1.h in sha1.c, rename to sha1.inl remove unused #ifdef sections make endian independent align buffer to 4 bytes remove unused variable assignments */ /* Test Vectors (from FIPS PUB 180-1) "abc" A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 A million repetitions of "a" 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */ #include #include typedef struct { uint32_t state[5]; uint32_t count[2]; uint8_t buffer[64]; } SHA_CTX; #define SHA1_DIGEST_SIZE 20 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* blk0() and blk() perform the initial expand. */ /* I got the idea of expanding during the round function from SSLeay */ typedef union { uint8_t c[64]; uint32_t l[16]; } CHAR64LONG16; static uint32_t blk0(CHAR64LONG16 *block, int i) { static const uint32_t n = 1u; if ((*((uint8_t *)(&n))) == 1) { /* little endian / intel byte order */ block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF); } return block->l[i]; } #define blk(block, i) \ ((block)->l[(i)&15] = \ rol((block)->l[((i) + 13) & 15] ^ (block)->l[((i) + 8) & 15] \ ^ (block)->l[((i) + 2) & 15] ^ (block)->l[(i)&15], \ 1)) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v, w, x, y, z, i) \ z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \ w = rol(w, 30); #define R1(v, w, x, y, z, i) \ z += ((w & (x ^ y)) ^ y) + blk(block, i) + 0x5A827999 + rol(v, 5); \ w = rol(w, 30); #define R2(v, w, x, y, z, i) \ z += (w ^ x ^ y) + blk(block, i) + 0x6ED9EBA1 + rol(v, 5); \ w = rol(w, 30); #define R3(v, w, x, y, z, i) \ z += (((w | x) & y) | (w & x)) + blk(block, i) + 0x8F1BBCDC + rol(v, 5); \ w = rol(w, 30); #define R4(v, w, x, y, z, i) \ z += (w ^ x ^ y) + blk(block, i) + 0xCA62C1D6 + rol(v, 5); \ w = rol(w, 30); /* Hash a single 512-bit block. This is the core of the algorithm. */ static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]) { uint32_t a, b, c, d, e; /* Must use an aligned, read/write buffer */ CHAR64LONG16 block[1]; memcpy(block, buffer, sizeof(block)); /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3); R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7); R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11); R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15); R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; } /* SHA1Init - Initialize new context */ SHA_API void SHA1_Init(SHA_CTX *context) { /* SHA1 initialization constants */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->count[0] = context->count[1] = 0; } SHA_API void SHA1_Update(SHA_CTX *context, const uint8_t *data, const uint32_t len) { uint32_t i, j; j = context->count[0]; if ((context->count[0] += (len << 3)) < j) { context->count[1]++; } context->count[1] += (len >> 29); j = (j >> 3) & 63; if ((j + len) > 63) { i = 64 - j; memcpy(&context->buffer[j], data, i); SHA1_Transform(context->state, context->buffer); for (; i + 63 < len; i += 64) { SHA1_Transform(context->state, &data[i]); } j = 0; } else { i = 0; } memcpy(&context->buffer[j], &data[i], len - i); } /* Add padding and return the message digest. */ SHA_API void SHA1_Final(unsigned char *digest, SHA_CTX *context) { uint32_t i; uint8_t finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (uint8_t)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ } SHA1_Update(context, (uint8_t *)"\x80", 1); while ((context->count[0] & 504) != 448) { SHA1_Update(context, (uint8_t *)"\x00", 1); } SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */ for (i = 0; i < SHA1_DIGEST_SIZE; i++) { digest[i] = (uint8_t)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); } /* Wipe variables */ memset(context, '\0', sizeof(*context)); } /* End of sha1.inl */ webfakes/src/response.h0000644000176200001440000002122314740430263014642 0ustar liggesusers/* response.inl * * Bufferring for HTTP headers for HTTP response. * This function are only intended to be used at the server side. * Optional for HTTP/1.0 and HTTP/1.1, mandatory for HTTP/2. * * This file is part of the CivetWeb project. */ #if defined(NO_RESPONSE_BUFFERING) && defined(USE_HTTP2) #error "HTTP2 works only if NO_RESPONSE_BUFFERING is not set" #endif /* Internal function to free header list */ static void free_buffered_response_header_list(struct mg_connection *conn) { #if !defined(NO_RESPONSE_BUFFERING) while (conn->response_info.num_headers > 0) { conn->response_info.num_headers--; mg_free((void *)conn->response_info .http_headers[conn->response_info.num_headers] .name); conn->response_info.http_headers[conn->response_info.num_headers].name = 0; mg_free((void *)conn->response_info .http_headers[conn->response_info.num_headers] .value); conn->response_info.http_headers[conn->response_info.num_headers] .value = 0; } #else (void)conn; /* Nothing to do */ #endif } /* Send first line of HTTP/1.x response */ static int send_http1_response_status_line(struct mg_connection *conn) { const char *status_txt; const char *http_version = conn->request_info.http_version; int status_code = conn->status_code; if ((status_code < 100) || (status_code > 999)) { /* Set invalid status code to "500 Internal Server Error" */ status_code = 500; } if (!http_version) { http_version = "1.0"; } /* mg_get_response_code_text will never return NULL */ status_txt = mg_get_response_code_text(conn, conn->status_code); if (mg_printf( conn, "HTTP/%s %i %s\r\n", http_version, status_code, status_txt) < 10) { /* Network sending failed */ return 0; } return 1; } /* Initialize a new HTTP response * Parameters: * conn: Current connection handle. * status: HTTP status code (e.g., 200 for "OK"). * Return: * 0: ok * -1: parameter error * -2: invalid connection type * -3: invalid connection status * -4: network error (only if built with NO_RESPONSE_BUFFERING) */ int mg_response_header_start(struct mg_connection *conn, int status) { int ret = 0; if ((conn == NULL) || (status < 100) || (status > 999)) { /* Parameter error */ return -1; } if ((conn->connection_type != CONNECTION_TYPE_REQUEST) || (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) { /* Only allowed in server context */ return -2; } if (conn->request_state != 0) { /* only allowed if nothing was sent up to now */ return -3; } conn->status_code = status; conn->request_state = 1; /* Buffered response is stored, unbuffered response will be sent directly, * but we can only send HTTP/1.x response here */ #if !defined(NO_RESPONSE_BUFFERING) free_buffered_response_header_list(conn); #else if (!send_http1_response_status_line(conn)) { ret = -4; }; conn->request_state = 1; /* Reset from 10 to 1 */ #endif return ret; } /* Add a new HTTP response header line * Parameters: * conn: Current connection handle. * header: Header name. * value: Header value. * value_len: Length of header value, excluding the terminating zero. * Use -1 for "strlen(value)". * Return: * 0: ok * -1: parameter error * -2: invalid connection type * -3: invalid connection status * -4: too many headers * -5: out of memory */ int mg_response_header_add(struct mg_connection *conn, const char *header, const char *value, int value_len) { #if !defined(NO_RESPONSE_BUFFERING) int hidx; #endif if ((conn == NULL) || (header == NULL) || (value == NULL)) { /* Parameter error */ return -1; } if ((conn->connection_type != CONNECTION_TYPE_REQUEST) || (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) { /* Only allowed in server context */ return -2; } if (conn->request_state != 1) { /* only allowed if mg_response_header_start has been called before */ return -3; } #if !defined(NO_RESPONSE_BUFFERING) hidx = conn->response_info.num_headers; if (hidx >= MG_MAX_HEADERS) { /* Too many headers */ return -4; } /* Alloc new element */ conn->response_info.http_headers[hidx].name = mg_strdup_ctx(header, conn->phys_ctx); if (value_len >= 0) { char *hbuf = (char *)mg_malloc_ctx((unsigned)value_len + 1, conn->phys_ctx); if (hbuf) { memcpy(hbuf, value, (unsigned)value_len); hbuf[value_len] = 0; } conn->response_info.http_headers[hidx].value = hbuf; } else { conn->response_info.http_headers[hidx].value = mg_strdup_ctx(value, conn->phys_ctx); } if ((conn->response_info.http_headers[hidx].name == 0) || (conn->response_info.http_headers[hidx].value == 0)) { /* Out of memory */ mg_free((void *)conn->response_info.http_headers[hidx].name); conn->response_info.http_headers[hidx].name = 0; mg_free((void *)conn->response_info.http_headers[hidx].value); conn->response_info.http_headers[hidx].value = 0; return -5; } /* OK, header stored */ conn->response_info.num_headers++; #else if (value_len >= 0) { mg_printf(conn, "%s: %.*s\r\n", header, (int)value_len, value); } else { mg_printf(conn, "%s: %s\r\n", header, value); } conn->request_state = 1; /* Reset from 10 to 1 */ #endif return 0; } /* forward */ static int parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS]); /* Add a complete header string (key + value). * Parameters: * conn: Current connection handle. * http1_headers: Header line(s) in the form "name: value". * Return: * >=0: no error, number of header lines added * -1: parameter error * -2: invalid connection type * -3: invalid connection status * -4: too many headers * -5: out of memory */ int mg_response_header_add_lines(struct mg_connection *conn, const char *http1_headers) { struct mg_header add_hdr[MG_MAX_HEADERS]; int num_hdr, i, ret; char *workbuffer, *parse; /* We need to work on a copy of the work buffer, sice parse_http_headers * will modify */ workbuffer = mg_strdup_ctx(http1_headers, conn->phys_ctx); if (!workbuffer) { /* Out of memory */ return -5; } /* Call existing method to split header buffer */ parse = workbuffer; num_hdr = parse_http_headers(&parse, add_hdr); ret = num_hdr; for (i = 0; i < num_hdr; i++) { int lret = mg_response_header_add(conn, add_hdr[i].name, add_hdr[i].value, -1); if ((ret > 0) && (lret < 0)) { /* Store error return value */ ret = lret; } } /* mg_response_header_add created a copy, so we can free the original */ mg_free(workbuffer); return ret; } #if defined(USE_HTTP2) static int http2_send_response_headers(struct mg_connection *conn); #endif /* Send http response * Parameters: * conn: Current connection handle. * Return: * 0: ok * -1: parameter error * -2: invalid connection type * -3: invalid connection status * -4: network send failed */ int mg_response_header_send(struct mg_connection *conn) { #if !defined(NO_RESPONSE_BUFFERING) int i; int has_date = 0; int has_connection = 0; #endif if (conn == NULL) { /* Parameter error */ return -1; } if ((conn->connection_type != CONNECTION_TYPE_REQUEST) || (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET)) { /* Only allowed in server context */ return -2; } if (conn->request_state != 1) { /* only allowed if mg_response_header_start has been called before */ return -3; } /* State: 2 */ conn->request_state = 2; #if !defined(NO_RESPONSE_BUFFERING) #if defined(USE_HTTP2) if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) { int ret = http2_send_response_headers(conn); free_buffered_response_header_list(conn); return (ret ? 0 : -4); } #endif /* Send */ if (!send_http1_response_status_line(conn)) { free_buffered_response_header_list(conn); return -4; }; for (i = 0; i < conn->response_info.num_headers; i++) { mg_printf(conn, "%s: %s\r\n", conn->response_info.http_headers[i].name, conn->response_info.http_headers[i].value); /* Check for some special headers */ if (!mg_strcasecmp("Date", conn->response_info.http_headers[i].name)) { has_date = 1; } if (!mg_strcasecmp("Connection", conn->response_info.http_headers[i].name)) { has_connection = 1; } } if (!has_date) { time_t curtime = time(NULL); char date[64]; gmt_time_string(date, sizeof(date), &curtime); mg_printf(conn, "Date: %s\r\n", date); } if (!has_connection) { mg_printf(conn, "Connection: %s\r\n", suggest_connection_header(conn)); } #endif mg_write(conn, "\r\n", 2); conn->request_state = 3; /* ok */ free_buffered_response_header_list(conn); return 0; } webfakes/src/civetweb.c0000644000176200001440000225615614741260254014632 0ustar liggesusers/* Copyright (c) 2013-2021 the Civetweb developers * Copyright (c) 2004-2013 Sergey Lyubka * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #if defined(__GNUC__) || defined(__MINGW32__) #ifndef GCC_VERSION #define GCC_VERSION \ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #endif #if GCC_VERSION >= 40500 /* gcc diagnostic pragmas available */ #define GCC_DIAGNOSTIC #endif #endif #if defined(GCC_DIAGNOSTIC) /* Disable unused macros warnings - not all defines are required * for all systems and all compilers. */ # pragma GCC diagnostic ignored "-Wunused-macros" /* A padding warning is just plain useless */ # pragma GCC diagnostic ignored "-Wpadded" #endif #if defined(__clang__) /* GCC does not (yet) support this pragma */ /* We must set some flags for the headers we include. These flags * are reserved ids according to C99, so we need to disable a * warning for that. */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wreserved-id-macro" #endif #if defined(_WIN32) #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */ #endif #if !defined(_WIN32_WINNT) /* defined for tdm-gcc so we can use getnameinfo */ #define _WIN32_WINNT 0x0502 #endif #else #if !defined(_GNU_SOURCE) #define _GNU_SOURCE /* for setgroups(), pthread_setname_np() */ #endif #if defined(__linux__) && !defined(_XOPEN_SOURCE) #define _XOPEN_SOURCE 600 /* For flockfile() on Linux */ #endif #if defined(__LSB_VERSION__) || defined(__sun) #define NEED_TIMEGM #define NO_THREAD_NAME #endif #if !defined(_LARGEFILE_SOURCE) #define _LARGEFILE_SOURCE /* For fseeko(), ftello() */ #endif #if !defined(_FILE_OFFSET_BITS) #define _FILE_OFFSET_BITS 64 /* Use 64-bit file offsets by default */ #endif #if !defined(__STDC_FORMAT_MACROS) #define __STDC_FORMAT_MACROS /* wants this for C++ */ #endif #if !defined(__STDC_LIMIT_MACROS) #define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */ #endif #if !defined(_DARWIN_UNLIMITED_SELECT) #define _DARWIN_UNLIMITED_SELECT #endif #if defined(__sun) #define __EXTENSIONS__ /* to expose flockfile and friends in stdio.h */ #define __inline inline /* not recognized on older compiler versions */ #endif #endif #if defined(__clang__) /* Enable reserved-id-macro warning again. */ # pragma GCC diagnostic pop #endif #if defined(USE_LUA) #define USE_TIMERS #endif #if defined(_MSC_VER) /* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */ # pragma warning(disable : 4306) /* conditional expression is constant: introduced by FD_SET(..) */ # pragma warning(disable : 4127) /* non-constant aggregate initializer: issued due to missing C99 support */ # pragma warning(disable : 4204) /* padding added after data member */ # pragma warning(disable : 4820) /* not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */ # pragma warning(disable : 4668) /* no function prototype given: converting '()' to '(void)' */ # pragma warning(disable : 4255) /* function has been selected for automatic inline expansion */ # pragma warning(disable : 4711) #endif /* This code uses static_assert to check some conditions. * Unfortunately some compilers still do not support it, so we have a * replacement function here. */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201100L #define mg_static_assert _Static_assert #elif defined(__cplusplus) && __cplusplus >= 201103L #define mg_static_assert static_assert #else char static_assert_replacement[1]; #define mg_static_assert(cond, txt) \ extern char static_assert_replacement[(cond) ? 1 : -1] #endif mg_static_assert(sizeof(int) == 4 || sizeof(int) == 8, "int data type size check"); mg_static_assert(sizeof(void *) == 4 || sizeof(void *) == 8, "pointer data type size check"); mg_static_assert(sizeof(void *) >= sizeof(int), "data type size check"); /* Select queue implementation. Diagnosis features originally only implemented * for the "ALTERNATIVE_QUEUE" have been ported to the previous queue * implementation (NO_ALTERNATIVE_QUEUE) as well. The new configuration value * "CONNECTION_QUEUE_SIZE" is only available for the previous queue * implementation, since the queue length is independent from the number of * worker threads there, while the new queue is one element per worker thread. * */ #if defined(NO_ALTERNATIVE_QUEUE) && defined(ALTERNATIVE_QUEUE) /* The queues are exclusive or - only one can be used. */ #error \ "Define ALTERNATIVE_QUEUE or NO_ALTERNATIVE_QUEUE (or none of them), but not both" #endif #if !defined(NO_ALTERNATIVE_QUEUE) && !defined(ALTERNATIVE_QUEUE) /* Use a default implementation */ #define NO_ALTERNATIVE_QUEUE #endif #if defined(NO_FILESYSTEMS) && !defined(NO_FILES) /* File system access: * NO_FILES = do not serve any files from the file system automatically. * However, with NO_FILES CivetWeb may still write log files, read access * control files, default error page files or use API functions like * mg_send_file in callbacks to send files from the server local * file system. * NO_FILES only disables the automatic mapping between URLs and local * file names. * NO_FILESYSTEM = do not access any file at all. Useful for embedded * devices without file system. Logging to files in not available * (use callbacks instead) and API functions like mg_send_file are not * available. * If NO_FILESYSTEM is set, NO_FILES must be set as well. */ #error "Inconsistent build flags, NO_FILESYSTEMS requires NO_FILES" #endif /* DTL -- including winsock2.h works better if lean and mean */ #if !defined(WIN32_LEAN_AND_MEAN) #define WIN32_LEAN_AND_MEAN #endif #if defined(__SYMBIAN32__) /* According to https://en.wikipedia.org/wiki/Symbian#History, * Symbian is no longer maintained since 2014-01-01. * Support for Symbian has been removed from CivetWeb */ #error "Symbian is no longer maintained. CivetWeb no longer supports Symbian." #endif /* __SYMBIAN32__ */ #if defined(__ZEPHYR__) #include #include #include #include #include #include #include #include #include #include #include /* Max worker threads is the max of pthreads minus the main application thread * and minus the main civetweb thread, thus -2 */ #define MAX_WORKER_THREADS (CONFIG_MAX_PTHREAD_COUNT - 2) #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) #define ZEPHYR_STACK_SIZE USE_STACK_SIZE #else #define ZEPHYR_STACK_SIZE (1024 * 16) #endif K_THREAD_STACK_DEFINE(civetweb_main_stack, ZEPHYR_STACK_SIZE); K_THREAD_STACK_ARRAY_DEFINE(civetweb_worker_stacks, MAX_WORKER_THREADS, ZEPHYR_STACK_SIZE); static int zephyr_worker_stack_index; #endif #if !defined(CIVETWEB_HEADER_INCLUDED) /* Include the header file here, so the CivetWeb interface is defined for the * entire implementation, including the following forward definitions. */ #include "civetweb.h" #endif #if !defined(DEBUG_TRACE) #if defined(DEBUG) static void DEBUG_TRACE_FUNC(const char *func, unsigned line, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(3, 4); #define DEBUG_TRACE(fmt, ...) \ DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__) #define NEED_DEBUG_TRACE_FUNC #if !defined(DEBUG_TRACE_STREAM) #define DEBUG_TRACE_STREAM stdout #endif #else #define DEBUG_TRACE(fmt, ...) \ do { \ } while (0) #endif /* DEBUG */ #endif /* DEBUG_TRACE */ #if !defined(DEBUG_ASSERT) #if defined(DEBUG) #include #define DEBUG_ASSERT(cond) \ do { \ if (!(cond)) { \ DEBUG_TRACE("ASSERTION FAILED: %s", #cond); \ exit(2); /* Exit with error */ \ } \ } while (0) #else #define DEBUG_ASSERT(cond) #endif /* DEBUG */ #endif #if defined(__GNUC__) && defined(GCC_INSTRUMENTATION) void __cyg_profile_func_enter(void *this_fn, void *call_site) __attribute__((no_instrument_function)); void __cyg_profile_func_exit(void *this_fn, void *call_site) __attribute__((no_instrument_function)); void __cyg_profile_func_enter(void *this_fn, void *call_site) { if ((void *)this_fn != (void *)printf) { /* printf("E %p %p\n", this_fn, call_site); */ } } void __cyg_profile_func_exit(void *this_fn, void *call_site) { if ((void *)this_fn != (void *)printf) { /* printf("X %p %p\n", this_fn, call_site); */ } } #endif #if !defined(IGNORE_UNUSED_RESULT) #define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1)) #endif #if defined(__GNUC__) || defined(__MINGW32__) /* GCC unused function attribute seems fundamentally broken. * Several attempts to tell the compiler "THIS FUNCTION MAY BE USED * OR UNUSED" for individual functions failed. * Either the compiler creates an "unused-function" warning if a * function is not marked with __attribute__((unused)). * On the other hand, if the function is marked with this attribute, * but is used, the compiler raises a completely idiotic * "used-but-marked-unused" warning - and * # pragma GCC diagnostic ignored "-Wused-but-marked-unused" * raises error: unknown option after "# pragma GCC diagnostic". * Disable this warning completely, until the GCC guys sober up * again. */ # pragma GCC diagnostic ignored "-Wunused-function" #define FUNCTION_MAY_BE_UNUSED /* __attribute__((unused)) */ #else #define FUNCTION_MAY_BE_UNUSED #endif /* Some ANSI #includes are not available on Windows CE and Zephyr */ #if !defined(_WIN32_WCE) && !defined(__ZEPHYR__) #include #include #include #include #include #include #endif /* !_WIN32_WCE */ #if defined(__clang__) /* When using -Weverything, clang does not accept it's own headers * in a release build configuration. Disable what is too much in * -Weverything. */ # pragma clang diagnostic ignored "-Wdisabled-macro-expansion" #endif #if defined(__GNUC__) || defined(__MINGW32__) /* Who on earth came to the conclusion, using __DATE__ should rise * an "expansion of date or time macro is not reproducible" * warning. That's exactly what was intended by using this macro. * Just disable this nonsense warning. */ /* And disabling them does not work either: * # pragma clang diagnostic ignored "-Wno-error=date-time" * # pragma clang diagnostic ignored "-Wdate-time" * So we just have to disable ALL warnings for some lines * of code. * This seems to be a known GCC bug, not resolved since 2012: * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431 */ #endif #if defined(__MACH__) && defined(__APPLE__) /* Apple OSX section */ #if defined(__clang__) #if (__clang_major__ == 3) && ((__clang_minor__ == 7) || (__clang_minor__ == 8)) /* Avoid warnings for Xcode 7. It seems it does no longer exist in Xcode 8 */ # pragma clang diagnostic ignored "-Wno-reserved-id-macro" # pragma clang diagnostic ignored "-Wno-keyword-macro" #endif #endif #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (1) #endif #ifndef CLOCK_REALTIME #define CLOCK_REALTIME (2) #endif #include #include #include #include #include /* clock_gettime is not implemented on OSX prior to 10.12 */ static int _civet_clock_gettime(int clk_id, struct timespec *t) { memset(t, 0, sizeof(*t)); if (clk_id == CLOCK_REALTIME) { struct timeval now; int rv = gettimeofday(&now, NULL); if (rv) { return rv; } t->tv_sec = now.tv_sec; t->tv_nsec = now.tv_usec * 1000; return 0; } else if (clk_id == CLOCK_MONOTONIC) { static uint64_t clock_start_time = 0; static mach_timebase_info_data_t timebase_ifo = {0, 0}; uint64_t now = mach_absolute_time(); if (clock_start_time == 0) { kern_return_t mach_status = mach_timebase_info(&timebase_ifo); DEBUG_ASSERT(mach_status == KERN_SUCCESS); /* appease "unused variable" warning for release builds */ (void)mach_status; clock_start_time = now; } now = (uint64_t)((double)(now - clock_start_time) * (double)timebase_ifo.numer / (double)timebase_ifo.denom); t->tv_sec = now / 1000000000; t->tv_nsec = now % 1000000000; return 0; } return -1; /* EINVAL - Clock ID is unknown */ } /* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */ #if defined(__CLOCK_AVAILABILITY) /* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be * declared but it may be NULL at runtime. So we need to check before using * it. */ static int _civet_safe_clock_gettime(int clk_id, struct timespec *t) { if (clock_gettime) { return clock_gettime(clk_id, t); } return _civet_clock_gettime(clk_id, t); } #define clock_gettime _civet_safe_clock_gettime #else #define clock_gettime _civet_clock_gettime #endif #endif #if defined(_WIN32) #define ERROR_TRY_AGAIN(err) ((err) == WSAEWOULDBLOCK) #else /* Unix might return different error codes indicating to try again. * For Linux EAGAIN==EWOULDBLOCK, maybe EAGAIN!=EWOULDBLOCK is history from * decades ago, but better check both and let the compiler optimize it. */ #define ERROR_TRY_AGAIN(err) \ (((err) == EAGAIN) || ((err) == EWOULDBLOCK) || ((err) == EINTR)) #endif #if defined(USE_ZLIB) #include "zconf.h" #include "zlib.h" #endif /********************************************************************/ /* CivetWeb configuration defines */ /********************************************************************/ /* Maximum number of threads that can be configured. * The number of threads actually created depends on the "num_threads" * configuration parameter, but this is the upper limit. */ #if !defined(MAX_WORKER_THREADS) #define MAX_WORKER_THREADS (1024 * 64) /* in threads (count) */ #endif /* Timeout interval for select/poll calls. * The timeouts depend on "*_timeout_ms" configuration values, but long * timeouts are split into timouts as small as SOCKET_TIMEOUT_QUANTUM. * This reduces the time required to stop the server. */ #if !defined(SOCKET_TIMEOUT_QUANTUM) #define SOCKET_TIMEOUT_QUANTUM (2000) /* in ms */ #endif /* Do not try to compress files smaller than this limit. */ #if !defined(MG_FILE_COMPRESSION_SIZE_LIMIT) #define MG_FILE_COMPRESSION_SIZE_LIMIT (1024) /* in bytes */ #endif #if !defined(PASSWORDS_FILE_NAME) #define PASSWORDS_FILE_NAME ".htpasswd" #endif /* Initial buffer size for all CGI environment variables. In case there is * not enough space, another block is allocated. */ #if !defined(CGI_ENVIRONMENT_SIZE) #define CGI_ENVIRONMENT_SIZE (4096) /* in bytes */ #endif /* Maximum number of environment variables. */ #if !defined(MAX_CGI_ENVIR_VARS) #define MAX_CGI_ENVIR_VARS (256) /* in variables (count) */ #endif /* General purpose buffer size. */ #if !defined(MG_BUF_LEN) /* in bytes */ #define MG_BUF_LEN (1024 * 8) #endif /********************************************************************/ /* Helper macros */ #if !defined(ARRAY_SIZE) #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) #endif #include /* Standard defines */ #if !defined(INT64_MAX) #define INT64_MAX (9223372036854775807) #endif #define SHUTDOWN_RD (0) #define SHUTDOWN_WR (1) #define SHUTDOWN_BOTH (2) mg_static_assert(MAX_WORKER_THREADS >= 1, "worker threads must be a positive number"); mg_static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t data type size check"); #if defined(_WIN32) /* WINDOWS include block */ #include /* *alloc( */ #include /* *alloc( */ #include /* struct timespec */ #include #include /* DTL add for SO_EXCLUSIVE */ #include typedef const char *SOCK_OPT_TYPE; /* For a detailed description of these *_PATH_MAX defines, see * https://github.com/civetweb/civetweb/issues/937. */ /* UTF8_PATH_MAX is a char buffer size for 259 BMP characters in UTF-8 plus * null termination, rounded up to the next 4 bytes boundary */ #define UTF8_PATH_MAX (3 * 260) /* UTF16_PATH_MAX is the 16-bit wchar_t buffer size required for 259 BMP * characters plus termination. (Note: wchar_t is 16 bit on Windows) */ #define UTF16_PATH_MAX (260) #if !defined(_IN_PORT_T) #if !defined(in_port_t) #define in_port_t u_short #endif #endif #if defined(_WIN32_WCE) #error "WinCE support has ended" #endif #include #include #include #define MAKEUQUAD(lo, hi) \ ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32)) #define RATE_DIFF (10000000) /* 100 nsecs */ #define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de)) #define SYS2UNIX_TIME(lo, hi) \ ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF)) /* Visual Studio 6 does not know __func__ or __FUNCTION__ * The rest of MS compilers use __FUNCTION__, not C99 __func__ * Also use _strtoui64 on modern M$ compilers */ #if defined(_MSC_VER) #if (_MSC_VER < 1300) #define STRX(x) #x #define STR(x) STRX(x) #define __func__ __FILE__ ":" STR(__LINE__) #define strtoull(x, y, z) ((unsigned __int64)_atoi64(x)) #define strtoll(x, y, z) (_atoi64(x)) #else #define __func__ __FUNCTION__ #define strtoull(x, y, z) (_strtoui64(x, y, z)) #define strtoll(x, y, z) (_strtoi64(x, y, z)) #endif #endif /* _MSC_VER */ #define ERRNO ((int)(GetLastError())) #define NO_SOCKLEN_T #if defined(_WIN64) || defined(__MINGW64__) #if !defined(SSL_LIB) #if defined(OPENSSL_API_3_0) #define SSL_LIB "libssl-3-x64.dll" #define CRYPTO_LIB "libcrypto-3-x64.dll" #endif #if defined(OPENSSL_API_1_1) #define SSL_LIB "libssl-1_1-x64.dll" #define CRYPTO_LIB "libcrypto-1_1-x64.dll" #endif /* OPENSSL_API_1_1 */ #if defined(OPENSSL_API_1_0) #define SSL_LIB "ssleay64.dll" #define CRYPTO_LIB "libeay64.dll" #endif /* OPENSSL_API_1_0 */ #endif #else /* defined(_WIN64) || defined(__MINGW64__) */ #if !defined(SSL_LIB) #if defined(OPENSSL_API_3_0) #define SSL_LIB "libssl-3.dll" #define CRYPTO_LIB "libcrypto-3.dll" #endif #if defined(OPENSSL_API_1_1) #define SSL_LIB "libssl-1_1.dll" #define CRYPTO_LIB "libcrypto-1_1.dll" #endif /* OPENSSL_API_1_1 */ #if defined(OPENSSL_API_1_0) #define SSL_LIB "ssleay32.dll" #define CRYPTO_LIB "libeay32.dll" #endif /* OPENSSL_API_1_0 */ #endif /* SSL_LIB */ #endif /* defined(_WIN64) || defined(__MINGW64__) */ #define O_NONBLOCK (0) #if !defined(W_OK) #define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */ #endif #define _POSIX_ #include #define INT64_FMT PRId64 #define UINT64_FMT PRIu64 #define WINCDECL __cdecl #define vsnprintf_impl _vsnprintf #define access _access #define mg_sleep(x) (Sleep(x)) #define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY) #if !defined(popen) #define popen(x, y) (_popen(x, y)) #endif #if !defined(pclose) #define pclose(x) (_pclose(x)) #endif #define close(x) (_close(x)) #define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y))) #define RTLD_LAZY (0) #define fseeko(x, y, z) ((_lseeki64(_fileno(x), (y), (z)) == -1) ? -1 : 0) #define fdopen(x, y) (_fdopen((x), (y))) #define write(x, y, z) (_write((x), (y), (unsigned)z)) #define read(x, y, z) (_read((x), (y), (unsigned)z)) #define flockfile(x) ((void)pthread_mutex_lock(&global_log_file_lock)) #define funlockfile(x) ((void)pthread_mutex_unlock(&global_log_file_lock)) #define sleep(x) (Sleep((x)*1000)) #define rmdir(x) (_rmdir(x)) #if defined(_WIN64) || !defined(__MINGW32__) /* Only MinGW 32 bit is missing this function */ #define timegm(x) (_mkgmtime(x)) #else time_t timegm(struct tm *tm); #define NEED_TIMEGM #endif #if !defined(fileno) #define fileno(x) (_fileno(x)) #endif /* !fileno MINGW #defines fileno */ typedef struct { CRITICAL_SECTION sec; /* Immovable */ } pthread_mutex_t; typedef DWORD pthread_key_t; typedef HANDLE pthread_t; typedef struct { pthread_mutex_t threadIdSec; struct mg_workerTLS *waiting_thread; /* The chain of threads */ } pthread_cond_t; #if !defined(__clockid_t_defined) typedef DWORD clockid_t; #endif #if !defined(CLOCK_MONOTONIC) #define CLOCK_MONOTONIC (1) #endif #if !defined(CLOCK_REALTIME) #define CLOCK_REALTIME (2) #endif #if !defined(CLOCK_THREAD) #define CLOCK_THREAD (3) #endif #if !defined(CLOCK_PROCESS) #define CLOCK_PROCESS (4) #endif #if defined(_MSC_VER) && (_MSC_VER >= 1900) #define _TIMESPEC_DEFINED #endif #if !defined(_TIMESPEC_DEFINED) struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; #endif #if !defined(WIN_PTHREADS_TIME_H) #define MUST_IMPLEMENT_CLOCK_GETTIME #endif #if defined(MUST_IMPLEMENT_CLOCK_GETTIME) #define clock_gettime mg_clock_gettime static int clock_gettime(clockid_t clk_id, struct timespec *tp) { FILETIME ft; ULARGE_INTEGER li, li2; BOOL ok = FALSE; double d; static double perfcnt_per_sec = 0.0; static BOOL initialized = FALSE; if (!initialized) { QueryPerformanceFrequency((LARGE_INTEGER *)&li); perfcnt_per_sec = 1.0 / li.QuadPart; initialized = TRUE; } if (tp) { memset(tp, 0, sizeof(*tp)); if (clk_id == CLOCK_REALTIME) { /* BEGIN: CLOCK_REALTIME = wall clock (date and time) */ GetSystemTimeAsFileTime(&ft); li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */ tp->tv_sec = (time_t)(li.QuadPart / 10000000); tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100; ok = TRUE; /* END: CLOCK_REALTIME */ } else if (clk_id == CLOCK_MONOTONIC) { /* BEGIN: CLOCK_MONOTONIC = stopwatch (time differences) */ QueryPerformanceCounter((LARGE_INTEGER *)&li); d = li.QuadPart * perfcnt_per_sec; tp->tv_sec = (time_t)d; d -= (double)tp->tv_sec; tp->tv_nsec = (long)(d * 1.0E9); ok = TRUE; /* END: CLOCK_MONOTONIC */ } else if (clk_id == CLOCK_THREAD) { /* BEGIN: CLOCK_THREAD = CPU usage of thread */ FILETIME t_create, t_exit, t_kernel, t_user; if (GetThreadTimes(GetCurrentThread(), &t_create, &t_exit, &t_kernel, &t_user)) { li.LowPart = t_user.dwLowDateTime; li.HighPart = t_user.dwHighDateTime; li2.LowPart = t_kernel.dwLowDateTime; li2.HighPart = t_kernel.dwHighDateTime; li.QuadPart += li2.QuadPart; tp->tv_sec = (time_t)(li.QuadPart / 10000000); tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100; ok = TRUE; } /* END: CLOCK_THREAD */ } else if (clk_id == CLOCK_PROCESS) { /* BEGIN: CLOCK_PROCESS = CPU usage of process */ FILETIME t_create, t_exit, t_kernel, t_user; if (GetProcessTimes(GetCurrentProcess(), &t_create, &t_exit, &t_kernel, &t_user)) { li.LowPart = t_user.dwLowDateTime; li.HighPart = t_user.dwHighDateTime; li2.LowPart = t_kernel.dwLowDateTime; li2.HighPart = t_kernel.dwHighDateTime; li.QuadPart += li2.QuadPart; tp->tv_sec = (time_t)(li.QuadPart / 10000000); tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100; ok = TRUE; } /* END: CLOCK_PROCESS */ } else { /* BEGIN: unknown clock */ /* ok = FALSE; already set by init */ /* END: unknown clock */ } } return ok ? 0 : -1; } #endif #define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */ static int pthread_mutex_lock(pthread_mutex_t *); static int pthread_mutex_unlock(pthread_mutex_t *); static void path_to_unicode(const struct mg_connection *conn, const char *path, wchar_t *wbuf, size_t wbuf_len); /* All file operations need to be rewritten to solve #246. */ struct mg_file; static const char *mg_fgets(char *buf, size_t size, struct mg_file *filep); /* POSIX dirent interface */ struct dirent { char d_name[UTF8_PATH_MAX]; }; typedef struct DIR { HANDLE handle; WIN32_FIND_DATAW info; struct dirent result; } DIR; #if defined(HAVE_POLL) #define mg_pollfd pollfd #else struct mg_pollfd { SOCKET fd; short events; short revents; }; #endif /* Mark required libraries */ #if defined(_MSC_VER) # pragma comment(lib, "Ws2_32.lib") #endif #else /* defined(_WIN32) - WINDOWS vs UNIX include block */ #include /* Linux & co. internally use UTF8 */ #define UTF8_PATH_MAX (PATH_MAX) typedef const void *SOCK_OPT_TYPE; #if defined(ANDROID) typedef unsigned short int in_port_t; #endif #if !defined(__ZEPHYR__) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(USE_X_DOM_SOCKET) #include #endif #endif #define vsnprintf_impl vsnprintf #if !defined(NO_SSL_DL) && !defined(NO_SSL) #include #endif #if defined(__MACH__) && defined(__APPLE__) #define SSL_LIB "libssl.dylib" #define CRYPTO_LIB "libcrypto.dylib" #else #if !defined(SSL_LIB) #define SSL_LIB "libssl.so" #endif #if !defined(CRYPTO_LIB) #define CRYPTO_LIB "libcrypto.so" #endif #endif #if !defined(O_BINARY) #define O_BINARY (0) #endif /* O_BINARY */ #define closesocket(a) (close(a)) #define mg_mkdir(conn, path, mode) (mkdir(path, mode)) #define mg_remove(conn, x) (remove(x)) #define mg_sleep(x) (usleep((x)*1000)) #define mg_opendir(conn, x) (opendir(x)) #define mg_closedir(x) (closedir(x)) #define mg_readdir(x) (readdir(x)) #define ERRNO (errno) #define INVALID_SOCKET (-1) #define INT64_FMT PRId64 #define UINT64_FMT PRIu64 typedef int SOCKET; #define WINCDECL #if defined(__hpux) /* HPUX 11 does not have monotonic, fall back to realtime */ #if !defined(CLOCK_MONOTONIC) #define CLOCK_MONOTONIC CLOCK_REALTIME #endif /* HPUX defines socklen_t incorrectly as size_t which is 64bit on * Itanium. Without defining _XOPEN_SOURCE or _XOPEN_SOURCE_EXTENDED * the prototypes use int* rather than socklen_t* which matches the * actual library expectation. When called with the wrong size arg * accept() returns a zero client inet addr and check_acl() always * fails. Since socklen_t is widely used below, just force replace * their typedef with int. - DTL */ #define socklen_t int #endif /* hpux */ #define mg_pollfd pollfd #endif /* defined(_WIN32) - WINDOWS vs UNIX include block */ /* In case our C library is missing "timegm", provide an implementation */ #if defined(NEED_TIMEGM) static inline int is_leap(int y) { return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0; } static inline int count_leap(int y) { return (y - 1969) / 4 - (y - 1901) / 100 + (y - 1601) / 400; } time_t timegm(struct tm *tm) { static const unsigned short ydays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; int year = tm->tm_year + 1900; int mon = tm->tm_mon; int mday = tm->tm_mday - 1; int hour = tm->tm_hour; int min = tm->tm_min; int sec = tm->tm_sec; if (year < 1970 || mon < 0 || mon > 11 || mday < 0 || (mday >= ydays[mon + 1] - ydays[mon] + (mon == 1 && is_leap(year) ? 1 : 0)) || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60) return -1; time_t res = year - 1970; res *= 365; res += mday; res += ydays[mon] + (mon > 1 && is_leap(year) ? 1 : 0); res += count_leap(year); res *= 24; res += hour; res *= 60; res += min; res *= 60; res += sec; return res; } #endif /* NEED_TIMEGM */ /* va_copy should always be a macro, C99 and C++11 - DTL */ #if !defined(va_copy) #define va_copy(x, y) ((x) = (y)) #endif #if defined(_WIN32) /* Create substitutes for POSIX functions in Win32. */ #if defined(GCC_DIAGNOSTIC) /* Show no warning in case system functions are not used. */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-function" #endif static pthread_mutex_t global_log_file_lock; FUNCTION_MAY_BE_UNUSED static DWORD pthread_self(void) { return GetCurrentThreadId(); } FUNCTION_MAY_BE_UNUSED static int pthread_key_create( pthread_key_t *key, void (*_ignored)(void *) /* destructor not supported for Windows */ ) { (void)_ignored; if ((key != 0)) { *key = TlsAlloc(); return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1; } return -2; } FUNCTION_MAY_BE_UNUSED static int pthread_key_delete(pthread_key_t key) { return TlsFree(key) ? 0 : 1; } FUNCTION_MAY_BE_UNUSED static int pthread_setspecific(pthread_key_t key, void *value) { return TlsSetValue(key, value) ? 0 : 1; } FUNCTION_MAY_BE_UNUSED static void * pthread_getspecific(pthread_key_t key) { return TlsGetValue(key); } #if defined(GCC_DIAGNOSTIC) /* Enable unused function warning again */ # pragma GCC diagnostic pop #endif static struct pthread_mutex_undefined_struct *pthread_mutex_attr = NULL; #else static pthread_mutexattr_t pthread_mutex_attr; #endif /* _WIN32 */ #if defined(GCC_DIAGNOSTIC) /* Show no warning in case system functions are not used. */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-function" #endif /* defined(GCC_DIAGNOSTIC) */ #if defined(__clang__) /* Show no warning in case system functions are not used. */ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunused-function" #endif static pthread_mutex_t global_lock_mutex; FUNCTION_MAY_BE_UNUSED static void mg_global_lock(void) { (void)pthread_mutex_lock(&global_lock_mutex); } FUNCTION_MAY_BE_UNUSED static void mg_global_unlock(void) { (void)pthread_mutex_unlock(&global_lock_mutex); } #if defined(_WIN64) mg_static_assert(SIZE_MAX == 0xFFFFFFFFFFFFFFFFu, "Mismatch for atomic types"); #elif defined(_WIN32) mg_static_assert(SIZE_MAX == 0xFFFFFFFFu, "Mismatch for atomic types"); #endif /* Atomic functions working on ptrdiff_t ("signed size_t"). * Operations: Increment, Decrement, Add, Maximum. * Up to size_t, they do not an atomic "load" operation. */ FUNCTION_MAY_BE_UNUSED static ptrdiff_t mg_atomic_inc(volatile ptrdiff_t *addr) { ptrdiff_t ret; #if defined(_WIN64) && defined(_WIN32) && !defined(NO_ATOMICS) ret = InterlockedIncrement64(addr); #elif defined(__GNUC__) \ && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \ && !defined(NO_ATOMICS) ret = __sync_add_and_fetch(addr, 1); #elif defined(_WIN32) && !defined(NO_ATOMICS) ret = InterlockedIncrement(addr); #else mg_global_lock(); ret = (++(*addr)); mg_global_unlock(); #endif return ret; } FUNCTION_MAY_BE_UNUSED static ptrdiff_t mg_atomic_dec(volatile ptrdiff_t *addr) { ptrdiff_t ret; #if defined(_WIN64) && defined(_WIN32) && !defined(NO_ATOMICS) ret = InterlockedDecrement64(addr); #elif defined(__GNUC__) \ && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \ && !defined(NO_ATOMICS) ret = __sync_sub_and_fetch(addr, 1); #elif defined(_WIN32) && !defined(NO_ATOMICS) ret = InterlockedDecrement(addr); #else mg_global_lock(); ret = (--(*addr)); mg_global_unlock(); #endif return ret; } #if defined(USE_SERVER_STATS) || defined(STOP_FLAG_NEEDS_LOCK) static ptrdiff_t mg_atomic_add(volatile ptrdiff_t *addr, ptrdiff_t value) { ptrdiff_t ret; #if defined(_WIN64) && !defined(NO_ATOMICS) ret = InterlockedAdd64(addr, value); #elif defined(_WIN32) && !defined(NO_ATOMICS) ret = InterlockedExchangeAdd(addr, value) + value; #elif defined(__GNUC__) \ && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \ && !defined(NO_ATOMICS) ret = __sync_add_and_fetch(addr, value); #else mg_global_lock(); *addr += value; ret = (*addr); mg_global_unlock(); #endif return ret; } FUNCTION_MAY_BE_UNUSED static ptrdiff_t mg_atomic_compare_and_swap(volatile ptrdiff_t *addr, ptrdiff_t oldval, ptrdiff_t newval) { ptrdiff_t ret; #if defined(_WIN64) && !defined(NO_ATOMICS) ret = InterlockedCompareExchange64(addr, newval, oldval); #elif defined(_WIN32) && !defined(NO_ATOMICS) ret = InterlockedCompareExchange(addr, newval, oldval); #elif defined(__GNUC__) \ && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \ && !defined(NO_ATOMICS) ret = __sync_val_compare_and_swap(addr, oldval, newval); #else mg_global_lock(); ret = *addr; if ((ret != newval) && (ret == oldval)) { *addr = newval; } mg_global_unlock(); #endif return ret; } static void mg_atomic_max(volatile ptrdiff_t *addr, ptrdiff_t value) { register ptrdiff_t tmp = *addr; #if defined(_WIN64) && !defined(NO_ATOMICS) while (tmp < value) { tmp = InterlockedCompareExchange64(addr, value, tmp); } #elif defined(_WIN32) && !defined(NO_ATOMICS) while (tmp < value) { tmp = InterlockedCompareExchange(addr, value, tmp); } #elif defined(__GNUC__) \ && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \ && !defined(NO_ATOMICS) while (tmp < value) { tmp = __sync_val_compare_and_swap(addr, tmp, value); } #else mg_global_lock(); if (*addr < value) { *addr = value; } mg_global_unlock(); #endif } static int64_t mg_atomic_add64(volatile int64_t *addr, int64_t value) { int64_t ret; #if defined(_WIN64) && !defined(NO_ATOMICS) ret = InterlockedAdd64(addr, value); #elif defined(_WIN32) && !defined(NO_ATOMICS) ret = InterlockedExchangeAdd64(addr, value) + value; #elif defined(__GNUC__) \ && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0))) \ && !defined(NO_ATOMICS) ret = __sync_add_and_fetch(addr, value); #else mg_global_lock(); *addr += value; ret = (*addr); mg_global_unlock(); #endif return ret; } #endif #if defined(GCC_DIAGNOSTIC) /* Show no warning in case system functions are not used. */ # pragma GCC diagnostic pop #endif /* defined(GCC_DIAGNOSTIC) */ #if defined(__clang__) /* Show no warning in case system functions are not used. */ # pragma clang diagnostic pop #endif #if defined(USE_SERVER_STATS) struct mg_memory_stat { volatile ptrdiff_t totalMemUsed; volatile ptrdiff_t maxMemUsed; volatile ptrdiff_t blockCount; }; static struct mg_memory_stat *get_memory_stat(struct mg_context *ctx); static void * mg_malloc_ex(size_t size, struct mg_context *ctx, const char *file, unsigned line) { void *data = malloc(size + 2 * sizeof(uintptr_t)); void *memory = 0; struct mg_memory_stat *mstat = get_memory_stat(ctx); #if defined(MEMORY_DEBUGGING) char mallocStr[256]; #else (void)file; (void)line; #endif if (data) { ptrdiff_t mmem = mg_atomic_add(&mstat->totalMemUsed, (ptrdiff_t)size); mg_atomic_max(&mstat->maxMemUsed, mmem); mg_atomic_inc(&mstat->blockCount); ((uintptr_t *)data)[0] = size; ((uintptr_t *)data)[1] = (uintptr_t)mstat; memory = (void *)(((char *)data) + 2 * sizeof(uintptr_t)); } #if defined(MEMORY_DEBUGGING) sprintf(mallocStr, "MEM: %p %5lu alloc %7lu %4lu --- %s:%u\n", memory, (unsigned long)size, (unsigned long)mstat->totalMemUsed, (unsigned long)mstat->blockCount, file, line); DEBUG_TRACE("%s", mallocStr); #endif return memory; } static void * mg_calloc_ex(size_t count, size_t size, struct mg_context *ctx, const char *file, unsigned line) { void *data = mg_malloc_ex(size * count, ctx, file, line); if (data) { memset(data, 0, size * count); } return data; } static void mg_free_ex(void *memory, const char *file, unsigned line) { #if defined(MEMORY_DEBUGGING) char mallocStr[256]; #else (void)file; (void)line; #endif if (memory) { void *data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t)); uintptr_t size = ((uintptr_t *)data)[0]; struct mg_memory_stat *mstat = (struct mg_memory_stat *)(((uintptr_t *)data)[1]); mg_atomic_add(&mstat->totalMemUsed, -(ptrdiff_t)size); mg_atomic_dec(&mstat->blockCount); #if defined(MEMORY_DEBUGGING) sprintf(mallocStr, "MEM: %p %5lu free %7lu %4lu --- %s:%u\n", memory, (unsigned long)size, (unsigned long)mstat->totalMemUsed, (unsigned long)mstat->blockCount, file, line); DEBUG_TRACE("%s", mallocStr); #endif free(data); } } static void * mg_realloc_ex(void *memory, size_t newsize, struct mg_context *ctx, const char *file, unsigned line) { void *data; void *_realloc; uintptr_t oldsize; #if defined(MEMORY_DEBUGGING) char mallocStr[256]; #else (void)file; (void)line; #endif if (newsize) { if (memory) { /* Reallocate existing block */ struct mg_memory_stat *mstat; data = (void *)(((char *)memory) - 2 * sizeof(uintptr_t)); oldsize = ((uintptr_t *)data)[0]; mstat = (struct mg_memory_stat *)((uintptr_t *)data)[1]; _realloc = realloc(data, newsize + 2 * sizeof(uintptr_t)); if (_realloc) { data = _realloc; mg_atomic_add(&mstat->totalMemUsed, -(ptrdiff_t)oldsize); #if defined(MEMORY_DEBUGGING) sprintf(mallocStr, "MEM: %p %5lu r-free %7lu %4lu --- %s:%u\n", memory, (unsigned long)oldsize, (unsigned long)mstat->totalMemUsed, (unsigned long)mstat->blockCount, file, line); DEBUG_TRACE("%s", mallocStr); #endif mg_atomic_add(&mstat->totalMemUsed, (ptrdiff_t)newsize); #if defined(MEMORY_DEBUGGING) sprintf(mallocStr, "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n", memory, (unsigned long)newsize, (unsigned long)mstat->totalMemUsed, (unsigned long)mstat->blockCount, file, line); DEBUG_TRACE("%s", mallocStr); #endif *(uintptr_t *)data = newsize; data = (void *)(((char *)data) + 2 * sizeof(uintptr_t)); } else { #if defined(MEMORY_DEBUGGING) DEBUG_TRACE("%s", "MEM: realloc failed\n"); #endif return _realloc; } } else { /* Allocate new block */ data = mg_malloc_ex(newsize, ctx, file, line); } } else { /* Free existing block */ data = 0; mg_free_ex(memory, file, line); } return data; } #define mg_malloc(a) mg_malloc_ex(a, NULL, __FILE__, __LINE__) #define mg_calloc(a, b) mg_calloc_ex(a, b, NULL, __FILE__, __LINE__) #define mg_realloc(a, b) mg_realloc_ex(a, b, NULL, __FILE__, __LINE__) #define mg_free(a) mg_free_ex(a, __FILE__, __LINE__) #define mg_malloc_ctx(a, c) mg_malloc_ex(a, c, __FILE__, __LINE__) #define mg_calloc_ctx(a, b, c) mg_calloc_ex(a, b, c, __FILE__, __LINE__) #define mg_realloc_ctx(a, b, c) mg_realloc_ex(a, b, c, __FILE__, __LINE__) #else /* USE_SERVER_STATS */ static __inline void * mg_malloc(size_t a) { return malloc(a); } static __inline void * mg_calloc(size_t a, size_t b) { return calloc(a, b); } static __inline void * mg_realloc(void *a, size_t b) { return realloc(a, b); } static __inline void mg_free(void *a) { free(a); } #define mg_malloc_ctx(a, c) mg_malloc(a) #define mg_calloc_ctx(a, b, c) mg_calloc(a, b) #define mg_realloc_ctx(a, b, c) mg_realloc(a, b) #define mg_free_ctx(a, c) mg_free(a) #endif /* USE_SERVER_STATS */ static void mg_vsnprintf(const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, const char *fmt, va_list ap); static void mg_snprintf(const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(5, 6); /* This following lines are just meant as a reminder to use the mg-functions * for memory management */ #if defined(malloc) #undef malloc #endif #if defined(calloc) #undef calloc #endif #if defined(realloc) #undef realloc #endif #if defined(free) #undef free #endif /* #if defined(snprintf) */ /* #undef snprintf */ /* #endif */ #if defined(vsnprintf) #undef vsnprintf #endif #define malloc DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc #define calloc DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc #define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc #define free DO_NOT_USE_THIS_FUNCTION__USE_mg_free /* #define snprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_snprintf */ #if defined(_WIN32) /* vsnprintf must not be used in any system, * but this define only works well for Windows. */ #define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf #endif /* mg_init_library counter */ static int mg_init_library_called = 0; #if !defined(NO_SSL) #if defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \ || defined(OPENSSL_API_3_0) static int mg_openssl_initialized = 0; #endif #if !defined(OPENSSL_API_1_0) && !defined(OPENSSL_API_1_1) \ && !defined(OPENSSL_API_3_0) && !defined(USE_MBEDTLS) #error "Please define OPENSSL_API_#_# or USE_MBEDTLS" #endif #if defined(OPENSSL_API_1_0) && defined(OPENSSL_API_1_1) #error "Multiple OPENSSL_API versions defined" #endif #if defined(OPENSSL_API_1_1) && defined(OPENSSL_API_3_0) #error "Multiple OPENSSL_API versions defined" #endif #if defined(OPENSSL_API_1_0) && defined(OPENSSL_API_3_0) #error "Multiple OPENSSL_API versions defined" #endif #if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \ || defined(OPENSSL_API_3_0)) \ && defined(USE_MBEDTLS) #error "Multiple SSL libraries defined" #endif #endif static pthread_key_t sTlsKey; /* Thread local storage index */ static volatile ptrdiff_t thread_idx_max = 0; #if defined(MG_LEGACY_INTERFACE) #define MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE #endif struct mg_workerTLS { int is_master; unsigned long thread_idx; void *user_ptr; #if defined(_WIN32) HANDLE pthread_cond_helper_mutex; struct mg_workerTLS *next_waiting_thread; #endif const char *alpn_proto; #if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE) char txtbuf[4]; #endif }; #if defined(GCC_DIAGNOSTIC) /* Show no warning in case system functions are not used. */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-function" #endif /* defined(GCC_DIAGNOSTIC) */ #if defined(__clang__) /* Show no warning in case system functions are not used. */ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunused-function" #endif /* Get a unique thread ID as unsigned long, independent from the data type * of thread IDs defined by the operating system API. * If two calls to mg_current_thread_id return the same value, they calls * are done from the same thread. If they return different values, they are * done from different threads. (Provided this function is used in the same * process context and threads are not repeatedly created and deleted, but * CivetWeb does not do that). * This function must match the signature required for SSL id callbacks: * CRYPTO_set_id_callback */ FUNCTION_MAY_BE_UNUSED static unsigned long mg_current_thread_id(void) { #if defined(_WIN32) return GetCurrentThreadId(); #else #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunreachable-code" /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)" * or not, so one of the two conditions will be unreachable by construction. * Unfortunately the C standard does not define a way to check this at * compile time, since the #if preprocessor conditions can not use the * sizeof operator as an argument. */ #endif if (sizeof(pthread_t) > sizeof(unsigned long)) { /* This is the problematic case for CRYPTO_set_id_callback: * The OS pthread_t can not be cast to unsigned long. */ struct mg_workerTLS *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey); if (tls == NULL) { /* SSL called from an unknown thread: Create some thread index. */ tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS)); tls->is_master = -2; /* -2 means "3rd party thread" */ tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max); pthread_setspecific(sTlsKey, tls); } return tls->thread_idx; } else { /* pthread_t may be any data type, so a simple cast to unsigned long * can rise a warning/error, depending on the platform. * Here memcpy is used as an anything-to-anything cast. */ unsigned long ret = 0; pthread_t t = pthread_self(); memcpy(&ret, &t, sizeof(pthread_t)); return ret; } #if defined(__clang__) # pragma clang diagnostic pop #endif #endif } FUNCTION_MAY_BE_UNUSED static uint64_t mg_get_current_time_ns(void) { struct timespec tsnow; clock_gettime(CLOCK_REALTIME, &tsnow); return (((uint64_t)tsnow.tv_sec) * 1000000000) + (uint64_t)tsnow.tv_nsec; } #if defined(GCC_DIAGNOSTIC) /* Show no warning in case system functions are not used. */ # pragma GCC diagnostic pop #endif /* defined(GCC_DIAGNOSTIC) */ #if defined(__clang__) /* Show no warning in case system functions are not used. */ # pragma clang diagnostic pop #endif #if defined(NEED_DEBUG_TRACE_FUNC) static void DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...) { va_list args; struct timespec tsnow; /* Get some operating system independent thread id */ unsigned long thread_id = mg_current_thread_id(); clock_gettime(CLOCK_REALTIME, &tsnow); flockfile(DEBUG_TRACE_STREAM); fprintf(DEBUG_TRACE_STREAM, "*** %lu.%09lu %lu %s:%u: ", (unsigned long)tsnow.tv_sec, (unsigned long)tsnow.tv_nsec, thread_id, func, line); va_start(args, fmt); vfprintf(DEBUG_TRACE_STREAM, fmt, args); va_end(args); putc('\n', DEBUG_TRACE_STREAM); fflush(DEBUG_TRACE_STREAM); funlockfile(DEBUG_TRACE_STREAM); } #endif /* NEED_DEBUG_TRACE_FUNC */ #define MD5_STATIC static #include "md5.h" /* Darwin prior to 7.0 and Win32 do not have socklen_t */ #if defined(NO_SOCKLEN_T) typedef int socklen_t; #endif /* NO_SOCKLEN_T */ #define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */ #if !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL (0) #endif /* SSL: mbedTLS vs. no-ssl vs. OpenSSL */ #if defined(USE_MBEDTLS) /* mbedTLS */ #include "mod_mbedtls.h" #elif defined(NO_SSL) /* no SSL */ typedef struct SSL SSL; /* dummy for SSL argument to push/pull */ typedef struct SSL_CTX SSL_CTX; #elif defined(NO_SSL_DL) /* OpenSSL without dynamic loading */ #include #include #include #include #include #include #include #include #include #include #include #if defined(WOLFSSL_VERSION) /* Additional defines for WolfSSL, see * https://github.com/civetweb/civetweb/issues/583 */ #include "wolfssl_extras.h" #endif #if defined(OPENSSL_IS_BORINGSSL) /* From boringssl/src/include/openssl/mem.h: * * OpenSSL has, historically, had a complex set of malloc debugging options. * However, that was written in a time before Valgrind and ASAN. Since we now * have those tools, the OpenSSL allocation functions are simply macros around * the standard memory functions. * * #define OPENSSL_free free */ #define free free // disable for boringssl #define CONF_modules_unload(a) ((void)0) #define ENGINE_cleanup() ((void)0) #endif /* If OpenSSL headers are included, automatically select the API version */ #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) #if !defined(OPENSSL_API_3_0) #define OPENSSL_API_3_0 #endif #define OPENSSL_REMOVE_THREAD_STATE() #else #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) #if !defined(OPENSSL_API_1_1) #define OPENSSL_API_1_1 #endif #define OPENSSL_REMOVE_THREAD_STATE() #else #if !defined(OPENSSL_API_1_0) #define OPENSSL_API_1_0 #endif #define OPENSSL_REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL) #endif #endif #else /* SSL loaded dynamically from DLL / shared object */ /* Add all prototypes here, to be independent from OpenSSL source * installation. */ #include "openssl_dl.h" #endif /* Various SSL bindings */ #if !defined(NO_CACHING) static const char month_names[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; #endif /* !NO_CACHING */ /* Unified socket address. For IPv6 support, add IPv6 address structure in * the union u. */ union usa { struct sockaddr sa; struct sockaddr_in sin; #if defined(USE_IPV6) struct sockaddr_in6 sin6; #endif #if defined(USE_X_DOM_SOCKET) struct sockaddr_un sun; #endif }; #if defined(USE_X_DOM_SOCKET) static unsigned short USA_IN_PORT_UNSAFE(union usa *s) { if (s->sa.sa_family == AF_INET) return s->sin.sin_port; #if defined(USE_IPV6) if (s->sa.sa_family == AF_INET6) return s->sin6.sin6_port; #endif return 0; } #endif #if defined(USE_IPV6) #define USA_IN_PORT_UNSAFE(s) \ (((s)->sa.sa_family == AF_INET6) ? (s)->sin6.sin6_port : (s)->sin.sin_port) #else #define USA_IN_PORT_UNSAFE(s) ((s)->sin.sin_port) #endif /* Describes a string (chunk of memory). */ struct vec { const char *ptr; size_t len; }; struct mg_file_stat { /* File properties filled by mg_stat: */ uint64_t size; time_t last_modified; int is_directory; /* Set to 1 if mg_stat is called for a directory */ int is_gzipped; /* Set to 1 if the content is gzipped, in which * case we need a "Content-Eencoding: gzip" header */ int location; /* 0 = nowhere, 1 = on disk, 2 = in memory */ }; struct mg_file_access { /* File properties filled by mg_fopen: */ FILE *fp; }; struct mg_file { struct mg_file_stat stat; struct mg_file_access access; }; #define STRUCT_FILE_INITIALIZER \ { \ {(uint64_t)0, (time_t)0, 0, 0, 0}, \ { \ (FILE *)NULL \ } \ } /* Describes listening socket, or socket which was accept()-ed by the master * thread and queued for future handling by the worker thread. */ struct socket { SOCKET sock; /* Listening socket */ union usa lsa; /* Local socket address */ union usa rsa; /* Remote socket address */ unsigned char is_ssl; /* Is port SSL-ed */ unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL * port */ unsigned char in_use; /* 0: invalid, 1: valid, 2: free */ }; /* Enum const for all options must be in sync with * static struct mg_option config_options[] * This is tested in the unit test (test/private.c) * "Private Config Options" */ enum { /* Once for each server */ LISTENING_PORTS, NUM_THREADS, RUN_AS_USER, CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the * socket option typedef TCP_NODELAY. */ MAX_REQUEST_SIZE, LINGER_TIMEOUT, CONNECTION_QUEUE_SIZE, LISTEN_BACKLOG_SIZE, #if defined(__linux__) ALLOW_SENDFILE_CALL, #endif #if defined(_WIN32) CASE_SENSITIVE_FILES, #endif THROTTLE, ENABLE_KEEP_ALIVE, REQUEST_TIMEOUT, KEEP_ALIVE_TIMEOUT, #if defined(USE_WEBSOCKET) WEBSOCKET_TIMEOUT, ENABLE_WEBSOCKET_PING_PONG, #endif DECODE_URL, DECODE_QUERY_STRING, #if defined(USE_LUA) LUA_BACKGROUND_SCRIPT, LUA_BACKGROUND_SCRIPT_PARAMS, #endif #if defined(USE_HTTP2) ENABLE_HTTP2, #endif /* Once for each domain */ DOCUMENT_ROOT, ACCESS_LOG_FILE, ERROR_LOG_FILE, CGI_EXTENSIONS, CGI_ENVIRONMENT, CGI_INTERPRETER, CGI_INTERPRETER_ARGS, #if defined(USE_TIMERS) CGI_TIMEOUT, #endif CGI_BUFFERING, CGI2_EXTENSIONS, CGI2_ENVIRONMENT, CGI2_INTERPRETER, CGI2_INTERPRETER_ARGS, #if defined(USE_TIMERS) CGI2_TIMEOUT, #endif CGI2_BUFFERING, #if defined(USE_4_CGI) CGI3_EXTENSIONS, CGI3_ENVIRONMENT, CGI3_INTERPRETER, CGI3_INTERPRETER_ARGS, #if defined(USE_TIMERS) CGI3_TIMEOUT, #endif CGI3_BUFFERING, CGI4_EXTENSIONS, CGI4_ENVIRONMENT, CGI4_INTERPRETER, CGI4_INTERPRETER_ARGS, #if defined(USE_TIMERS) CGI4_TIMEOUT, #endif CGI4_BUFFERING, #endif PUT_DELETE_PASSWORDS_FILE, /* must follow CGI_* */ PROTECT_URI, AUTHENTICATION_DOMAIN, ENABLE_AUTH_DOMAIN_CHECK, SSI_EXTENSIONS, ENABLE_DIRECTORY_LISTING, ENABLE_WEBDAV, GLOBAL_PASSWORDS_FILE, INDEX_FILES, ACCESS_CONTROL_LIST, EXTRA_MIME_TYPES, SSL_CERTIFICATE, SSL_CERTIFICATE_CHAIN, URL_REWRITE_PATTERN, HIDE_FILES, SSL_DO_VERIFY_PEER, SSL_CACHE_TIMEOUT, SSL_CA_PATH, SSL_CA_FILE, SSL_VERIFY_DEPTH, SSL_DEFAULT_VERIFY_PATHS, SSL_CIPHER_LIST, SSL_PROTOCOL_VERSION, SSL_SHORT_TRUST, #if defined(USE_LUA) LUA_PRELOAD_FILE, LUA_SCRIPT_EXTENSIONS, LUA_SERVER_PAGE_EXTENSIONS, #if defined(MG_EXPERIMENTAL_INTERFACES) LUA_DEBUG_PARAMS, #endif #endif #if defined(USE_DUKTAPE) DUKTAPE_SCRIPT_EXTENSIONS, #endif #if defined(USE_WEBSOCKET) WEBSOCKET_ROOT, #endif #if defined(USE_LUA) && defined(USE_WEBSOCKET) LUA_WEBSOCKET_EXTENSIONS, #endif ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_HEADERS, ERROR_PAGES, #if !defined(NO_CACHING) STATIC_FILE_MAX_AGE, STATIC_FILE_CACHE_CONTROL, #endif #if !defined(NO_SSL) STRICT_HTTPS_MAX_AGE, #endif ADDITIONAL_HEADER, ALLOW_INDEX_SCRIPT_SUB_RES, NUM_OPTIONS }; /* Config option name, config types, default value. * Must be in the same order as the enum const above. */ static const struct mg_option config_options[] = { /* Once for each server */ {"listening_ports", MG_CONFIG_TYPE_STRING_LIST, "8080"}, {"num_threads", MG_CONFIG_TYPE_NUMBER, "50"}, {"run_as_user", MG_CONFIG_TYPE_STRING, NULL}, {"tcp_nodelay", MG_CONFIG_TYPE_NUMBER, "0"}, {"max_request_size", MG_CONFIG_TYPE_NUMBER, "16384"}, {"linger_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, {"connection_queue", MG_CONFIG_TYPE_NUMBER, "20"}, {"listen_backlog", MG_CONFIG_TYPE_NUMBER, "200"}, #if defined(__linux__) {"allow_sendfile_call", MG_CONFIG_TYPE_BOOLEAN, "yes"}, #endif #if defined(_WIN32) {"case_sensitive", MG_CONFIG_TYPE_BOOLEAN, "no"}, #endif {"throttle", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"enable_keep_alive", MG_CONFIG_TYPE_BOOLEAN, "no"}, {"request_timeout_ms", MG_CONFIG_TYPE_NUMBER, "30000"}, {"keep_alive_timeout_ms", MG_CONFIG_TYPE_NUMBER, "500"}, #if defined(USE_WEBSOCKET) {"websocket_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, {"enable_websocket_ping_pong", MG_CONFIG_TYPE_BOOLEAN, "no"}, #endif {"decode_url", MG_CONFIG_TYPE_BOOLEAN, "yes"}, {"decode_query_string", MG_CONFIG_TYPE_BOOLEAN, "no"}, #if defined(USE_LUA) {"lua_background_script", MG_CONFIG_TYPE_FILE, NULL}, {"lua_background_script_params", MG_CONFIG_TYPE_STRING_LIST, NULL}, #endif #if defined(USE_HTTP2) {"enable_http2", MG_CONFIG_TYPE_BOOLEAN, "no"}, #endif /* Once for each domain */ {"document_root", MG_CONFIG_TYPE_DIRECTORY, NULL}, {"access_log_file", MG_CONFIG_TYPE_FILE, NULL}, {"error_log_file", MG_CONFIG_TYPE_FILE, NULL}, {"cgi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"}, {"cgi_environment", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"cgi_interpreter", MG_CONFIG_TYPE_FILE, NULL}, {"cgi_interpreter_args", MG_CONFIG_TYPE_STRING, NULL}, #if defined(USE_TIMERS) {"cgi_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, #endif {"cgi_buffering", MG_CONFIG_TYPE_BOOLEAN, "yes"}, {"cgi2_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL}, {"cgi2_environment", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"cgi2_interpreter", MG_CONFIG_TYPE_FILE, NULL}, {"cgi2_interpreter_args", MG_CONFIG_TYPE_STRING, NULL}, #if defined(USE_TIMERS) {"cgi2_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, #endif {"cgi2_buffering", MG_CONFIG_TYPE_BOOLEAN, "yes"}, #if defined(USE_4_CGI) {"cgi3_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL}, {"cgi3_environment", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"cgi3_interpreter", MG_CONFIG_TYPE_FILE, NULL}, {"cgi3_interpreter_args", MG_CONFIG_TYPE_STRING, NULL}, #if defined(USE_TIMERS) {"cgi3_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, #endif {"cgi3_buffering", MG_CONFIG_TYPE_BOOLEAN, "yes"}, {"cgi4_pattern", MG_CONFIG_TYPE_EXT_PATTERN, NULL}, {"cgi4_environment", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"cgi4_interpreter", MG_CONFIG_TYPE_FILE, NULL}, {"cgi4_interpreter_args", MG_CONFIG_TYPE_STRING, NULL}, #if defined(USE_TIMERS) {"cgi4_timeout_ms", MG_CONFIG_TYPE_NUMBER, NULL}, #endif {"cgi4_buffering", MG_CONFIG_TYPE_BOOLEAN, "yes"}, #endif {"put_delete_auth_file", MG_CONFIG_TYPE_FILE, NULL}, {"protect_uri", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"authentication_domain", MG_CONFIG_TYPE_STRING, "mydomain.com"}, {"enable_auth_domain_check", MG_CONFIG_TYPE_BOOLEAN, "yes"}, {"ssi_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"}, {"enable_directory_listing", MG_CONFIG_TYPE_BOOLEAN, "yes"}, {"enable_webdav", MG_CONFIG_TYPE_BOOLEAN, "no"}, {"global_auth_file", MG_CONFIG_TYPE_FILE, NULL}, {"index_files", MG_CONFIG_TYPE_STRING_LIST, #if defined(USE_LUA) "index.xhtml,index.html,index.htm," "index.lp,index.lsp,index.lua,index.cgi," "index.shtml,index.php"}, #else "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"}, #endif {"access_control_list", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"extra_mime_types", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"ssl_certificate", MG_CONFIG_TYPE_FILE, NULL}, {"ssl_certificate_chain", MG_CONFIG_TYPE_FILE, NULL}, {"url_rewrite_patterns", MG_CONFIG_TYPE_STRING_LIST, NULL}, {"hide_files_patterns", MG_CONFIG_TYPE_EXT_PATTERN, NULL}, {"ssl_verify_peer", MG_CONFIG_TYPE_YES_NO_OPTIONAL, "no"}, {"ssl_cache_timeout", MG_CONFIG_TYPE_NUMBER, "-1"}, {"ssl_ca_path", MG_CONFIG_TYPE_DIRECTORY, NULL}, {"ssl_ca_file", MG_CONFIG_TYPE_FILE, NULL}, {"ssl_verify_depth", MG_CONFIG_TYPE_NUMBER, "9"}, {"ssl_default_verify_paths", MG_CONFIG_TYPE_BOOLEAN, "yes"}, {"ssl_cipher_list", MG_CONFIG_TYPE_STRING, NULL}, /* HTTP2 requires ALPN, and anyway TLS1.2 should be considered * as a minimum in 2020 */ {"ssl_protocol_version", MG_CONFIG_TYPE_NUMBER, "4"}, {"ssl_short_trust", MG_CONFIG_TYPE_BOOLEAN, "no"}, #if defined(USE_LUA) {"lua_preload_file", MG_CONFIG_TYPE_FILE, NULL}, {"lua_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"}, {"lua_server_page_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"}, #if defined(MG_EXPERIMENTAL_INTERFACES) {"lua_debug", MG_CONFIG_TYPE_STRING, NULL}, #endif #endif #if defined(USE_DUKTAPE) /* The support for duktape is still in alpha version state. * The name of this config option might change. */ {"duktape_script_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"}, #endif #if defined(USE_WEBSOCKET) {"websocket_root", MG_CONFIG_TYPE_DIRECTORY, NULL}, #endif #if defined(USE_LUA) && defined(USE_WEBSOCKET) {"lua_websocket_pattern", MG_CONFIG_TYPE_EXT_PATTERN, "**.lua$"}, #endif {"access_control_allow_origin", MG_CONFIG_TYPE_STRING, "*"}, {"access_control_allow_methods", MG_CONFIG_TYPE_STRING, "*"}, {"access_control_allow_headers", MG_CONFIG_TYPE_STRING, "*"}, {"error_pages", MG_CONFIG_TYPE_DIRECTORY, NULL}, #if !defined(NO_CACHING) {"static_file_max_age", MG_CONFIG_TYPE_NUMBER, "3600"}, {"static_file_cache_control", MG_CONFIG_TYPE_STRING, NULL}, #endif #if !defined(NO_SSL) {"strict_transport_security_max_age", MG_CONFIG_TYPE_NUMBER, NULL}, #endif {"additional_header", MG_CONFIG_TYPE_STRING_MULTILINE, NULL}, {"allow_index_script_resource", MG_CONFIG_TYPE_BOOLEAN, "no"}, {NULL, MG_CONFIG_TYPE_UNKNOWN, NULL}}; /* Check if the config_options and the corresponding enum have compatible * sizes. */ mg_static_assert((sizeof(config_options) / sizeof(config_options[0])) == (NUM_OPTIONS + 1), "config_options and enum not sync"); enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER }; struct mg_handler_info { /* Name/Pattern of the URI. */ char *uri; size_t uri_len; /* handler type */ int handler_type; /* Handler for http/https or requests. */ mg_request_handler handler; unsigned int refcount; int removing; /* Handler for ws/wss (websocket) requests. */ mg_websocket_connect_handler connect_handler; mg_websocket_ready_handler ready_handler; mg_websocket_data_handler data_handler; mg_websocket_close_handler close_handler; /* accepted subprotocols for ws/wss requests. */ struct mg_websocket_subprotocols *subprotocols; /* Handler for authorization requests */ mg_authorization_handler auth_handler; /* User supplied argument for the handler function. */ void *cbdata; /* next handler in a linked list */ struct mg_handler_info *next; }; enum { CONTEXT_INVALID, CONTEXT_SERVER, CONTEXT_HTTP_CLIENT, CONTEXT_WS_CLIENT }; struct mg_domain_context { SSL_CTX *ssl_ctx; /* SSL context */ char *config[NUM_OPTIONS]; /* Civetweb configuration parameters */ struct mg_handler_info *handlers; /* linked list of uri handlers */ int64_t ssl_cert_last_mtime; /* Server nonce */ uint64_t auth_nonce_mask; /* Mask for all nonce values */ unsigned long nonce_count; /* Used nonces, used for authentication */ #if defined(USE_LUA) && defined(USE_WEBSOCKET) /* linked list of shared lua websockets */ struct mg_shared_lua_websocket_list *shared_lua_websockets; #endif /* Linked list of domains */ struct mg_domain_context *next; }; /* Stop flag can be "volatile" or require a lock. * MSDN uses volatile for "Interlocked" operations, but also explicitly * states a read operation for int is always atomic. */ #if defined(STOP_FLAG_NEEDS_LOCK) typedef ptrdiff_t volatile stop_flag_t; static int STOP_FLAG_IS_ZERO(const stop_flag_t *f) { stop_flag_t sf = mg_atomic_add((stop_flag_t *)f, 0); return (sf == 0); } static int STOP_FLAG_IS_TWO(stop_flag_t *f) { stop_flag_t sf = mg_atomic_add(f, 0); return (sf == 2); } static void STOP_FLAG_ASSIGN(stop_flag_t *f, stop_flag_t v) { stop_flag_t sf; do { sf = mg_atomic_compare_and_swap(f, *f, v); } while (sf != v); } #else /* STOP_FLAG_NEEDS_LOCK */ typedef int volatile stop_flag_t; #define STOP_FLAG_IS_ZERO(f) ((*(f)) == 0) #define STOP_FLAG_IS_TWO(f) ((*(f)) == 2) #define STOP_FLAG_ASSIGN(f, v) ((*(f)) = (v)) #endif /* STOP_FLAG_NEEDS_LOCK */ #if !defined(NUM_WEBDAV_LOCKS) #define NUM_WEBDAV_LOCKS 10 #endif #if !defined(LOCK_DURATION_S) #define LOCK_DURATION_S 60 #endif struct twebdav_lock { uint64_t locktime; char token[33]; char path[UTF8_PATH_MAX * 2]; char user[UTF8_PATH_MAX * 2]; }; struct mg_context { /* Part 1 - Physical context: * This holds threads, ports, timeouts, ... * set for the entire server, independent from the * addressed hostname. */ /* Connection related */ int context_type; /* See CONTEXT_* above */ struct socket *listening_sockets; struct mg_pollfd *listening_socket_fds; unsigned int num_listening_sockets; struct mg_connection *worker_connections; /* The connection struct, pre- * allocated for each worker */ #if defined(USE_SERVER_STATS) volatile ptrdiff_t active_connections; volatile ptrdiff_t max_active_connections; volatile ptrdiff_t total_connections; volatile ptrdiff_t total_requests; volatile int64_t total_data_read; volatile int64_t total_data_written; #endif /* Thread related */ stop_flag_t stop_flag; /* Should we stop event loop */ pthread_mutex_t thread_mutex; /* Protects client_socks or queue */ pthread_t masterthreadid; /* The master thread ID */ unsigned int cfg_worker_threads; /* The number of configured worker threads. */ pthread_t *worker_threadids; /* The worker thread IDs */ unsigned long starter_thread_idx; /* thread index which called mg_start */ /* Connection to thread dispatching */ #if defined(ALTERNATIVE_QUEUE) struct socket *client_socks; void **client_wait_events; #else struct socket *squeue; /* Socket queue (sq) : accepted sockets waiting for a worker thread */ volatile int sq_head; /* Head of the socket queue */ volatile int sq_tail; /* Tail of the socket queue */ pthread_cond_t sq_full; /* Signaled when socket is produced */ pthread_cond_t sq_empty; /* Signaled when socket is consumed */ volatile int sq_blocked; /* Status information: sq is full */ int sq_size; /* No of elements in socket queue */ #if defined(USE_SERVER_STATS) int sq_max_fill; #endif /* USE_SERVER_STATS */ #endif /* ALTERNATIVE_QUEUE */ /* Memory related */ unsigned int max_request_size; /* The max request size */ #if defined(USE_SERVER_STATS) struct mg_memory_stat ctx_memory; #endif /* WebDAV lock structures */ struct twebdav_lock webdav_lock[NUM_WEBDAV_LOCKS]; /* Operating system related */ char *systemName; /* What operating system is running */ time_t start_time; /* Server start time, used for authentication * and for diagnstics. */ #if defined(USE_TIMERS) struct ttimers *timers; #endif /* Lua specific: Background operations and shared websockets */ #if defined(USE_LUA) void *lua_background_state; /* lua_State (here as void *) */ pthread_mutex_t lua_bg_mutex; /* Protect background state */ int lua_bg_log_available; /* Use Lua background state for access log */ #endif /* Server nonce */ pthread_mutex_t nonce_mutex; /* Protects ssl_ctx, handlers, * ssl_cert_last_mtime, nonce_count, and * next (linked list) */ /* Server callbacks */ struct mg_callbacks callbacks; /* User-defined callback function */ void *user_data; /* User-defined data */ /* Part 2 - Logical domain: * This holds hostname, TLS certificate, document root, ... * set for a domain hosted at the server. * There may be multiple domains hosted at one physical server. * The default domain "dd" is the first element of a list of * domains. */ struct mg_domain_context dd; /* default domain */ }; #if defined(USE_SERVER_STATS) static struct mg_memory_stat mg_common_memory = {0, 0, 0}; static struct mg_memory_stat * get_memory_stat(struct mg_context *ctx) { if (ctx) { return &(ctx->ctx_memory); } return &mg_common_memory; } #endif enum { CONNECTION_TYPE_INVALID = 0, CONNECTION_TYPE_REQUEST = 1, CONNECTION_TYPE_RESPONSE = 2 }; enum { PROTOCOL_TYPE_HTTP1 = 0, PROTOCOL_TYPE_WEBSOCKET = 1, PROTOCOL_TYPE_HTTP2 = 2 }; #if defined(USE_HTTP2) #if !defined(HTTP2_DYN_TABLE_SIZE) #define HTTP2_DYN_TABLE_SIZE (256) #endif struct mg_http2_connection { uint32_t stream_id; uint32_t dyn_table_size; struct mg_header dyn_table[HTTP2_DYN_TABLE_SIZE]; }; #endif struct mg_connection { int connection_type; /* see CONNECTION_TYPE_* above */ int protocol_type; /* see PROTOCOL_TYPE_*: 0=http/1.x, 1=ws, 2=http/2 */ int request_state; /* 0: nothing sent, 1: header partially sent, 2: header fully sent */ #if defined(USE_HTTP2) struct mg_http2_connection http2; #endif struct mg_request_info request_info; struct mg_response_info response_info; struct mg_context *phys_ctx; struct mg_domain_context *dom_ctx; #if defined(USE_SERVER_STATS) int conn_state; /* 0 = undef, numerical value may change in different * versions. For the current definition, see * mg_get_connection_info_impl */ #endif SSL *ssl; /* SSL descriptor */ struct socket client; /* Connected client */ time_t conn_birth_time; /* Time (wall clock) when connection was * established */ #if defined(USE_SERVER_STATS) time_t conn_close_time; /* Time (wall clock) when connection was * closed (or 0 if still open) */ double processing_time; /* Processing time for one request. */ #endif struct timespec req_time; /* Time (since system start) when the request * was received */ int64_t num_bytes_sent; /* Total bytes sent to client */ int64_t content_len; /* How many bytes of content can be read * !is_chunked: Content-Length header value * or -1 (until connection closed, * not allowed for a request) * is_chunked: >= 0, appended gradually */ int64_t consumed_content; /* How many bytes of content have been read */ int is_chunked; /* Transfer-Encoding is chunked: * 0 = not chunked, * 1 = chunked, not yet, or some data read, * 2 = chunked, has error, * 3 = chunked, all data read except trailer, * 4 = chunked, all data read */ char *buf; /* Buffer for received data */ char *path_info; /* PATH_INFO part of the URL */ int must_close; /* 1 if connection must be closed */ int accept_gzip; /* 1 if gzip encoding is accepted */ int in_error_handler; /* 1 if in handler for user defined error * pages */ #if defined(USE_WEBSOCKET) int in_websocket_handling; /* 1 if in read_websocket */ #endif #if defined(USE_ZLIB) && defined(USE_WEBSOCKET) \ && defined(MG_EXPERIMENTAL_INTERFACES) /* Parameters for websocket data compression according to rfc7692 */ int websocket_deflate_server_max_windows_bits; int websocket_deflate_client_max_windows_bits; int websocket_deflate_server_no_context_takeover; int websocket_deflate_client_no_context_takeover; int websocket_deflate_initialized; int websocket_deflate_flush; z_stream websocket_deflate_state; z_stream websocket_inflate_state; #endif int handled_requests; /* Number of requests handled by this connection */ int buf_size; /* Buffer size */ int request_len; /* Size of the request + headers in a buffer */ int data_len; /* Total size of data in a buffer */ int status_code; /* HTTP reply status code, e.g. 200 */ int throttle; /* Throttling, bytes/sec. <= 0 means no * throttle */ time_t last_throttle_time; /* Last time throttled data was sent */ int last_throttle_bytes; /* Bytes sent this second */ pthread_mutex_t mutex; /* Used by mg_(un)lock_connection to ensure * atomic transmissions for websockets */ #if defined(USE_LUA) && defined(USE_WEBSOCKET) void *lua_websocket_state; /* Lua_State for a websocket connection */ #endif void *tls_user_ptr; /* User defined pointer in thread local storage, * for quick access */ }; /* Directory entry */ struct de { char *file_name; struct mg_file_stat file; }; #define mg_cry_internal(conn, fmt, ...) \ mg_cry_internal_wrap(conn, NULL, __func__, __LINE__, fmt, __VA_ARGS__) #define mg_cry_ctx_internal(ctx, fmt, ...) \ mg_cry_internal_wrap(NULL, ctx, __func__, __LINE__, fmt, __VA_ARGS__) static void mg_cry_internal_wrap(const struct mg_connection *conn, struct mg_context *ctx, const char *func, unsigned line, const char *fmt, ...) PRINTF_ARGS(5, 6); #if !defined(NO_THREAD_NAME) #if defined(_WIN32) && defined(_MSC_VER) /* Set the thread name for debugging purposes in Visual Studio * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx */ # pragma pack(push, 8) typedef struct tagTHREADNAME_INFO { DWORD dwType; /* Must be 0x1000. */ LPCSTR szName; /* Pointer to name (in user addr space). */ DWORD dwThreadID; /* Thread ID (-1=caller thread). */ DWORD dwFlags; /* Reserved for future use, must be zero. */ } THREADNAME_INFO; # pragma pack(pop) #elif defined(__linux__) #include #include #if defined(ALTERNATIVE_QUEUE) #include #endif /* ALTERNATIVE_QUEUE */ #if defined(ALTERNATIVE_QUEUE) static void * event_create(void) { int evhdl = eventfd(0, EFD_CLOEXEC); int *ret; if (evhdl == -1) { /* Linux uses -1 on error, Windows NULL. */ /* However, Linux does not return 0 on success either. */ return 0; } ret = (int *)mg_malloc(sizeof(int)); if (ret) { *ret = evhdl; } else { (void)close(evhdl); } return (void *)ret; } static int event_wait(void *eventhdl) { uint64_t u; int evhdl, s; if (!eventhdl) { /* error */ return 0; } evhdl = *(int *)eventhdl; s = (int)read(evhdl, &u, sizeof(u)); if (s != sizeof(u)) { /* error */ return 0; } (void)u; /* the value is not required */ return 1; } static int event_signal(void *eventhdl) { uint64_t u = 1; int evhdl, s; if (!eventhdl) { /* error */ return 0; } evhdl = *(int *)eventhdl; s = (int)write(evhdl, &u, sizeof(u)); if (s != sizeof(u)) { /* error */ return 0; } return 1; } static void event_destroy(void *eventhdl) { int evhdl; if (!eventhdl) { /* error */ return; } evhdl = *(int *)eventhdl; close(evhdl); mg_free(eventhdl); } #endif #endif #if !defined(__linux__) && !defined(_WIN32) && defined(ALTERNATIVE_QUEUE) struct posix_event { pthread_mutex_t mutex; pthread_cond_t cond; int signaled; }; static void * event_create(void) { struct posix_event *ret = mg_malloc(sizeof(struct posix_event)); if (ret == 0) { /* out of memory */ return 0; } if (0 != pthread_mutex_init(&(ret->mutex), NULL)) { /* pthread mutex not available */ mg_free(ret); return 0; } if (0 != pthread_cond_init(&(ret->cond), NULL)) { /* pthread cond not available */ pthread_mutex_destroy(&(ret->mutex)); mg_free(ret); return 0; } ret->signaled = 0; return (void *)ret; } static int event_wait(void *eventhdl) { struct posix_event *ev = (struct posix_event *)eventhdl; pthread_mutex_lock(&(ev->mutex)); while (!ev->signaled) { pthread_cond_wait(&(ev->cond), &(ev->mutex)); } ev->signaled = 0; pthread_mutex_unlock(&(ev->mutex)); return 1; } static int event_signal(void *eventhdl) { struct posix_event *ev = (struct posix_event *)eventhdl; pthread_mutex_lock(&(ev->mutex)); pthread_cond_signal(&(ev->cond)); ev->signaled = 1; pthread_mutex_unlock(&(ev->mutex)); return 1; } static void event_destroy(void *eventhdl) { struct posix_event *ev = (struct posix_event *)eventhdl; pthread_cond_destroy(&(ev->cond)); pthread_mutex_destroy(&(ev->mutex)); mg_free(ev); } #endif static void mg_set_thread_name(const char *name) { char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */ mg_snprintf( NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name); #if defined(_WIN32) #if defined(_MSC_VER) /* Windows and Visual Studio Compiler */ __try { THREADNAME_INFO info; info.dwType = 0x1000; info.szName = threadName; info.dwThreadID = ~0U; info.dwFlags = 0; RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)&info); } __except (EXCEPTION_EXECUTE_HANDLER) { } #elif defined(__MINGW32__) /* No option known to set thread name for MinGW known */ #endif #elif defined(_GNU_SOURCE) && defined(__GLIBC__) \ && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12))) /* pthread_setname_np first appeared in glibc in version 2.12 */ #if defined(__MACH__) && defined(__APPLE__) /* OS X only current thread name can be changed */ (void)pthread_setname_np(threadName); #else (void)pthread_setname_np(pthread_self(), threadName); #endif #elif defined(__linux__) /* On Linux we can use the prctl function. * When building for Linux Standard Base (LSB) use * NO_THREAD_NAME. However, thread names are a big * help for debugging, so the stadard is to set them. */ (void)prctl(PR_SET_NAME, threadName, 0, 0, 0); #endif } #else /* !defined(NO_THREAD_NAME) */ static void mg_set_thread_name(const char *threadName) { } #endif CIVETWEB_API const struct mg_option * mg_get_valid_options(void) { return config_options; } /* Do not open file (unused) */ #define MG_FOPEN_MODE_NONE (0) /* Open file for read only access */ #define MG_FOPEN_MODE_READ (1) /* Open file for writing, create and overwrite */ #define MG_FOPEN_MODE_WRITE (2) /* Open file for writing, create and append */ #define MG_FOPEN_MODE_APPEND (4) static int is_file_opened(const struct mg_file_access *fileacc) { if (!fileacc) { return 0; } return (fileacc->fp != NULL); } #if !defined(NO_FILESYSTEMS) static int mg_stat(const struct mg_connection *conn, const char *path, struct mg_file_stat *filep); /* Reject files with special characters (for Windows) */ static int mg_path_suspicious(const struct mg_connection *conn, const char *path) { const uint8_t *c = (const uint8_t *)path; (void)conn; /* not used */ if ((c == NULL) || (c[0] == 0)) { /* Null pointer or empty path --> suspicious */ return 1; } #if defined(_WIN32) while (*c) { if (*c < 32) { /* Control character */ return 1; } if ((*c == '>') || (*c == '<') || (*c == '|')) { /* stdin/stdout redirection character */ return 1; } if ((*c == '*') || (*c == '?')) { /* Wildcard character */ return 1; } if (*c == '"') { /* Windows quotation */ return 1; } c++; } #endif /* Nothing suspicious found */ return 0; } /* mg_fopen will open a file either in memory or on the disk. * The input parameter path is a string in UTF-8 encoding. * The input parameter mode is MG_FOPEN_MODE_* * On success, fp will be set in the output struct mg_file. * All status members will also be set. * The function returns 1 on success, 0 on error. */ static int mg_fopen(const struct mg_connection *conn, const char *path, int mode, struct mg_file *filep) { int found; if (!filep) { return 0; } filep->access.fp = NULL; if (mg_path_suspicious(conn, path)) { return 0; } /* filep is initialized in mg_stat: all fields with memset to, * some fields like size and modification date with values */ found = mg_stat(conn, path, &(filep->stat)); if ((mode == MG_FOPEN_MODE_READ) && (!found)) { /* file does not exist and will not be created */ return 0; } #if defined(_WIN32) { wchar_t wbuf[UTF16_PATH_MAX]; path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); switch (mode) { case MG_FOPEN_MODE_READ: filep->access.fp = _wfopen(wbuf, L"rb"); break; case MG_FOPEN_MODE_WRITE: filep->access.fp = _wfopen(wbuf, L"wb"); break; case MG_FOPEN_MODE_APPEND: filep->access.fp = _wfopen(wbuf, L"ab"); break; } } #else /* Linux et al already use unicode. No need to convert. */ switch (mode) { case MG_FOPEN_MODE_READ: filep->access.fp = fopen(path, "r"); break; case MG_FOPEN_MODE_WRITE: filep->access.fp = fopen(path, "w"); break; case MG_FOPEN_MODE_APPEND: filep->access.fp = fopen(path, "a"); break; } #endif if (!found) { /* File did not exist before fopen was called. * Maybe it has been created now. Get stat info * like creation time now. */ found = mg_stat(conn, path, &(filep->stat)); (void)found; } /* return OK if file is opened */ return (filep->access.fp != NULL); } /* return 0 on success, just like fclose */ static int mg_fclose(struct mg_file_access *fileacc) { int ret = -1; if (fileacc != NULL) { if (fileacc->fp != NULL) { ret = fclose(fileacc->fp); } /* reset all members of fileacc */ memset(fileacc, 0, sizeof(*fileacc)); } return ret; } #endif /* NO_FILESYSTEMS */ static void mg_strlcpy(char *dst, const char *src, size_t n) { for (; *src != '\0' && n > 1; n--) { *dst++ = *src++; } *dst = '\0'; } static int lowercase(const char *s) { return tolower((unsigned char)*s); } CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len) { int diff = 0; if (len > 0) { do { diff = lowercase(s1++) - lowercase(s2++); } while (diff == 0 && s1[-1] != '\0' && --len > 0); } return diff; } CIVETWEB_API int mg_strcasecmp(const char *s1, const char *s2) { int diff; do { diff = lowercase(s1++) - lowercase(s2++); } while (diff == 0 && s1[-1] != '\0'); return diff; } static char * mg_strndup_ctx(const char *ptr, size_t len, struct mg_context *ctx) { char *p; (void)ctx; /* Avoid Visual Studio warning if USE_SERVER_STATS is not * defined */ if ((p = (char *)mg_malloc_ctx(len + 1, ctx)) != NULL) { mg_strlcpy(p, ptr, len + 1); } return p; } static char * mg_strdup_ctx(const char *str, struct mg_context *ctx) { return mg_strndup_ctx(str, strlen(str), ctx); } static char * mg_strdup(const char *str) { return mg_strndup_ctx(str, strlen(str), NULL); } static const char * mg_strcasestr(const char *big_str, const char *small_str) { size_t i, big_len = strlen(big_str), small_len = strlen(small_str); if (big_len >= small_len) { for (i = 0; i <= (big_len - small_len); i++) { if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) { return big_str + i; } } } return NULL; } /* Return null terminated string of given maximum length. * Report errors if length is exceeded. */ static void mg_vsnprintf(const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, const char *fmt, va_list ap) { int n, ok; if (buflen == 0) { if (truncated) { *truncated = 1; } return; } #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wformat-nonliteral" /* Using fmt as a non-literal is intended here, since it is mostly called * indirectly by mg_snprintf */ #endif n = (int)vsnprintf_impl(buf, buflen, fmt, ap); ok = (n >= 0) && ((size_t)n < buflen); #if defined(__clang__) # pragma clang diagnostic pop #endif if (ok) { if (truncated) { *truncated = 0; } } else { if (truncated) { *truncated = 1; } mg_cry_internal(conn, "truncating vsnprintf buffer: [%.*s]", (int)((buflen > 200) ? 200 : (buflen - 1)), buf); n = (int)buflen - 1; } buf[n] = '\0'; } static void mg_snprintf(const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, const char *fmt, ...) { va_list ap; va_start(ap, fmt); mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap); va_end(ap); } static int get_option_index(const char *name) { int i; for (i = 0; config_options[i].name != NULL; i++) { if (strcmp(config_options[i].name, name) == 0) { return i; } } return -1; } CIVETWEB_API const char * mg_get_option(const struct mg_context *ctx, const char *name) { int i; if ((i = get_option_index(name)) == -1) { return NULL; } else if (!ctx || ctx->dd.config[i] == NULL) { return ""; } else { return ctx->dd.config[i]; } } #define mg_get_option DO_NOT_USE_THIS_FUNCTION_INTERNALLY__access_directly CIVETWEB_API struct mg_context * mg_get_context(const struct mg_connection *conn) { return (conn == NULL) ? (struct mg_context *)NULL : (conn->phys_ctx); } CIVETWEB_API void * mg_get_user_data(const struct mg_context *ctx) { return (ctx == NULL) ? NULL : ctx->user_data; } CIVETWEB_API void * mg_get_user_context_data(const struct mg_connection *conn) { return mg_get_user_data(mg_get_context(conn)); } CIVETWEB_API void * mg_get_thread_pointer(const struct mg_connection *conn) { /* both methods should return the same pointer */ if (conn) { /* quick access, in case conn is known */ return conn->tls_user_ptr; } else { /* otherwise get pointer from thread local storage (TLS) */ struct mg_workerTLS *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey); return tls->user_ptr; } } CIVETWEB_API void mg_set_user_connection_data(const struct mg_connection *const_conn, void *data) { if (const_conn != NULL) { /* Const cast, since "const struct mg_connection *" does not mean * the connection object is not modified. Here "const" is used, * to indicate mg_read/mg_write/mg_send/.. must not be called. */ struct mg_connection *conn = (struct mg_connection *)const_conn; conn->request_info.conn_data = data; } } CIVETWEB_API void * mg_get_user_connection_data(const struct mg_connection *conn) { if (conn != NULL) { return conn->request_info.conn_data; } return NULL; } CIVETWEB_API int mg_get_server_ports(const struct mg_context *ctx, int size, struct mg_server_port *ports) { int i, cnt = 0; if (size <= 0) { return -1; } memset(ports, 0, sizeof(*ports) * (size_t)size); if (!ctx) { return -1; } if (!ctx->listening_sockets) { return -1; } for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) { ports[cnt].port = ntohs(USA_IN_PORT_UNSAFE(&(ctx->listening_sockets[i].lsa))); ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl; ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir; if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) { /* IPv4 */ ports[cnt].protocol = 1; cnt++; } else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) { /* IPv6 */ ports[cnt].protocol = 3; cnt++; } } return cnt; } #if defined(USE_X_DOM_SOCKET) && !defined(UNIX_DOMAIN_SOCKET_SERVER_NAME) #define UNIX_DOMAIN_SOCKET_SERVER_NAME "*" #endif static void sockaddr_to_string(char *buf, size_t len, const union usa *usa) { buf[0] = '\0'; if (!usa) { return; } if (usa->sa.sa_family == AF_INET) { getnameinfo(&usa->sa, sizeof(usa->sin), buf, (unsigned)len, NULL, 0, NI_NUMERICHOST); } #if defined(USE_IPV6) else if (usa->sa.sa_family == AF_INET6) { getnameinfo(&usa->sa, sizeof(usa->sin6), buf, (unsigned)len, NULL, 0, NI_NUMERICHOST); } #endif #if defined(USE_X_DOM_SOCKET) else if (usa->sa.sa_family == AF_UNIX) { /* TODO: Define a remote address for unix domain sockets. * This code will always return "localhost", identical to http+tcp: getnameinfo(&usa->sa, sizeof(usa->sun), buf, (unsigned)len, NULL, 0, NI_NUMERICHOST); */ mg_strlcpy(buf, UNIX_DOMAIN_SOCKET_SERVER_NAME, len); } #endif } /* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be * included in all responses other than 100, 101, 5xx. */ static void gmt_time_string(char *buf, size_t buf_len, time_t *t) { #if !defined(REENTRANT_TIME) struct tm *tm; tm = ((t != NULL) ? gmtime(t) : NULL); if (tm != NULL) { #else struct tm _tm; struct tm *tm = &_tm; if (t != NULL) { gmtime_r(t, tm); #endif strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm); } else { mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len); } } /* difftime for struct timespec. Return value is in seconds. */ static double mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before) { return (double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9 + (double)(ts_now->tv_sec - ts_before->tv_sec); } #if defined(MG_EXTERNAL_FUNCTION_mg_cry_internal_impl) static void mg_cry_internal_impl(const struct mg_connection *conn, const char *func, unsigned line, const char *fmt, va_list ap); #include "external_mg_cry_internal_impl.h" #elif !defined(NO_FILESYSTEMS) /* Print error message to the opened error log stream. */ static void mg_cry_internal_impl(const struct mg_connection *conn, const char *func, unsigned line, const char *fmt, va_list ap) { char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN]; struct mg_file fi; time_t timestamp; /* Unused, in the RELEASE build */ (void)func; (void)line; #if defined(GCC_DIAGNOSTIC) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif IGNORE_UNUSED_RESULT(vsnprintf_impl(buf, sizeof(buf), fmt, ap)); #if defined(GCC_DIAGNOSTIC) # pragma GCC diagnostic pop #endif buf[sizeof(buf) - 1] = 0; DEBUG_TRACE("mg_cry called from %s:%u: %s", func, line, buf); if (!conn) { /* puts(buf) */ return; } /* Do not lock when getting the callback value, here and below. * I suppose this is fine, since function cannot disappear in the * same way string option can. */ if ((conn->phys_ctx->callbacks.log_message == NULL) || (conn->phys_ctx->callbacks.log_message(conn, buf) == 0)) { if (conn->dom_ctx->config[ERROR_LOG_FILE] != NULL) { if (mg_fopen(conn, conn->dom_ctx->config[ERROR_LOG_FILE], MG_FOPEN_MODE_APPEND, &fi) == 0) { fi.access.fp = NULL; } } else { fi.access.fp = NULL; } if (fi.access.fp != NULL) { flockfile(fi.access.fp); timestamp = time(NULL); sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); fprintf(fi.access.fp, "[%010lu] [error] [client %s] ", (unsigned long)timestamp, src_addr); if (conn->request_info.request_method != NULL) { fprintf(fi.access.fp, "%s %s: ", conn->request_info.request_method, conn->request_info.request_uri ? conn->request_info.request_uri : ""); } fprintf(fi.access.fp, "%s", buf); fputc('\n', fi.access.fp); fflush(fi.access.fp); funlockfile(fi.access.fp); (void)mg_fclose(&fi.access); /* Ignore errors. We can't call * mg_cry here anyway ;-) */ } } } #else #error Must either enable filesystems or provide a custom mg_cry_internal_impl implementation #endif /* Externally provided function */ /* Construct fake connection structure. Used for logging, if connection * is not applicable at the moment of logging. */ static struct mg_connection * fake_connection(struct mg_connection *fc, struct mg_context *ctx) { static const struct mg_connection conn_zero = {0}; *fc = conn_zero; fc->phys_ctx = ctx; fc->dom_ctx = &(ctx->dd); return fc; } static void mg_cry_internal_wrap(const struct mg_connection *conn, struct mg_context *ctx, const char *func, unsigned line, const char *fmt, ...) { va_list ap; va_start(ap, fmt); if (!conn && ctx) { struct mg_connection fc; mg_cry_internal_impl(fake_connection(&fc, ctx), func, line, fmt, ap); } else { mg_cry_internal_impl(conn, func, line, fmt, ap); } va_end(ap); } CIVETWEB_API void mg_cry(const struct mg_connection *conn, const char *fmt, ...) { va_list ap; va_start(ap, fmt); mg_cry_internal_impl(conn, "user", 0, fmt, ap); va_end(ap); } #define mg_cry DO_NOT_USE_THIS_FUNCTION__USE_mg_cry_internal CIVETWEB_API const char * mg_version(void) { return CIVETWEB_VERSION; } CIVETWEB_API const struct mg_request_info * mg_get_request_info(const struct mg_connection *conn) { if (!conn) { return NULL; } #if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE) if (conn->connection_type == CONNECTION_TYPE_RESPONSE) { char txt[16]; struct mg_workerTLS *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey); snprintf(txt, "%03i", sizeof(txt), conn->response_info.status_code); if (strlen(txt) == 3) { memcpy(tls->txtbuf, txt, 4); } else { strcpy(tls->txtbuf, "ERR"); } ((struct mg_connection *)conn)->request_info.local_uri = tls->txtbuf; /* use thread safe buffer */ ((struct mg_connection *)conn)->request_info.local_uri_raw = tls->txtbuf; /* use the same thread safe buffer */ ((struct mg_connection *)conn)->request_info.request_uri = tls->txtbuf; /* use the same thread safe buffer */ ((struct mg_connection *)conn)->request_info.num_headers = conn->response_info.num_headers; memcpy(((struct mg_connection *)conn)->request_info.http_headers, conn->response_info.http_headers, sizeof(conn->response_info.http_headers)); } else #endif if (conn->connection_type != CONNECTION_TYPE_REQUEST) { return NULL; } return &conn->request_info; } CIVETWEB_API const struct mg_response_info * mg_get_response_info(const struct mg_connection *conn) { if (!conn) { return NULL; } if (conn->connection_type != CONNECTION_TYPE_RESPONSE) { return NULL; } return &conn->response_info; } static const char * get_proto_name(const struct mg_connection *conn) { #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunreachable-code" /* Depending on USE_WEBSOCKET and NO_SSL, some oft the protocols might be * not supported. Clang raises an "unreachable code" warning for parts of ?: * unreachable, but splitting into four different #ifdef clauses here is * more complicated. */ #endif const struct mg_request_info *ri = &conn->request_info; const char *proto = ((conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET) ? (ri->is_ssl ? "wss" : "ws") : (ri->is_ssl ? "https" : "http")); return proto; #if defined(__clang__) # pragma clang diagnostic pop #endif } static int mg_construct_local_link(const struct mg_connection *conn, char *buf, size_t buflen, const char *define_proto, int define_port, const char *define_uri) { if ((buflen < 1) || (buf == 0) || (conn == 0)) { return -1; } else { int i, j; int truncated = 0; const struct mg_request_info *ri = &conn->request_info; const char *proto = (define_proto != NULL) ? define_proto : get_proto_name(conn); const char *uri = (define_uri != NULL) ? define_uri : ((ri->request_uri != NULL) ? ri->request_uri : ri->local_uri); int port = (define_port > 0) ? define_port : ri->server_port; int default_port = 80; char *uri_encoded; size_t uri_encoded_len; if (uri == NULL) { return -1; } uri_encoded_len = strlen(uri) * 3 + 1; uri_encoded = (char *)mg_malloc_ctx(uri_encoded_len, conn->phys_ctx); if (uri_encoded == NULL) { return -1; } mg_url_encode(uri, uri_encoded, uri_encoded_len); /* Directory separator should be preserved. */ for (i = j = 0; uri_encoded[i]; j++) { if (!strncmp(uri_encoded + i, "%2f", 3)) { uri_encoded[j] = '/'; i += 3; } else { uri_encoded[j] = uri_encoded[i++]; } } uri_encoded[j] = '\0'; #if defined(USE_X_DOM_SOCKET) if (conn->client.lsa.sa.sa_family == AF_UNIX) { /* TODO: Define and document a link for UNIX domain sockets. */ /* There seems to be no official standard for this. * Common uses seem to be "httpunix://", "http.unix://" or * "http+unix://" as a protocol definition string, followed by * "localhost" or "127.0.0.1" or "/tmp/unix/path" or * "%2Ftmp%2Funix%2Fpath" (url % encoded) or * "localhost:%2Ftmp%2Funix%2Fpath" (domain socket path as port) or * "" (completely skipping the server name part). In any case, the * last part is the server local path. */ const char *server_name = UNIX_DOMAIN_SOCKET_SERVER_NAME; mg_snprintf(conn, &truncated, buf, buflen, "%s.unix://%s%s", proto, server_name, ri->local_uri); default_port = 0; mg_free(uri_encoded); return 0; } #endif if (define_proto) { /* If we got a protocol name, use the default port accordingly. */ if ((0 == strcmp(define_proto, "https")) || (0 == strcmp(define_proto, "wss"))) { default_port = 443; } } else if (ri->is_ssl) { /* If we did not get a protocol name, use TLS as default if it is * already used. */ default_port = 443; } { #if defined(USE_IPV6) int is_ipv6 = (conn->client.lsa.sa.sa_family == AF_INET6); #endif int auth_domain_check_enabled = conn->dom_ctx->config[ENABLE_AUTH_DOMAIN_CHECK] && (!mg_strcasecmp( conn->dom_ctx->config[ENABLE_AUTH_DOMAIN_CHECK], "yes")); const char *server_domain = conn->dom_ctx->config[AUTHENTICATION_DOMAIN]; char portstr[16]; char server_ip[48]; if (port != default_port) { snprintf(portstr, sizeof(portstr), ":%u", (unsigned)port); } else { portstr[0] = 0; } if (!auth_domain_check_enabled || !server_domain) { sockaddr_to_string(server_ip, sizeof(server_ip), &conn->client.lsa); server_domain = server_ip; } mg_snprintf(conn, &truncated, buf, buflen, #if defined(USE_IPV6) "%s://%s%s%s%s%s", proto, (is_ipv6 && (server_domain == server_ip)) ? "[" : "", server_domain, (is_ipv6 && (server_domain == server_ip)) ? "]" : "", #else "%s://%s%s%s", proto, server_domain, #endif portstr, uri_encoded); mg_free(uri_encoded); if (truncated) { return -1; } return 0; } } } CIVETWEB_API int mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen) { return mg_construct_local_link(conn, buf, buflen, NULL, -1, NULL); } /* Skip the characters until one of the delimiters characters found. * 0-terminate resulting word. Skip the delimiter and following whitespaces. * Advance pointer to buffer to the next word. Return found 0-terminated * word. * Delimiters can be quoted with quotechar. */ static char * skip_quoted(char **buf, const char *delimiters, const char *whitespace, char quotechar) { char *p, *begin_word, *end_word, *end_whitespace; begin_word = *buf; end_word = begin_word + strcspn(begin_word, delimiters); /* Check for quotechar */ if (end_word > begin_word) { p = end_word - 1; while (*p == quotechar) { /* While the delimiter is quoted, look for the next delimiter. */ /* This happens, e.g., in calls from parse_auth_header, * if the user name contains a " character. */ /* If there is anything beyond end_word, copy it. */ if (*end_word != '\0') { size_t end_off = strcspn(end_word + 1, delimiters); memmove(p, end_word, end_off + 1); p += end_off; /* p must correspond to end_word - 1 */ end_word += end_off + 1; } else { *p = '\0'; break; } } for (p++; p < end_word; p++) { *p = '\0'; } } if (*end_word == '\0') { *buf = end_word; } else { #if defined(GCC_DIAGNOSTIC) /* Disable spurious conversion warning for GCC */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wsign-conversion" #endif /* defined(GCC_DIAGNOSTIC) */ end_whitespace = end_word + strspn(&end_word[1], whitespace) + 1; #if defined(GCC_DIAGNOSTIC) # pragma GCC diagnostic pop #endif /* defined(GCC_DIAGNOSTIC) */ for (p = end_word; p < end_whitespace; p++) { *p = '\0'; } *buf = end_whitespace; } return begin_word; } /* Return HTTP header value, or NULL if not found. */ static const char * get_header(const struct mg_header *hdr, int num_hdr, const char *name) { int i; for (i = 0; i < num_hdr; i++) { if (!mg_strcasecmp(name, hdr[i].name)) { return hdr[i].value; } } return NULL; } /* Retrieve requested HTTP header multiple values, and return the number of * found occurrences */ static int get_req_headers(const struct mg_request_info *ri, const char *name, const char **output, int output_max_size) { int i; int cnt = 0; if (ri) { for (i = 0; i < ri->num_headers && cnt < output_max_size; i++) { if (!mg_strcasecmp(name, ri->http_headers[i].name)) { output[cnt++] = ri->http_headers[i].value; } } } return cnt; } CIVETWEB_API const char * mg_get_header(const struct mg_connection *conn, const char *name) { if (!conn) { return NULL; } if (conn->connection_type == CONNECTION_TYPE_REQUEST) { return get_header(conn->request_info.http_headers, conn->request_info.num_headers, name); } if (conn->connection_type == CONNECTION_TYPE_RESPONSE) { return get_header(conn->response_info.http_headers, conn->response_info.num_headers, name); } return NULL; } static const char * get_http_version(const struct mg_connection *conn) { if (!conn) { return NULL; } if (conn->connection_type == CONNECTION_TYPE_REQUEST) { return conn->request_info.http_version; } if (conn->connection_type == CONNECTION_TYPE_RESPONSE) { return conn->response_info.http_version; } return NULL; } /* A helper function for traversing a comma separated list of values. * It returns a list pointer shifted to the next value, or NULL if the end * of the list found. * Value is stored in val vector. If value has form "x=y", then eq_val * vector is initialized to point to the "y" part, and val vector length * is adjusted to point only to "x". */ static const char * next_option(const char *list, struct vec *val, struct vec *eq_val) { int end; reparse: if (val == NULL || list == NULL || *list == '\0') { /* End of the list */ return NULL; } /* Skip over leading LWS */ while (*list == ' ' || *list == '\t') list++; val->ptr = list; if ((list = strchr(val->ptr, ',')) != NULL) { /* Comma found. Store length and shift the list ptr */ val->len = ((size_t)(list - val->ptr)); list++; } else { /* This value is the last one */ list = val->ptr + strlen(val->ptr); val->len = ((size_t)(list - val->ptr)); } /* Adjust length for trailing LWS */ end = (int)val->len - 1; while (end >= 0 && ((val->ptr[end] == ' ') || (val->ptr[end] == '\t'))) end--; val->len = (size_t)(end) + (size_t)(1); if (val->len == 0) { /* Ignore any empty entries. */ goto reparse; } if (eq_val != NULL) { /* Value has form "x=y", adjust pointers and lengths * so that val points to "x", and eq_val points to "y". */ eq_val->len = 0; eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len); if (eq_val->ptr != NULL) { eq_val->ptr++; /* Skip over '=' character */ eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len; val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1; } } return list; } /* A helper function for checking if a comma separated list of values * contains * the given option (case insensitvely). * 'header' can be NULL, in which case false is returned. */ static int header_has_option(const char *header, const char *option) { struct vec opt_vec; struct vec eq_vec; DEBUG_ASSERT(option != NULL); DEBUG_ASSERT(option[0] != '\0'); while ((header = next_option(header, &opt_vec, &eq_vec)) != NULL) { if (mg_strncasecmp(option, opt_vec.ptr, opt_vec.len) == 0) return 1; } return 0; } /* Sorting function implemented in a separate file */ #include "sort.h" /* Pattern matching has been reimplemented in a new file */ #include "match.h" /* HTTP 1.1 assumes keep alive if "Connection:" header is not set * This function must tolerate situations when connection info is not * set up, for example if request parsing failed. */ static int should_keep_alive(const struct mg_connection *conn) { const char *http_version; const char *header; /* First satisfy needs of the server */ if ((conn == NULL) || conn->must_close) { /* Close, if civetweb framework needs to close */ return 0; } if (mg_strcasecmp(conn->dom_ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0) { /* Close, if keep alive is not enabled */ return 0; } /* Check explicit wish of the client */ header = mg_get_header(conn, "Connection"); if (header) { /* If there is a connection header from the client, obey */ if (header_has_option(header, "keep-alive")) { return 1; } return 0; } /* Use default of the standard */ http_version = get_http_version(conn); if (http_version && (0 == strcmp(http_version, "1.1"))) { /* HTTP 1.1 default is keep alive */ return 1; } /* HTTP 1.0 (and earlier) default is to close the connection */ return 0; } static int should_decode_url(const struct mg_connection *conn) { if (!conn || !conn->dom_ctx) { return 0; } return (mg_strcasecmp(conn->dom_ctx->config[DECODE_URL], "yes") == 0); } static int should_decode_query_string(const struct mg_connection *conn) { if (!conn || !conn->dom_ctx) { return 0; } return (mg_strcasecmp(conn->dom_ctx->config[DECODE_QUERY_STRING], "yes") == 0); } static const char * suggest_connection_header(const struct mg_connection *conn) { return should_keep_alive(conn) ? "keep-alive" : "close"; } #include "response.h" static void send_no_cache_header(struct mg_connection *conn) { /* Send all current and obsolete cache opt-out directives. */ mg_response_header_add(conn, "Cache-Control", "no-cache, no-store, " "must-revalidate, private, max-age=0", -1); mg_response_header_add(conn, "Expires", "0", -1); if (conn->protocol_type == PROTOCOL_TYPE_HTTP1) { /* Obsolete, but still send it for HTTP/1.0 */ mg_response_header_add(conn, "Pragma", "no-cache", -1); } } static void send_static_cache_header(struct mg_connection *conn) { #if !defined(NO_CACHING) int max_age; char val[64]; const char *cache_control = conn->dom_ctx->config[STATIC_FILE_CACHE_CONTROL]; /* If there is a full cache-control option configured,0 use it */ if (cache_control != NULL) { mg_response_header_add(conn, "Cache-Control", cache_control, -1); return; } /* Read the server config to check how long a file may be cached. * The configuration is in seconds. */ max_age = atoi(conn->dom_ctx->config[STATIC_FILE_MAX_AGE]); if (max_age <= 0) { /* 0 means "do not cache". All values <0 are reserved * and may be used differently in the future. */ /* If a file should not be cached, do not only send * max-age=0, but also pragmas and Expires headers. */ send_no_cache_header(conn); return; } /* Use "Cache-Control: max-age" instead of "Expires" header. * Reason: see https://www.mnot.net/blog/2007/05/15/expires_max-age */ /* See also https://www.mnot.net/cache_docs/ */ /* According to RFC 2616, Section 14.21, caching times should not exceed * one year. A year with 365 days corresponds to 31536000 seconds, a * leap * year to 31622400 seconds. For the moment, we just send whatever has * been configured, still the behavior for >1 year should be considered * as undefined. */ mg_snprintf( conn, NULL, val, sizeof(val), "max-age=%lu", (unsigned long)max_age); mg_response_header_add(conn, "Cache-Control", val, -1); #else /* NO_CACHING */ send_no_cache_header(conn); #endif /* !NO_CACHING */ } static void send_additional_header(struct mg_connection *conn) { const char *header = conn->dom_ctx->config[ADDITIONAL_HEADER]; #if !defined(NO_SSL) if (conn->dom_ctx->config[STRICT_HTTPS_MAX_AGE]) { long max_age = atol(conn->dom_ctx->config[STRICT_HTTPS_MAX_AGE]); if (max_age >= 0) { char val[64]; mg_snprintf(conn, NULL, val, sizeof(val), "max-age=%lu", (unsigned long)max_age); mg_response_header_add(conn, "Strict-Transport-Security", val, -1); } } #endif if (header && header[0]) { mg_response_header_add_lines(conn, header); } } static void send_cors_header(struct mg_connection *conn) { const char *origin_hdr = mg_get_header(conn, "Origin"); const char *cors_orig_cfg = conn->dom_ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN]; if (cors_orig_cfg && *cors_orig_cfg && origin_hdr && *origin_hdr) { /* Cross-origin resource sharing (CORS), see * http://www.html5rocks.com/en/tutorials/cors/, * http://www.html5rocks.com/static/images/cors_server_flowchart.png * CORS preflight is not supported for files. */ mg_response_header_add(conn, "Access-Control-Allow-Origin", cors_orig_cfg, -1); } } #if !defined(NO_FILESYSTEMS) static void handle_file_based_request(struct mg_connection *conn, const char *path, struct mg_file *filep); #endif /* NO_FILESYSTEMS */ CIVETWEB_API const char * mg_get_response_code_text(const struct mg_connection *conn, int response_code) { /* See IANA HTTP status code assignment: * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml */ switch (response_code) { /* RFC2616 Section 10.1 - Informational 1xx */ case 100: return "Continue"; /* RFC2616 Section 10.1.1 */ case 101: return "Switching Protocols"; /* RFC2616 Section 10.1.2 */ case 102: return "Processing"; /* RFC2518 Section 10.1 */ /* RFC2616 Section 10.2 - Successful 2xx */ case 200: return "OK"; /* RFC2616 Section 10.2.1 */ case 201: return "Created"; /* RFC2616 Section 10.2.2 */ case 202: return "Accepted"; /* RFC2616 Section 10.2.3 */ case 203: return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */ case 204: return "No Content"; /* RFC2616 Section 10.2.5 */ case 205: return "Reset Content"; /* RFC2616 Section 10.2.6 */ case 206: return "Partial Content"; /* RFC2616 Section 10.2.7 */ case 207: return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1 */ case 208: return "Already Reported"; /* RFC5842 Section 7.1 */ case 226: return "IM used"; /* RFC3229 Section 10.4.1 */ /* RFC2616 Section 10.3 - Redirection 3xx */ case 300: return "Multiple Choices"; /* RFC2616 Section 10.3.1 */ case 301: return "Moved Permanently"; /* RFC2616 Section 10.3.2 */ case 302: return "Found"; /* RFC2616 Section 10.3.3 */ case 303: return "See Other"; /* RFC2616 Section 10.3.4 */ case 304: return "Not Modified"; /* RFC2616 Section 10.3.5 */ case 305: return "Use Proxy"; /* RFC2616 Section 10.3.6 */ case 307: return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */ case 308: return "Permanent Redirect"; /* RFC7238 Section 3 */ /* RFC2616 Section 10.4 - Client Error 4xx */ case 400: return "Bad Request"; /* RFC2616 Section 10.4.1 */ case 401: return "Unauthorized"; /* RFC2616 Section 10.4.2 */ case 402: return "Payment Required"; /* RFC2616 Section 10.4.3 */ case 403: return "Forbidden"; /* RFC2616 Section 10.4.4 */ case 404: return "Not Found"; /* RFC2616 Section 10.4.5 */ case 405: return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */ case 406: return "Not Acceptable"; /* RFC2616 Section 10.4.7 */ case 407: return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */ case 408: return "Request Time-out"; /* RFC2616 Section 10.4.9 */ case 409: return "Conflict"; /* RFC2616 Section 10.4.10 */ case 410: return "Gone"; /* RFC2616 Section 10.4.11 */ case 411: return "Length Required"; /* RFC2616 Section 10.4.12 */ case 412: return "Precondition Failed"; /* RFC2616 Section 10.4.13 */ case 413: return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */ case 414: return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */ case 415: return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */ case 416: return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17 */ case 417: return "Expectation Failed"; /* RFC2616 Section 10.4.18 */ case 421: return "Misdirected Request"; /* RFC7540 Section 9.1.2 */ case 422: return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918 * Section 11.2 */ case 423: return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */ case 424: return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918 * Section 11.4 */ case 426: return "Upgrade Required"; /* RFC 2817 Section 4 */ case 428: return "Precondition Required"; /* RFC 6585, Section 3 */ case 429: return "Too Many Requests"; /* RFC 6585, Section 4 */ case 431: return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */ case 451: return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05, * Section 3 */ /* RFC2616 Section 10.5 - Server Error 5xx */ case 500: return "Internal Server Error"; /* RFC2616 Section 10.5.1 */ case 501: return "Not Implemented"; /* RFC2616 Section 10.5.2 */ case 502: return "Bad Gateway"; /* RFC2616 Section 10.5.3 */ case 503: return "Service Unavailable"; /* RFC2616 Section 10.5.4 */ case 504: return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */ case 505: return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */ case 506: return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */ case 507: return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918 * Section 11.5 */ case 508: return "Loop Detected"; /* RFC5842 Section 7.1 */ case 510: return "Not Extended"; /* RFC 2774, Section 7 */ case 511: return "Network Authentication Required"; /* RFC 6585, Section 6 */ /* Other status codes, not shown in the IANA HTTP status code * assignment. * E.g., "de facto" standards due to common use, ... */ case 418: return "I am a teapot"; /* RFC2324 Section 2.3.2 */ case 419: return "Authentication Timeout"; /* common use */ case 420: return "Enhance Your Calm"; /* common use */ case 440: return "Login Timeout"; /* common use */ case 509: return "Bandwidth Limit Exceeded"; /* common use */ default: /* This error code is unknown. This should not happen. */ if (conn) { mg_cry_internal(conn, "Unknown HTTP response code: %u", response_code); } /* Return at least a category according to RFC 2616 Section 10. */ if (response_code >= 100 && response_code < 200) { /* Unknown informational status code */ return "Information"; } if (response_code >= 200 && response_code < 300) { /* Unknown success code */ return "Success"; } if (response_code >= 300 && response_code < 400) { /* Unknown redirection code */ return "Redirection"; } if (response_code >= 400 && response_code < 500) { /* Unknown request error code */ return "Client Error"; } if (response_code >= 500 && response_code < 600) { /* Unknown server error code */ return "Server Error"; } /* Response code not even within reasonable range */ return ""; } } static int mg_send_http_error_impl(struct mg_connection *conn, int status, const char *fmt, va_list args) { char errmsg_buf[MG_BUF_LEN]; va_list ap; int has_body; #if !defined(NO_FILESYSTEMS) char path_buf[UTF8_PATH_MAX]; int len, i, page_handler_found, scope, truncated; const char *error_handler = NULL; struct mg_file error_page_file = STRUCT_FILE_INITIALIZER; const char *error_page_file_ext, *tstr; #endif /* NO_FILESYSTEMS */ int handled_by_callback = 0; if ((conn == NULL) || (fmt == NULL)) { return -2; } /* Set status (for log) */ conn->status_code = status; /* Errors 1xx, 204 and 304 MUST NOT send a body */ has_body = ((status > 199) && (status != 204) && (status != 304)); /* Prepare message in buf, if required */ if (has_body || (!conn->in_error_handler && (conn->phys_ctx->callbacks.http_error != NULL))) { /* Store error message in errmsg_buf */ va_copy(ap, args); mg_vsnprintf(conn, NULL, errmsg_buf, sizeof(errmsg_buf), fmt, ap); va_end(ap); /* In a debug build, print all html errors */ DEBUG_TRACE("Error %i - [%s]", status, errmsg_buf); } /* If there is a http_error callback, call it. * But don't do it recursively, if callback calls mg_send_http_error again. */ if (!conn->in_error_handler && (conn->phys_ctx->callbacks.http_error != NULL)) { /* Mark in_error_handler to avoid recursion and call user callback. */ conn->in_error_handler = 1; handled_by_callback = (conn->phys_ctx->callbacks.http_error(conn, status, errmsg_buf) == 0); conn->in_error_handler = 0; } if (!handled_by_callback) { /* Check for recursion */ if (conn->in_error_handler) { DEBUG_TRACE( "Recursion when handling error %u - fall back to default", status); #if !defined(NO_FILESYSTEMS) } else { /* Send user defined error pages, if defined */ error_handler = conn->dom_ctx->config[ERROR_PAGES]; error_page_file_ext = conn->dom_ctx->config[INDEX_FILES]; page_handler_found = 0; if (error_handler != NULL) { for (scope = 1; (scope <= 3) && !page_handler_found; scope++) { switch (scope) { case 1: /* Handler for specific error, e.g. 404 error */ mg_snprintf(conn, &truncated, path_buf, sizeof(path_buf) - 32, "%serror%03u.", error_handler, status); break; case 2: /* Handler for error group, e.g., 5xx error * handler * for all server errors (500-599) */ mg_snprintf(conn, &truncated, path_buf, sizeof(path_buf) - 32, "%serror%01uxx.", error_handler, status / 100); break; default: /* Handler for all errors */ mg_snprintf(conn, &truncated, path_buf, sizeof(path_buf) - 32, "%serror.", error_handler); break; } /* String truncation in buf may only occur if * error_handler is too long. This string is * from the config, not from a client. */ (void)truncated; /* The following code is redundant, but it should avoid * false positives in static source code analyzers and * vulnerability scanners. */ path_buf[sizeof(path_buf) - 32] = 0; len = (int)strlen(path_buf); if (len > (int)sizeof(path_buf) - 32) { len = (int)sizeof(path_buf) - 32; } /* Start with the file extension from the configuration. */ tstr = strchr(error_page_file_ext, '.'); while (tstr) { for (i = 1; (i < 32) && (tstr[i] != 0) && (tstr[i] != ','); i++) { /* buffer overrun is not possible here, since * (i < 32) && (len < sizeof(path_buf) - 32) * ==> (i + len) < sizeof(path_buf) */ path_buf[len + i - 1] = tstr[i]; } /* buffer overrun is not possible here, since * (i <= 32) && (len < sizeof(path_buf) - 32) * ==> (i + len) <= sizeof(path_buf) */ path_buf[len + i - 1] = 0; if (mg_stat(conn, path_buf, &error_page_file.stat)) { DEBUG_TRACE("Check error page %s - found", path_buf); page_handler_found = 1; break; } DEBUG_TRACE("Check error page %s - not found", path_buf); /* Continue with the next file extension from the * configuration (if there is a next one). */ tstr = strchr(tstr + i, '.'); } } } if (page_handler_found) { conn->in_error_handler = 1; handle_file_based_request(conn, path_buf, &error_page_file); conn->in_error_handler = 0; return 0; } #endif /* NO_FILESYSTEMS */ } /* No custom error page. Send default error page. */ conn->must_close = 1; mg_response_header_start(conn, status); send_no_cache_header(conn); send_additional_header(conn); send_cors_header(conn); if (has_body) { mg_response_header_add(conn, "Content-Type", "text/plain; charset=utf-8", -1); } mg_response_header_send(conn); /* HTTP responses 1xx, 204 and 304 MUST NOT send a body */ if (has_body) { /* For other errors, send a generic error message. */ const char *status_text = mg_get_response_code_text(conn, status); mg_printf(conn, "Error %d: %s\n", status, status_text); mg_write(conn, errmsg_buf, strlen(errmsg_buf)); } else { /* No body allowed. Close the connection. */ DEBUG_TRACE("Error %i", status); } } return 0; } CIVETWEB_API int mg_send_http_error(struct mg_connection *conn, int status, const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = mg_send_http_error_impl(conn, status, fmt, ap); va_end(ap); return ret; } CIVETWEB_API int mg_send_http_ok(struct mg_connection *conn, const char *mime_type, long long content_length) { if ((mime_type == NULL) || (*mime_type == 0)) { /* No content type defined: default to text/html */ mime_type = "text/html"; } mg_response_header_start(conn, 200); send_no_cache_header(conn); send_additional_header(conn); send_cors_header(conn); mg_response_header_add(conn, "Content-Type", mime_type, -1); if (content_length < 0) { /* Size not known. Use chunked encoding (HTTP/1.x) */ if (conn->protocol_type == PROTOCOL_TYPE_HTTP1) { /* Only HTTP/1.x defines "chunked" encoding, HTTP/2 does not*/ mg_response_header_add(conn, "Transfer-Encoding", "chunked", -1); } } else { char len[32]; int trunc = 0; mg_snprintf(conn, &trunc, len, sizeof(len), "%" UINT64_FMT, (uint64_t)content_length); if (!trunc) { /* Since 32 bytes is enough to hold any 64 bit decimal number, * !trunc is always true */ mg_response_header_add(conn, "Content-Length", len, -1); } } mg_response_header_send(conn); return 0; } CIVETWEB_API int mg_send_http_redirect(struct mg_connection *conn, const char *target_url, int redirect_code) { /* Send a 30x redirect response. * * Redirect types (status codes): * * Status | Perm/Temp | Method | Version * 301 | permanent | POST->GET undefined | HTTP/1.0 * 302 | temporary | POST->GET undefined | HTTP/1.0 * 303 | temporary | always use GET | HTTP/1.1 * 307 | temporary | always keep method | HTTP/1.1 * 308 | permanent | always keep method | HTTP/1.1 */ #if defined(MG_SEND_REDIRECT_BODY) char redirect_body[MG_BUF_LEN]; size_t content_len = 0; char content_len_text[32]; #endif /* In case redirect_code=0, use 307. */ if (redirect_code == 0) { redirect_code = 307; } /* In case redirect_code is none of the above, return error. */ if ((redirect_code != 301) && (redirect_code != 302) && (redirect_code != 303) && (redirect_code != 307) && (redirect_code != 308)) { /* Parameter error */ return -2; } /* If target_url is not defined, redirect to "/". */ if ((target_url == NULL) || (*target_url == 0)) { target_url = "/"; } #if defined(MG_SEND_REDIRECT_BODY) /* TODO: condition name? */ /* Prepare a response body with a hyperlink. * * According to RFC2616 (and RFC1945 before): * Unless the request method was HEAD, the entity of the * response SHOULD contain a short hypertext note with a hyperlink to * the new URI(s). * * However, this response body is not useful in M2M communication. * Probably the original reason in the RFC was, clients not supporting * a 30x HTTP redirect could still show the HTML page and let the user * press the link. Since current browsers support 30x HTTP, the additional * HTML body does not seem to make sense anymore. * * The new RFC7231 (Section 6.4) does no longer recommend it ("SHOULD"), * but it only notes: * The server's response payload usually contains a short * hypertext note with a hyperlink to the new URI(s). * * Deactivated by default. If you need the 30x body, set the define. */ mg_snprintf( conn, NULL /* ignore truncation */, redirect_body, sizeof(redirect_body), "%s%s", redirect_text, target_url, target_url); content_len = strlen(reply); sprintf(content_len_text, "%lu", (unsigned long)content_len); #endif /* Send all required headers */ mg_response_header_start(conn, redirect_code); mg_response_header_add(conn, "Location", target_url, -1); if ((redirect_code == 301) || (redirect_code == 308)) { /* Permanent redirect */ send_static_cache_header(conn); } else { /* Temporary redirect */ send_no_cache_header(conn); } send_additional_header(conn); send_cors_header(conn); #if defined(MG_SEND_REDIRECT_BODY) mg_response_header_add(conn, "Content-Type", "text/html", -1); mg_response_header_add(conn, "Content-Length", content_len_text, -1); #else mg_response_header_add(conn, "Content-Length", "0", 1); #endif mg_response_header_send(conn); #if defined(MG_SEND_REDIRECT_BODY) /* Send response body */ /* ... unless it is a HEAD request */ if (0 != strcmp(conn->request_info.request_method, "HEAD")) { ret = mg_write(conn, redirect_body, content_len); } #endif return 1; } #if defined(_WIN32) /* Create substitutes for POSIX functions in Win32. */ #if defined(GCC_DIAGNOSTIC) /* Show no warning in case system functions are not used. */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-function" #endif static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused) { (void)unused; /* Always initialize as PTHREAD_MUTEX_RECURSIVE */ InitializeCriticalSection(&mutex->sec); return 0; } static int pthread_mutex_destroy(pthread_mutex_t *mutex) { DeleteCriticalSection(&mutex->sec); return 0; } static int pthread_mutex_lock(pthread_mutex_t *mutex) { EnterCriticalSection(&mutex->sec); return 0; } static int pthread_mutex_unlock(pthread_mutex_t *mutex) { LeaveCriticalSection(&mutex->sec); return 0; } FUNCTION_MAY_BE_UNUSED static int pthread_cond_init(pthread_cond_t *cv, const void *unused) { (void)unused; (void)pthread_mutex_init(&cv->threadIdSec, &pthread_mutex_attr); cv->waiting_thread = NULL; return 0; } FUNCTION_MAY_BE_UNUSED static int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mutex, FUNCTION_MAY_BE_UNUSED const struct timespec *abstime) { struct mg_workerTLS **ptls, *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey); int ok; uint64_t nsnow, nswaitabs; int64_t nswaitrel; DWORD mswaitrel; pthread_mutex_lock(&cv->threadIdSec); /* Add this thread to cv's waiting list */ ptls = &cv->waiting_thread; for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread) ; tls->next_waiting_thread = NULL; *ptls = tls; pthread_mutex_unlock(&cv->threadIdSec); if (abstime) { nsnow = mg_get_current_time_ns(); nswaitabs = (((uint64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec; nswaitrel = nswaitabs - nsnow; if (nswaitrel < 0) { nswaitrel = 0; } mswaitrel = (DWORD)(nswaitrel / 1000000); } else { mswaitrel = (DWORD)INFINITE; } pthread_mutex_unlock(mutex); ok = (WAIT_OBJECT_0 == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel)); if (!ok) { ok = 1; pthread_mutex_lock(&cv->threadIdSec); ptls = &cv->waiting_thread; for (; *ptls != NULL; ptls = &(*ptls)->next_waiting_thread) { if (*ptls == tls) { *ptls = tls->next_waiting_thread; ok = 0; break; } } pthread_mutex_unlock(&cv->threadIdSec); if (ok) { WaitForSingleObject(tls->pthread_cond_helper_mutex, (DWORD)INFINITE); } } /* This thread has been removed from cv's waiting list */ pthread_mutex_lock(mutex); return ok ? 0 : -1; } FUNCTION_MAY_BE_UNUSED static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex) { return pthread_cond_timedwait(cv, mutex, NULL); } FUNCTION_MAY_BE_UNUSED static int pthread_cond_signal(pthread_cond_t *cv) { HANDLE wkup = NULL; BOOL ok = FALSE; pthread_mutex_lock(&cv->threadIdSec); if (cv->waiting_thread) { wkup = cv->waiting_thread->pthread_cond_helper_mutex; cv->waiting_thread = cv->waiting_thread->next_waiting_thread; ok = SetEvent(wkup); DEBUG_ASSERT(ok); } pthread_mutex_unlock(&cv->threadIdSec); return ok ? 0 : 1; } FUNCTION_MAY_BE_UNUSED static int pthread_cond_broadcast(pthread_cond_t *cv) { pthread_mutex_lock(&cv->threadIdSec); while (cv->waiting_thread) { pthread_cond_signal(cv); } pthread_mutex_unlock(&cv->threadIdSec); return 0; } FUNCTION_MAY_BE_UNUSED static int pthread_cond_destroy(pthread_cond_t *cv) { pthread_mutex_lock(&cv->threadIdSec); DEBUG_ASSERT(cv->waiting_thread == NULL); pthread_mutex_unlock(&cv->threadIdSec); pthread_mutex_destroy(&cv->threadIdSec); return 0; } #if defined(ALTERNATIVE_QUEUE) FUNCTION_MAY_BE_UNUSED static void * event_create(void) { return (void *)CreateEvent(NULL, FALSE, FALSE, NULL); } FUNCTION_MAY_BE_UNUSED static int event_wait(void *eventhdl) { int res = WaitForSingleObject((HANDLE)eventhdl, (DWORD)INFINITE); return (res == WAIT_OBJECT_0); } FUNCTION_MAY_BE_UNUSED static int event_signal(void *eventhdl) { return (int)SetEvent((HANDLE)eventhdl); } FUNCTION_MAY_BE_UNUSED static void event_destroy(void *eventhdl) { CloseHandle((HANDLE)eventhdl); } #endif #if defined(GCC_DIAGNOSTIC) /* Enable unused function warning again */ # pragma GCC diagnostic pop #endif /* For Windows, change all slashes to backslashes in path names. */ static void change_slashes_to_backslashes(char *path) { int i; for (i = 0; path[i] != '\0'; i++) { if (path[i] == '/') { path[i] = '\\'; } /* remove double backslash (check i > 0 to preserve UNC paths, * like \\server\file.txt) */ if ((i > 0) && (path[i] == '\\')) { while ((path[i + 1] == '\\') || (path[i + 1] == '/')) { (void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1)); } } } } static int mg_wcscasecmp(const wchar_t *s1, const wchar_t *s2) { int diff; do { diff = ((*s1 >= L'A') && (*s1 <= L'Z') ? (*s1 - L'A' + L'a') : *s1) - ((*s2 >= L'A') && (*s2 <= L'Z') ? (*s2 - L'A' + L'a') : *s2); s1++; s2++; } while ((diff == 0) && (s1[-1] != L'\0')); return diff; } /* Encode 'path' which is assumed UTF-8 string, into UNICODE string. * wbuf and wbuf_len is a target buffer and its length. */ static void path_to_unicode(const struct mg_connection *conn, const char *path, wchar_t *wbuf, size_t wbuf_len) { char buf[UTF8_PATH_MAX], buf2[UTF8_PATH_MAX]; wchar_t wbuf2[UTF16_PATH_MAX + 1]; DWORD long_len, err; int (*fcompare)(const wchar_t *, const wchar_t *) = mg_wcscasecmp; mg_strlcpy(buf, path, sizeof(buf)); change_slashes_to_backslashes(buf); /* Convert to Unicode and back. If doubly-converted string does not * match the original, something is fishy, reject. */ memset(wbuf, 0, wbuf_len * sizeof(wchar_t)); MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int)wbuf_len); WideCharToMultiByte( CP_UTF8, 0, wbuf, (int)wbuf_len, buf2, sizeof(buf2), NULL, NULL); if (strcmp(buf, buf2) != 0) { wbuf[0] = L'\0'; } /* Windows file systems are not case sensitive, but you can still use * uppercase and lowercase letters (on all modern file systems). * The server can check if the URI uses the same upper/lowercase * letters an the file system, effectively making Windows servers * case sensitive (like Linux servers are). It is still not possible * to use two files with the same name in different cases on Windows * (like /a and /A) - this would be possible in Linux. * As a default, Windows is not case sensitive, but the case sensitive * file name check can be activated by an additional configuration. */ if (conn) { if (conn->dom_ctx->config[CASE_SENSITIVE_FILES] && !mg_strcasecmp(conn->dom_ctx->config[CASE_SENSITIVE_FILES], "yes")) { /* Use case sensitive compare function */ fcompare = wcscmp; } } (void)conn; /* conn is currently unused */ /* Only accept a full file path, not a Windows short (8.3) path. */ memset(wbuf2, 0, ARRAY_SIZE(wbuf2) * sizeof(wchar_t)); long_len = GetLongPathNameW(wbuf, wbuf2, ARRAY_SIZE(wbuf2) - 1); if (long_len == 0) { err = GetLastError(); if (err == ERROR_FILE_NOT_FOUND) { /* File does not exist. This is not always a problem here. */ return; } } if ((long_len >= ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) { /* Short name is used. */ wbuf[0] = L'\0'; } } #if !defined(NO_FILESYSTEMS) /* Get file information, return 1 if file exists, 0 if not */ static int mg_stat(const struct mg_connection *conn, const char *path, struct mg_file_stat *filep) { wchar_t wbuf[UTF16_PATH_MAX]; WIN32_FILE_ATTRIBUTE_DATA info; time_t creation_time; size_t len; if (!filep) { return 0; } memset(filep, 0, sizeof(*filep)); if (mg_path_suspicious(conn, path)) { return 0; } path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); /* Windows happily opens files with some garbage at the end of file name. * For example, fopen("a.cgi ", "r") on Windows successfully opens * "a.cgi", despite one would expect an error back. */ len = strlen(path); if ((len > 0) && (path[len - 1] != ' ') && (path[len - 1] != '.') && (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0)) { filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh); filep->last_modified = SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime, info.ftLastWriteTime.dwHighDateTime); /* On Windows, the file creation time can be higher than the * modification time, e.g. when a file is copied. * Since the Last-Modified timestamp is used for caching * it should be based on the most recent timestamp. */ creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime, info.ftCreationTime.dwHighDateTime); if (creation_time > filep->last_modified) { filep->last_modified = creation_time; } filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; return 1; } return 0; } #endif static int mg_remove(const struct mg_connection *conn, const char *path) { wchar_t wbuf[UTF16_PATH_MAX]; path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); return DeleteFileW(wbuf) ? 0 : -1; } static int mg_mkdir(const struct mg_connection *conn, const char *path, int mode) { wchar_t wbuf[UTF16_PATH_MAX]; (void)mode; path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf)); return CreateDirectoryW(wbuf, NULL) ? 0 : -1; } /* Create substitutes for POSIX functions in Win32. */ #if defined(GCC_DIAGNOSTIC) /* Show no warning in case system functions are not used. */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-function" #endif /* Implementation of POSIX opendir/closedir/readdir for Windows. */ FUNCTION_MAY_BE_UNUSED static DIR * mg_opendir(const struct mg_connection *conn, const char *name) { DIR *dir = NULL; wchar_t wpath[UTF16_PATH_MAX]; DWORD attrs; if (name == NULL) { SetLastError(ERROR_BAD_ARGUMENTS); } else if ((dir = (DIR *)mg_malloc(sizeof(*dir))) == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); } else { path_to_unicode(conn, name, wpath, ARRAY_SIZE(wpath)); attrs = GetFileAttributesW(wpath); if ((wcslen(wpath) + 2 < ARRAY_SIZE(wpath)) && (attrs != 0xFFFFFFFF) && ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0)) { (void)wcscat(wpath, L"\\*"); dir->handle = FindFirstFileW(wpath, &dir->info); dir->result.d_name[0] = '\0'; } else { mg_free(dir); dir = NULL; } } return dir; } FUNCTION_MAY_BE_UNUSED static int mg_closedir(DIR *dir) { int result = 0; if (dir != NULL) { if (dir->handle != INVALID_HANDLE_VALUE) result = FindClose(dir->handle) ? 0 : -1; mg_free(dir); } else { result = -1; SetLastError(ERROR_BAD_ARGUMENTS); } return result; } FUNCTION_MAY_BE_UNUSED static struct dirent * mg_readdir(DIR *dir) { struct dirent *result = 0; if (dir) { if (dir->handle != INVALID_HANDLE_VALUE) { result = &dir->result; (void)WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1, result->d_name, sizeof(result->d_name), NULL, NULL); if (!FindNextFileW(dir->handle, &dir->info)) { (void)FindClose(dir->handle); dir->handle = INVALID_HANDLE_VALUE; } } else { SetLastError(ERROR_FILE_NOT_FOUND); } } else { SetLastError(ERROR_BAD_ARGUMENTS); } return result; } #if !defined(HAVE_POLL) #undef POLLIN #undef POLLPRI #undef POLLOUT #undef POLLERR #define POLLIN (1) /* Data ready - read will not block. */ #define POLLPRI (2) /* Priority data ready. */ #define POLLOUT (4) /* Send queue not full - write will not block. */ #define POLLERR (8) /* Error event */ FUNCTION_MAY_BE_UNUSED static int poll(struct mg_pollfd *pfd, unsigned int n, int milliseconds) { struct timeval tv; fd_set rset; fd_set wset; fd_set eset; unsigned int i; int result; SOCKET maxfd = 0; memset(&tv, 0, sizeof(tv)); tv.tv_sec = milliseconds / 1000; tv.tv_usec = (milliseconds % 1000) * 1000; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); for (i = 0; i < n; i++) { if (pfd[i].events & (POLLIN | POLLOUT | POLLERR)) { if (pfd[i].events & POLLIN) { FD_SET(pfd[i].fd, &rset); } if (pfd[i].events & POLLOUT) { FD_SET(pfd[i].fd, &wset); } /* Check for errors for any FD in the set */ FD_SET(pfd[i].fd, &eset); } pfd[i].revents = 0; if (pfd[i].fd > maxfd) { maxfd = pfd[i].fd; } } if ((result = select((int)maxfd + 1, &rset, &wset, &eset, &tv)) > 0) { for (i = 0; i < n; i++) { if (FD_ISSET(pfd[i].fd, &rset)) { pfd[i].revents |= POLLIN; } if (FD_ISSET(pfd[i].fd, &wset)) { pfd[i].revents |= POLLOUT; } if (FD_ISSET(pfd[i].fd, &eset)) { pfd[i].revents |= POLLERR; } } } /* We should subtract the time used in select from remaining * "milliseconds", in particular if called from mg_poll with a * timeout quantum. * Unfortunately, the remaining time is not stored in "tv" in all * implementations, so the result in "tv" must be considered undefined. * See http://man7.org/linux/man-pages/man2/select.2.html */ return result; } #endif /* HAVE_POLL */ #if defined(GCC_DIAGNOSTIC) /* Enable unused function warning again */ # pragma GCC diagnostic pop #endif static void set_close_on_exec(SOCKET sock, const struct mg_connection *conn /* may be null */, struct mg_context *ctx /* may be null */) { (void)conn; /* Unused. */ (void)ctx; (void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0); } CIVETWEB_API int mg_start_thread(mg_thread_func_t f, void *p) { #if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) /* Compile-time option to control stack size, e.g. * -DUSE_STACK_SIZE=16384 */ return ((_beginthread((void(__cdecl *)(void *))f, USE_STACK_SIZE, p) == ((uintptr_t)(-1L))) ? -1 : 0); #else return ( (_beginthread((void(__cdecl *)(void *))f, 0, p) == ((uintptr_t)(-1L))) ? -1 : 0); #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */ } /* Start a thread storing the thread context. */ static int mg_start_thread_with_id(unsigned(__stdcall *f)(void *), void *p, pthread_t *threadidptr) { uintptr_t uip; HANDLE threadhandle; int result = -1; uip = _beginthreadex(NULL, 0, f, p, 0, NULL); threadhandle = (HANDLE)uip; if ((uip != 0) && (threadidptr != NULL)) { *threadidptr = threadhandle; result = 0; } return result; } /* Wait for a thread to finish. */ static int mg_join_thread(pthread_t threadid) { int result; DWORD dwevent; result = -1; dwevent = WaitForSingleObject(threadid, (DWORD)INFINITE); if (dwevent == WAIT_FAILED) { DEBUG_TRACE("WaitForSingleObject() failed, error %d", ERRNO); } else { if (dwevent == WAIT_OBJECT_0) { CloseHandle(threadid); result = 0; } } return result; } #if !defined(NO_SSL_DL) && !defined(NO_SSL) /* If SSL is loaded dynamically, dlopen/dlclose is required. */ /* Create substitutes for POSIX functions in Win32. */ #if defined(GCC_DIAGNOSTIC) /* Show no warning in case system functions are not used. */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-function" #endif FUNCTION_MAY_BE_UNUSED static HANDLE dlopen(const char *dll_name, int flags) { wchar_t wbuf[UTF16_PATH_MAX]; (void)flags; path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf)); return LoadLibraryW(wbuf); } FUNCTION_MAY_BE_UNUSED static int dlclose(void *handle) { int result; if (FreeLibrary((HMODULE)handle) != 0) { result = 0; } else { result = -1; } return result; } #if defined(GCC_DIAGNOSTIC) /* Enable unused function warning again */ # pragma GCC diagnostic pop #endif #endif #if !defined(NO_CGI) #define SIGKILL (0) static int kill(pid_t pid, int sig_num) { (void)TerminateProcess((HANDLE)pid, (UINT)sig_num); (void)CloseHandle((HANDLE)pid); return 0; } #if !defined(WNOHANG) #define WNOHANG (1) #endif static pid_t waitpid(pid_t pid, int *status, int flags) { DWORD timeout = INFINITE; DWORD waitres; (void)status; /* Currently not used by any client here */ if ((flags | WNOHANG) == WNOHANG) { timeout = 0; } waitres = WaitForSingleObject((HANDLE)pid, timeout); if (waitres == WAIT_OBJECT_0) { return pid; } if (waitres == WAIT_TIMEOUT) { return 0; } return (pid_t)-1; } static void trim_trailing_whitespaces(char *s) { char *e = s + strlen(s); while ((e > s) && isspace((unsigned char)e[-1])) { *(--e) = '\0'; } } static pid_t spawn_process(struct mg_connection *conn, const char *prog, char *envblk, char *envp[], int fdin[2], int fdout[2], int fderr[2], const char *dir, int cgi_config_idx) { HANDLE me; char *interp; char *interp_arg = 0; char full_dir[UTF8_PATH_MAX], cmdline[UTF8_PATH_MAX], buf[UTF8_PATH_MAX]; int truncated; struct mg_file file = STRUCT_FILE_INITIALIZER; STARTUPINFOA si; PROCESS_INFORMATION pi = {0}; (void)envp; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; me = GetCurrentProcess(); DuplicateHandle(me, (HANDLE)_get_osfhandle(fdin[0]), me, &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(me, (HANDLE)_get_osfhandle(fdout[1]), me, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(me, (HANDLE)_get_osfhandle(fderr[1]), me, &si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS); /* Mark handles that should not be inherited. See * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx */ SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]), HANDLE_FLAG_INHERIT, 0); SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]), HANDLE_FLAG_INHERIT, 0); SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]), HANDLE_FLAG_INHERIT, 0); /* First check, if there is a CGI interpreter configured for all CGI * scripts. */ interp = conn->dom_ctx->config[CGI_INTERPRETER + cgi_config_idx]; if (interp != NULL) { /* If there is a configured interpreter, check for additional arguments */ interp_arg = conn->dom_ctx->config[CGI_INTERPRETER_ARGS + cgi_config_idx]; } else { /* Otherwise, the interpreter must be stated in the first line of the * CGI script file, after a #! (shebang) mark. */ buf[0] = buf[1] = '\0'; /* Get the full script path */ mg_snprintf( conn, &truncated, cmdline, sizeof(cmdline), "%s/%s", dir, prog); if (truncated) { pi.hProcess = (pid_t)-1; goto spawn_cleanup; } /* Open the script file, to read the first line */ if (mg_fopen(conn, cmdline, MG_FOPEN_MODE_READ, &file)) { /* Read the first line of the script into the buffer */ mg_fgets(buf, sizeof(buf), &file); (void)mg_fclose(&file.access); /* ignore error on read only file */ buf[sizeof(buf) - 1] = '\0'; } if ((buf[0] == '#') && (buf[1] == '!')) { trim_trailing_whitespaces(buf + 2); } else { buf[2] = '\0'; } interp = buf + 2; } GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL); if (interp[0] != '\0') { /* This is an interpreted script file. We must call the interpreter. */ if ((interp_arg != 0) && (interp_arg[0] != 0)) { mg_snprintf(conn, &truncated, cmdline, sizeof(cmdline), "\"%s\" %s \"%s\\%s\"", interp, interp_arg, full_dir, prog); } else { mg_snprintf(conn, &truncated, cmdline, sizeof(cmdline), "\"%s\" \"%s\\%s\"", interp, full_dir, prog); } } else { /* This is (probably) a compiled program. We call it directly. */ mg_snprintf(conn, &truncated, cmdline, sizeof(cmdline), "\"%s\\%s\"", full_dir, prog); } if (truncated) { pi.hProcess = (pid_t)-1; goto spawn_cleanup; } DEBUG_TRACE("Running [%s]", cmdline); if (CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP, envblk, NULL, &si, &pi) == 0) { mg_cry_internal( conn, "%s: CreateProcess(%s): %ld", __func__, cmdline, (long)ERRNO); pi.hProcess = (pid_t)-1; /* goto spawn_cleanup; */ } spawn_cleanup: (void)CloseHandle(si.hStdOutput); (void)CloseHandle(si.hStdError); (void)CloseHandle(si.hStdInput); if (pi.hThread != NULL) { (void)CloseHandle(pi.hThread); } return (pid_t)pi.hProcess; } #endif /* !NO_CGI */ static int set_blocking_mode(SOCKET sock) { unsigned long non_blocking = 0; return ioctlsocket(sock, (long)FIONBIO, &non_blocking); } static int set_non_blocking_mode(SOCKET sock) { unsigned long non_blocking = 1; return ioctlsocket(sock, (long)FIONBIO, &non_blocking); } #else #if !defined(NO_FILESYSTEMS) static int mg_stat(const struct mg_connection *conn, const char *path, struct mg_file_stat *filep) { struct stat st; if (!filep) { return 0; } memset(filep, 0, sizeof(*filep)); if (mg_path_suspicious(conn, path)) { return 0; } if (0 == stat(path, &st)) { filep->size = (uint64_t)(st.st_size); filep->last_modified = st.st_mtime; filep->is_directory = S_ISDIR(st.st_mode); return 1; } return 0; } #endif /* NO_FILESYSTEMS */ static void set_close_on_exec(int fd, const struct mg_connection *conn /* may be null */, struct mg_context *ctx /* may be null */) { #if defined(__ZEPHYR__) (void)fd; (void)conn; (void)ctx; #else if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) { if (conn || ctx) { struct mg_connection fc; mg_cry_internal((conn ? conn : fake_connection(&fc, ctx)), "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s", __func__, strerror(ERRNO)); } } #endif } CIVETWEB_API int mg_start_thread(mg_thread_func_t func, void *param) { pthread_t thread_id; pthread_attr_t attr; int result; (void)pthread_attr_init(&attr); (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); #if defined(__ZEPHYR__) pthread_attr_setstack(&attr, &civetweb_main_stack, ZEPHYR_STACK_SIZE); #elif defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) /* Compile-time option to control stack size, * e.g. -DUSE_STACK_SIZE=16384 */ (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE); #endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */ result = pthread_create(&thread_id, &attr, func, param); pthread_attr_destroy(&attr); return result; } /* Start a thread storing the thread context. */ static int mg_start_thread_with_id(mg_thread_func_t func, void *param, pthread_t *threadidptr) { pthread_t thread_id; pthread_attr_t attr; int result; (void)pthread_attr_init(&attr); #if defined(__ZEPHYR__) pthread_attr_setstack(&attr, &civetweb_worker_stacks[zephyr_worker_stack_index++], ZEPHYR_STACK_SIZE); #elif defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) /* Compile-time option to control stack size, * e.g. -DUSE_STACK_SIZE=16384 */ (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE); #endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */ result = pthread_create(&thread_id, &attr, func, param); pthread_attr_destroy(&attr); if ((result == 0) && (threadidptr != NULL)) { *threadidptr = thread_id; } return result; } /* Wait for a thread to finish. */ static int mg_join_thread(pthread_t threadid) { int result; result = pthread_join(threadid, NULL); return result; } #if !defined(NO_CGI) static pid_t spawn_process(struct mg_connection *conn, const char *prog, char *envblk, char *envp[], int fdin[2], int fdout[2], int fderr[2], const char *dir, int cgi_config_idx) { pid_t pid; const char *interp; (void)envblk; if ((pid = fork()) == -1) { /* Parent */ mg_cry_internal(conn, "%s: fork(): %s", __func__, strerror(ERRNO)); } else if (pid != 0) { /* Make sure children close parent-side descriptors. * The caller will close the child-side immediately. */ set_close_on_exec(fdin[1], conn, NULL); /* stdin write */ set_close_on_exec(fdout[0], conn, NULL); /* stdout read */ set_close_on_exec(fderr[0], conn, NULL); /* stderr read */ } else { /* Child */ if (chdir(dir) != 0) { mg_cry_internal( conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO)); } else if (dup2(fdin[0], 0) == -1) { mg_cry_internal(conn, "%s: dup2(%d, 0): %s", __func__, fdin[0], strerror(ERRNO)); } else if (dup2(fdout[1], 1) == -1) { mg_cry_internal(conn, "%s: dup2(%d, 1): %s", __func__, fdout[1], strerror(ERRNO)); } else if (dup2(fderr[1], 2) == -1) { mg_cry_internal(conn, "%s: dup2(%d, 2): %s", __func__, fderr[1], strerror(ERRNO)); } else { struct sigaction sa; /* Keep stderr and stdout in two different pipes. * Stdout will be sent back to the client, * stderr should go into a server error log. */ (void)close(fdin[0]); (void)close(fdout[1]); (void)close(fderr[1]); /* Close write end fdin and read end fdout and fderr */ (void)close(fdin[1]); (void)close(fdout[0]); (void)close(fderr[0]); /* After exec, all signal handlers are restored to their default * values, with one exception of SIGCHLD. According to * POSIX.1-2001 and Linux's implementation, SIGCHLD's handler * will leave unchanged after exec if it was set to be ignored. * Restore it to default action. */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); interp = conn->dom_ctx->config[CGI_INTERPRETER + cgi_config_idx]; if (interp == NULL) { /* no interpreter configured, call the program directly */ (void)execle(prog, prog, NULL, envp); mg_cry_internal(conn, "%s: execle(%s): %s", __func__, prog, strerror(ERRNO)); } else { /* call the configured interpreter */ const char *interp_args = conn->dom_ctx ->config[CGI_INTERPRETER_ARGS + cgi_config_idx]; if ((interp_args != NULL) && (interp_args[0] != 0)) { (void)execle(interp, interp, interp_args, prog, NULL, envp); } else { (void)execle(interp, interp, prog, NULL, envp); } mg_cry_internal(conn, "%s: execle(%s %s): %s", __func__, interp, prog, strerror(ERRNO)); } } exit(EXIT_FAILURE); } return pid; } #endif /* !NO_CGI */ static int set_non_blocking_mode(SOCKET sock) { int flags = fcntl(sock, F_GETFL, 0); if (flags < 0) { return -1; } if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) < 0) { return -1; } return 0; } static int set_blocking_mode(SOCKET sock) { int flags = fcntl(sock, F_GETFL, 0); if (flags < 0) { return -1; } if (fcntl(sock, F_SETFL, flags & (~(int)(O_NONBLOCK))) < 0) { return -1; } return 0; } #endif /* _WIN32 / else */ /* End of initial operating system specific define block. */ /* Get a random number (independent of C rand function) */ static uint64_t get_random(void) { static uint64_t lfsr = 0; /* Linear feedback shift register */ static uint64_t lcg = 0; /* Linear congruential generator */ uint64_t now = mg_get_current_time_ns(); if (lfsr == 0) { /* lfsr will be only 0 if has not been initialized, * so this code is called only once. */ lfsr = mg_get_current_time_ns(); lcg = mg_get_current_time_ns(); } else { /* Get the next step of both random number generators. */ lfsr = (lfsr >> 1) | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1) << 63); lcg = lcg * 6364136223846793005LL + 1442695040888963407LL; } /* Combining two pseudo-random number generators and a high resolution * part * of the current server time will make it hard (impossible?) to guess * the * next number. */ return (lfsr ^ lcg ^ now); } static int mg_poll(struct mg_pollfd *pfd, unsigned int n, int milliseconds, const stop_flag_t *stop_flag) { /* Call poll, but only for a maximum time of a few seconds. * This will allow to stop the server after some seconds, instead * of having to wait for a long socket timeout. */ int ms_now = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */ int check_pollerr = 0; if ((n == 1) && ((pfd[0].events & POLLERR) == 0)) { /* If we wait for only one file descriptor, wait on error as well */ pfd[0].events |= POLLERR; check_pollerr = 1; } do { int result; if (!STOP_FLAG_IS_ZERO(&*stop_flag)) { /* Shut down signal */ return -2; } if ((milliseconds >= 0) && (milliseconds < ms_now)) { ms_now = milliseconds; } result = poll(pfd, n, ms_now); if (result != 0) { int err = ERRNO; if ((result == 1) || (!ERROR_TRY_AGAIN(err))) { /* Poll returned either success (1) or error (-1). * Forward both to the caller. */ if ((check_pollerr) && ((pfd[0].revents & (POLLIN | POLLOUT | POLLERR)) == POLLERR)) { /* One and only file descriptor returned error */ return -1; } return result; } } /* Poll returned timeout (0). */ if (milliseconds > 0) { milliseconds -= ms_now; } } while (milliseconds > 0); /* timeout: return 0 */ return 0; } /* Write data to the IO channel - opened file descriptor, socket or SSL * descriptor. * Return value: * >=0 .. number of bytes successfully written * -1 .. timeout * -2 .. error */ static int push_inner(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int len, double timeout) { uint64_t start = 0, now = 0, timeout_ns = 0; int n, err; unsigned ms_wait = SOCKET_TIMEOUT_QUANTUM; /* Sleep quantum in ms */ #if defined(_WIN32) typedef int len_t; #else typedef size_t len_t; #endif if (timeout > 0) { now = mg_get_current_time_ns(); start = now; timeout_ns = (uint64_t)(timeout * 1.0E9); } if (ctx == NULL) { return -2; } #if defined(NO_SSL) && !defined(USE_MBEDTLS) if (ssl) { return -2; } #endif /* Try to read until it succeeds, fails, times out, or the server * shuts down. */ for (;;) { #if defined(USE_MBEDTLS) if (ssl != NULL) { n = mbed_ssl_write(ssl, (const unsigned char *)buf, len); if (n <= 0) { if ((n == MBEDTLS_ERR_SSL_WANT_READ) || (n == MBEDTLS_ERR_SSL_WANT_WRITE) || n == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { n = 0; } else { DEBUG_TRACE("SSL write failed, error %d\n", n); return -2; } } else { err = 0; } } else #elif !defined(NO_SSL) if (ssl != NULL) { ERR_clear_error(); n = SSL_write(ssl, buf, len); if (n <= 0) { err = SSL_get_error(ssl, n); if ((err == SSL_ERROR_SYSCALL) && (n == -1)) { err = ERRNO; } else if ((err == SSL_ERROR_WANT_READ) || (err == SSL_ERROR_WANT_WRITE)) { n = 0; } else { DEBUG_TRACE("SSL_write() failed, error %d", err); ERR_clear_error(); return -2; } ERR_clear_error(); } else { err = 0; } } else #endif if (fp != NULL) { n = (int)fwrite(buf, 1, (size_t)len, fp); if (ferror(fp)) { n = -1; err = ERRNO; } else { err = 0; } } else { n = (int)send(sock, buf, (len_t)len, MSG_NOSIGNAL); err = (n < 0) ? ERRNO : 0; if (ERROR_TRY_AGAIN(err)) { err = 0; n = 0; } if (n < 0) { /* shutdown of the socket at client side */ return -2; } } if (!STOP_FLAG_IS_ZERO(&ctx->stop_flag)) { return -2; } if ((n > 0) || ((n == 0) && (len == 0))) { /* some data has been read, or no data was requested */ return n; } if (n < 0) { /* socket error - check errno */ DEBUG_TRACE("send() failed, error %d", err); /* TODO (mid): error handling depending on the error code. * These codes are different between Windows and Linux. * Currently there is no problem with failing send calls, * if there is a reproducible situation, it should be * investigated in detail. */ return -2; } /* Only in case n=0 (timeout), repeat calling the write function */ /* If send failed, wait before retry */ if (fp != NULL) { /* For files, just wait a fixed time. * Maybe it helps, maybe not. */ mg_sleep(5); } else { /* For sockets, wait for the socket using poll */ struct mg_pollfd pfd[1]; int pollres; pfd[0].fd = sock; pfd[0].events = POLLOUT; pollres = mg_poll(pfd, 1, (int)(ms_wait), &(ctx->stop_flag)); if (!STOP_FLAG_IS_ZERO(&ctx->stop_flag)) { return -2; } if (pollres > 0) { continue; } } if (timeout > 0) { now = mg_get_current_time_ns(); if ((now - start) > timeout_ns) { /* Timeout */ break; } } } (void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not used */ return -1; } static int push_all(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int len) { double timeout = -1.0; int n, nwritten = 0; if (ctx == NULL) { return -1; } if (ctx->dd.config[REQUEST_TIMEOUT]) { timeout = atoi(ctx->dd.config[REQUEST_TIMEOUT]) / 1000.0; } if (timeout <= 0.0) { timeout = strtod(config_options[REQUEST_TIMEOUT].default_value, NULL) / 1000.0; } while ((len > 0) && STOP_FLAG_IS_ZERO(&ctx->stop_flag)) { n = push_inner(ctx, fp, sock, ssl, buf + nwritten, len, timeout); if (n < 0) { if (nwritten == 0) { nwritten = -1; /* Propagate the error */ } break; } else if (n == 0) { break; /* No more data to write */ } else { nwritten += n; len -= n; } } return nwritten; } /* Read from IO channel - opened file descriptor, socket, or SSL descriptor. * Return value: * >=0 .. number of bytes successfully read * -1 .. timeout * -2 .. error */ static int pull_inner(FILE *fp, struct mg_connection *conn, char *buf, int len, double timeout) { int nread, err = 0; #if defined(_WIN32) typedef int len_t; #else typedef size_t len_t; #endif /* We need an additional wait loop around this, because in some cases * with TLSwe may get data from the socket but not from SSL_read. * In this case we need to repeat at least once. */ if (fp != NULL) { /* Use read() instead of fread(), because if we're reading from the * CGI pipe, fread() may block until IO buffer is filled up. We * cannot afford to block and must pass all read bytes immediately * to the client. */ nread = (int)read(fileno(fp), buf, (size_t)len); err = (nread < 0) ? ERRNO : 0; if ((nread == 0) && (len > 0)) { /* Should get data, but got EOL */ return -2; } #if defined(USE_MBEDTLS) } else if (conn->ssl != NULL) { struct mg_pollfd pfd[1]; int to_read; int pollres; to_read = mbedtls_ssl_get_bytes_avail(conn->ssl); if (to_read > 0) { /* We already know there is no more data buffered in conn->buf * but there is more available in the SSL layer. So don't poll * conn->client.sock yet. */ pollres = 1; if (to_read > len) to_read = len; } else { pfd[0].fd = conn->client.sock; pfd[0].events = POLLIN; to_read = len; pollres = mg_poll(pfd, 1, (int)(timeout * 1000.0), &(conn->phys_ctx->stop_flag)); if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) { return -2; } } if (pollres > 0) { nread = mbed_ssl_read(conn->ssl, (unsigned char *)buf, to_read); if (nread <= 0) { if ((nread == MBEDTLS_ERR_SSL_WANT_READ) || (nread == MBEDTLS_ERR_SSL_WANT_WRITE) || nread == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { nread = 0; } else { DEBUG_TRACE("SSL read failed, error %d\n", nread); return -2; } } else { err = 0; } } else if (pollres < 0) { /* Error */ return -2; } else { /* pollres = 0 means timeout */ nread = 0; } #elif !defined(NO_SSL) } else if (conn->ssl != NULL) { int ssl_pending; struct mg_pollfd pfd[1]; int pollres; if ((ssl_pending = SSL_pending(conn->ssl)) > 0) { /* We already know there is no more data buffered in conn->buf * but there is more available in the SSL layer. So don't poll * conn->client.sock yet. */ if (ssl_pending > len) { ssl_pending = len; } pollres = 1; } else { pfd[0].fd = conn->client.sock; pfd[0].events = POLLIN; pollres = mg_poll(pfd, 1, (int)(timeout * 1000.0), &(conn->phys_ctx->stop_flag)); if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) { return -2; } } if (pollres > 0) { ERR_clear_error(); nread = SSL_read(conn->ssl, buf, (ssl_pending > 0) ? ssl_pending : len); if (nread <= 0) { err = SSL_get_error(conn->ssl, nread); if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) { err = ERRNO; } else if ((err == SSL_ERROR_WANT_READ) || (err == SSL_ERROR_WANT_WRITE)) { nread = 0; } else { /* All errors should return -2 */ DEBUG_TRACE("SSL_read() failed, error %d", err); ERR_clear_error(); return -2; } ERR_clear_error(); } else { err = 0; } } else if (pollres < 0) { /* Error */ return -2; } else { /* pollres = 0 means timeout */ nread = 0; } #endif } else { struct mg_pollfd pfd[1]; int pollres; pfd[0].fd = conn->client.sock; pfd[0].events = POLLIN; pollres = mg_poll(pfd, 1, (int)(timeout * 1000.0), &(conn->phys_ctx->stop_flag)); if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) { return -2; } if (pollres > 0) { nread = (int)recv(conn->client.sock, buf, (len_t)len, 0); err = (nread < 0) ? ERRNO : 0; if (nread <= 0) { /* shutdown of the socket at client side */ return -2; } } else if (pollres < 0) { /* error calling poll */ return -2; } else { /* pollres = 0 means timeout */ nread = 0; } } if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) { return -2; } if ((nread > 0) || ((nread == 0) && (len == 0))) { /* some data has been read, or no data was requested */ return nread; } if (nread < 0) { /* socket error - check errno */ #if defined(_WIN32) if (err == WSAEWOULDBLOCK) { /* TODO (low): check if this is still required */ /* standard case if called from close_socket_gracefully */ return -2; } else if (err == WSAETIMEDOUT) { /* TODO (low): check if this is still required */ /* timeout is handled by the while loop */ return 0; } else if (err == WSAECONNABORTED) { /* See https://www.chilkatsoft.com/p/p_299.asp */ return -2; } else { DEBUG_TRACE("recv() failed, error %d", err); return -2; } #else /* TODO: POSIX returns either EAGAIN or EWOULDBLOCK in both cases, * if the timeout is reached and if the socket was set to non- * blocking in close_socket_gracefully, so we can not distinguish * here. We have to wait for the timeout in both cases for now. */ if (ERROR_TRY_AGAIN(err)) { /* TODO (low): check if this is still required */ /* EAGAIN/EWOULDBLOCK: * standard case if called from close_socket_gracefully * => should return -1 */ /* or timeout occurred * => the code must stay in the while loop */ /* EINTR can be generated on a socket with a timeout set even * when SA_RESTART is effective for all relevant signals * (see signal(7)). * => stay in the while loop */ } else { DEBUG_TRACE("recv() failed, error %d", err); return -2; } #endif } /* Timeout occurred, but no data available. */ return -1; } static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len) { int n, nread = 0; double timeout = -1.0; uint64_t start_time = 0, now = 0, timeout_ns = 0; if (conn->dom_ctx->config[REQUEST_TIMEOUT]) { timeout = atoi(conn->dom_ctx->config[REQUEST_TIMEOUT]) / 1000.0; } if (timeout <= 0.0) { timeout = strtod(config_options[REQUEST_TIMEOUT].default_value, NULL) / 1000.0; } start_time = mg_get_current_time_ns(); timeout_ns = (uint64_t)(timeout * 1.0E9); while ((len > 0) && STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) { n = pull_inner(fp, conn, buf + nread, len, timeout); if (n == -2) { if (nread == 0) { nread = -1; /* Propagate the error */ } break; } else if (n == -1) { /* timeout */ if (timeout >= 0.0) { now = mg_get_current_time_ns(); if ((now - start_time) <= timeout_ns) { continue; } } break; } else if (n == 0) { break; /* No more data to read */ } else { nread += n; len -= n; } } return nread; } static void discard_unread_request_data(struct mg_connection *conn) { char buf[MG_BUF_LEN]; while (mg_read(conn, buf, sizeof(buf)) > 0) ; } static int mg_read_inner(struct mg_connection *conn, void *buf, size_t len) { int64_t content_len, n, buffered_len, nread; int64_t len64 = (int64_t)((len > INT_MAX) ? INT_MAX : len); /* since the return value is * int, we may not read more * bytes */ const char *body; if (conn == NULL) { return 0; } /* If Content-Length is not set for a response with body data, * we do not know in advance how much data should be read. */ content_len = conn->content_len; if (content_len < 0) { /* The body data is completed when the connection is closed. */ content_len = INT64_MAX; } nread = 0; if (conn->consumed_content < content_len) { /* Adjust number of bytes to read. */ int64_t left_to_read = content_len - conn->consumed_content; if (left_to_read < len64) { /* Do not read more than the total content length of the * request. */ len64 = left_to_read; } /* Return buffered data */ buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len - conn->consumed_content; if (buffered_len > 0) { if (len64 < buffered_len) { buffered_len = len64; } body = conn->buf + conn->request_len + conn->consumed_content; memcpy(buf, body, (size_t)buffered_len); len64 -= buffered_len; conn->consumed_content += buffered_len; nread += buffered_len; buf = (char *)buf + buffered_len; } /* We have returned all buffered data. Read new data from the remote * socket. */ if ((n = pull_all(NULL, conn, (char *)buf, (int)len64)) >= 0) { conn->consumed_content += n; nread += n; } else { nread = ((nread > 0) ? nread : n); } } return (int)nread; } /* Forward declarations */ static void handle_request(struct mg_connection *); static void log_access(const struct mg_connection *); /* Handle request, update statistics and call access log */ static void handle_request_stat_log(struct mg_connection *conn) { #if defined(USE_SERVER_STATS) struct timespec tnow; conn->conn_state = 4; /* processing */ #endif handle_request(conn); #if defined(USE_SERVER_STATS) conn->conn_state = 5; /* processed */ clock_gettime(CLOCK_MONOTONIC, &tnow); conn->processing_time = mg_difftimespec(&tnow, &(conn->req_time)); mg_atomic_add64(&(conn->phys_ctx->total_data_read), conn->consumed_content); mg_atomic_add64(&(conn->phys_ctx->total_data_written), conn->num_bytes_sent); #endif DEBUG_TRACE("%s", "handle_request done"); if (conn->phys_ctx->callbacks.end_request != NULL) { conn->phys_ctx->callbacks.end_request(conn, conn->status_code); DEBUG_TRACE("%s", "end_request callback done"); } log_access(conn); } #if defined(USE_HTTP2) #if defined(NO_SSL) #error "HTTP2 requires ALPN, ALPN requires SSL/TLS" #endif #define USE_ALPN #include "http2.h" /* Not supported with HTTP/2 */ #define HTTP1_only \ { \ if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) { \ http2_must_use_http1(conn); \ DEBUG_TRACE("%s", "must use HTTP/1.x"); \ return; \ } \ } #else #define HTTP1_only #endif CIVETWEB_API int mg_read(struct mg_connection *conn, void *buf, size_t len) { if (len > INT_MAX) { len = INT_MAX; } if (conn == NULL) { return 0; } if (conn->is_chunked) { size_t all_read = 0; while (len > 0) { if (conn->is_chunked >= 3) { /* No more data left to read */ return 0; } if (conn->is_chunked != 1) { /* Has error */ return -1; } if (conn->consumed_content != conn->content_len) { /* copy from the current chunk */ int read_ret = mg_read_inner(conn, (char *)buf + all_read, len); if (read_ret < 1) { /* read error */ conn->is_chunked = 2; return -1; } all_read += (size_t)read_ret; len -= (size_t)read_ret; if (conn->consumed_content == conn->content_len) { /* Add data bytes in the current chunk have been read, * so we are expecting \r\n now. */ char x[2]; conn->content_len += 2; if ((mg_read_inner(conn, x, 2) != 2) || (x[0] != '\r') || (x[1] != '\n')) { /* Protocol violation */ conn->is_chunked = 2; return -1; } } } else { /* fetch a new chunk */ size_t i; char lenbuf[64]; char *end = NULL; unsigned long chunkSize = 0; for (i = 0; i < (sizeof(lenbuf) - 1); i++) { conn->content_len++; if (mg_read_inner(conn, lenbuf + i, 1) != 1) { lenbuf[i] = 0; } if ((i > 0) && (lenbuf[i] == ';')) { // chunk extension --> skip chars until next CR // // RFC 2616, 3.6.1 Chunked Transfer Coding // (https://www.rfc-editor.org/rfc/rfc2616#page-25) // // chunk = chunk-size [ chunk-extension ] CRLF // chunk-data CRLF // ... // chunk-extension= *( ";" chunk-ext-name [ "=" // chunk-ext-val ] ) do ++conn->content_len; while (mg_read_inner(conn, lenbuf + i, 1) == 1 && lenbuf[i] != '\r'); } if ((i > 0) && (lenbuf[i] == '\r') && (lenbuf[i - 1] != '\r')) { continue; } if ((i > 1) && (lenbuf[i] == '\n') && (lenbuf[i - 1] == '\r')) { lenbuf[i + 1] = 0; chunkSize = strtoul(lenbuf, &end, 16); if (chunkSize == 0) { /* regular end of content */ conn->is_chunked = 3; } break; } if (!isxdigit((unsigned char)lenbuf[i])) { /* illegal character for chunk length */ conn->is_chunked = 2; return -1; } } if ((end == NULL) || (*end != '\r')) { /* chunksize not set correctly */ conn->is_chunked = 2; return -1; } if (conn->is_chunked == 3) { /* try discarding trailer for keep-alive */ // We found the last chunk (length 0) including the // CRLF that terminates that chunk. Now follows a possibly // empty trailer and a final CRLF. // // see RFC 2616, 3.6.1 Chunked Transfer Coding // (https://www.rfc-editor.org/rfc/rfc2616#page-25) // // Chunked-Body = *chunk // last-chunk // trailer // CRLF // ... // last-chunk = 1*("0") [ chunk-extension ] CRLF // ... // trailer = *(entity-header CRLF) int crlf_count = 2; // one CRLF already determined while (crlf_count < 4 && conn->is_chunked == 3) { ++conn->content_len; if (mg_read_inner(conn, lenbuf, 1) == 1) { if ((crlf_count == 0 || crlf_count == 2)) { if (lenbuf[0] == '\r') ++crlf_count; else crlf_count = 0; } else { // previous character was a CR // --> next character must be LF if (lenbuf[0] == '\n') ++crlf_count; else conn->is_chunked = 2; } } else // premature end of trailer conn->is_chunked = 2; } if (conn->is_chunked == 2) return -1; else conn->is_chunked = 4; break; } /* append a new chunk */ conn->content_len += (int64_t)chunkSize; } } return (int)all_read; } return mg_read_inner(conn, buf, len); } CIVETWEB_API int mg_write(struct mg_connection *conn, const void *buf, size_t len) { time_t now; int n, total, allowed; if (conn == NULL) { return 0; } if (len > INT_MAX) { return -1; } /* Mark connection as "data sent" */ conn->request_state = 10; #if defined(USE_HTTP2) if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) { http2_data_frame_head(conn, len, 0); } #endif if (conn->throttle > 0) { if ((now = time(NULL)) != conn->last_throttle_time) { conn->last_throttle_time = now; conn->last_throttle_bytes = 0; } allowed = conn->throttle - conn->last_throttle_bytes; if (allowed > (int)len) { allowed = (int)len; } total = push_all(conn->phys_ctx, NULL, conn->client.sock, conn->ssl, (const char *)buf, allowed); if (total == allowed) { buf = (const char *)buf + total; conn->last_throttle_bytes += total; while ((total < (int)len) && STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) { allowed = (conn->throttle > ((int)len - total)) ? (int)len - total : conn->throttle; n = push_all(conn->phys_ctx, NULL, conn->client.sock, conn->ssl, (const char *)buf, allowed); if (n != allowed) { break; } sleep(1); conn->last_throttle_bytes = allowed; conn->last_throttle_time = time(NULL); buf = (const char *)buf + n; total += n; } } } else { total = push_all(conn->phys_ctx, NULL, conn->client.sock, conn->ssl, (const char *)buf, (int)len); } if (total > 0) { conn->num_bytes_sent += total; } return total; } /* Send a chunk, if "Transfer-Encoding: chunked" is used */ CIVETWEB_API int mg_send_chunk(struct mg_connection *conn, const char *chunk, unsigned int chunk_len) { char lenbuf[16]; size_t lenbuf_len; int ret; int t; /* First store the length information in a text buffer. */ snprintf(lenbuf, sizeof(lenbuf), "%x\r\n", chunk_len); lenbuf_len = strlen(lenbuf); /* Then send length information, chunk and terminating \r\n. */ ret = mg_write(conn, lenbuf, lenbuf_len); if (ret != (int)lenbuf_len) { return -1; } t = ret; ret = mg_write(conn, chunk, chunk_len); if (ret != (int)chunk_len) { return -1; } t += ret; ret = mg_write(conn, "\r\n", 2); if (ret != 2) { return -1; } t += ret; return t; } #if defined(GCC_DIAGNOSTIC) /* This block forwards format strings to printf implementations, * so we need to disable the format-nonliteral warning. */ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif /* Alternative alloc_vprintf() for non-compliant C runtimes */ static int alloc_vprintf2(char **buf, const char *fmt, va_list ap) { va_list ap_copy; size_t size = MG_BUF_LEN / 4; int len = -1; *buf = NULL; while (len < 0) { if (*buf) { mg_free(*buf); } size *= 4; *buf = (char *)mg_malloc(size); if (!*buf) { break; } va_copy(ap_copy, ap); len = vsnprintf_impl(*buf, size - 1, fmt, ap_copy); va_end(ap_copy); (*buf)[size - 1] = 0; } return len; } /* Print message to buffer. If buffer is large enough to hold the message, * return buffer. If buffer is to small, allocate large enough buffer on * heap, * and return allocated buffer. */ static int alloc_vprintf(char **out_buf, char *prealloc_buf, size_t prealloc_size, const char *fmt, va_list ap) { va_list ap_copy; int len; /* Windows is not standard-compliant, and vsnprintf() returns -1 if * buffer is too small. Also, older versions of msvcrt.dll do not have * _vscprintf(). However, if size is 0, vsnprintf() behaves correctly. * Therefore, we make two passes: on first pass, get required message * length. * On second pass, actually print the message. */ va_copy(ap_copy, ap); len = vsnprintf_impl(NULL, 0, fmt, ap_copy); va_end(ap_copy); if (len < 0) { /* C runtime is not standard compliant, vsnprintf() returned -1. * Switch to alternative code path that uses incremental * allocations. */ va_copy(ap_copy, ap); len = alloc_vprintf2(out_buf, fmt, ap_copy); va_end(ap_copy); } else if ((size_t)(len) >= prealloc_size) { /* The pre-allocated buffer not large enough. */ /* Allocate a new buffer. */ *out_buf = (char *)mg_malloc((size_t)(len) + 1); if (!*out_buf) { /* Allocation failed. Return -1 as "out of memory" error. */ return -1; } /* Buffer allocation successful. Store the string there. */ va_copy(ap_copy, ap); IGNORE_UNUSED_RESULT( vsnprintf_impl(*out_buf, (size_t)(len) + 1, fmt, ap_copy)); va_end(ap_copy); } else { /* The pre-allocated buffer is large enough. * Use it to store the string and return the address. */ va_copy(ap_copy, ap); IGNORE_UNUSED_RESULT( vsnprintf_impl(prealloc_buf, prealloc_size, fmt, ap_copy)); va_end(ap_copy); *out_buf = prealloc_buf; } return len; } static int alloc_printf(char **out_buf, const char *fmt, ...) { va_list ap; int result; va_start(ap, fmt); result = alloc_vprintf(out_buf, NULL, 0, fmt, ap); va_end(ap); return result; } #if defined(GCC_DIAGNOSTIC) /* Enable format-nonliteral warning again. */ # pragma GCC diagnostic pop #endif static int mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap) { char mem[MG_BUF_LEN]; char *buf = NULL; int len; if ((len = alloc_vprintf(&buf, mem, sizeof(mem), fmt, ap)) > 0) { len = mg_write(conn, buf, (size_t)len); } if (buf != mem) { mg_free(buf); } return len; } CIVETWEB_API int mg_printf(struct mg_connection *conn, const char *fmt, ...) { va_list ap; int result; va_start(ap, fmt); result = mg_vprintf(conn, fmt, ap); va_end(ap); return result; } CIVETWEB_API int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded) { int i, j, a, b; #define HEXTOI(x) (isdigit(x) ? (x - '0') : (x - 'W')) for (i = j = 0; (i < src_len) && (j < (dst_len - 1)); i++, j++) { if ((i < src_len - 2) && (src[i] == '%') && isxdigit((unsigned char)src[i + 1]) && isxdigit((unsigned char)src[i + 2])) { a = tolower((unsigned char)src[i + 1]); b = tolower((unsigned char)src[i + 2]); dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b)); i += 2; } else if (is_form_url_encoded && (src[i] == '+')) { dst[j] = ' '; } else { dst[j] = src[i]; } } dst[j] = '\0'; /* Null-terminate the destination */ return (i >= src_len) ? j : -1; } /* form url decoding of an entire string */ static void url_decode_in_place(char *buf) { int len = (int)strlen(buf); (void)mg_url_decode(buf, len, buf, len + 1, 1); } CIVETWEB_API int mg_get_var(const char *data, size_t data_len, const char *name, char *dst, size_t dst_len) { return mg_get_var2(data, data_len, name, dst, dst_len, 0); } CIVETWEB_API int mg_get_var2(const char *data, size_t data_len, const char *name, char *dst, size_t dst_len, size_t occurrence) { const char *p, *e, *s; size_t name_len; int len; if ((dst == NULL) || (dst_len == 0)) { len = -2; } else if ((data == NULL) || (name == NULL) || (data_len == 0)) { len = -1; dst[0] = '\0'; } else { name_len = strlen(name); e = data + data_len; len = -1; dst[0] = '\0'; /* data is "var1=val1&var2=val2...". Find variable first */ for (p = data; p + name_len < e; p++) { if (((p == data) || (p[-1] == '&')) && (p[name_len] == '=') && !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) { /* Point p to variable value */ p += name_len + 1; /* Point s to the end of the value */ s = (const char *)memchr(p, '&', (size_t)(e - p)); if (s == NULL) { s = e; } DEBUG_ASSERT(s >= p); if (s < p) { return -3; } /* Decode variable into destination buffer */ len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1); /* Redirect error code from -1 to -2 (destination buffer too * small). */ if (len == -1) { len = -2; } break; } } } return len; } /* split a string "key1=val1&key2=val2" into key/value pairs */ CIVETWEB_API int mg_split_form_urlencoded(char *data, struct mg_header *form_fields, unsigned num_form_fields) { char *b; int i; int num = 0; if (data == NULL) { /* parameter error */ return -1; } if ((form_fields == NULL) && (num_form_fields == 0)) { /* determine the number of expected fields */ if (data[0] == 0) { return 0; } /* count number of & to return the number of key-value-pairs */ num = 1; while (*data) { if (*data == '&') { num++; } data++; } return num; } if ((form_fields == NULL) || ((int)num_form_fields <= 0)) { /* parameter error */ return -1; } for (i = 0; i < (int)num_form_fields; i++) { /* extract key-value pairs from input data */ while ((*data == ' ') || (*data == '\t')) { /* skip initial spaces */ data++; } if (*data == 0) { /* end of string reached */ break; } form_fields[num].name = data; /* find & or = */ b = data; while ((*b != 0) && (*b != '&') && (*b != '=')) { b++; } if (*b == 0) { /* last key without value */ form_fields[num].value = NULL; } else if (*b == '&') { /* mid key without value */ form_fields[num].value = NULL; } else { /* terminate string */ *b = 0; /* value starts after '=' */ data = b + 1; form_fields[num].value = data; } /* new field is stored */ num++; /* find a next key */ b = strchr(data, '&'); if (b == 0) { /* no more data */ break; } else { /* terminate value of last field at '&' */ *b = 0; /* next key-value-pairs starts after '&' */ data = b + 1; } } /* Decode all values */ for (i = 0; i < num; i++) { if (form_fields[i].name) { url_decode_in_place((char *)form_fields[i].name); } if (form_fields[i].value) { url_decode_in_place((char *)form_fields[i].value); } } /* return number of fields found */ return num; } /* HCP24: some changes to compare whole var_name */ CIVETWEB_API int mg_get_cookie(const char *cookie_header, const char *var_name, char *dst, size_t dst_size) { const char *s, *p, *end; int name_len, len = -1; if ((dst == NULL) || (dst_size == 0)) { return -2; } dst[0] = '\0'; if ((var_name == NULL) || ((s = cookie_header) == NULL)) { return -1; } name_len = (int)strlen(var_name); end = s + strlen(s); for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) { if (s[name_len] == '=') { /* HCP24: now check is it a substring or a full cookie name */ if ((s == cookie_header) || (s[-1] == ' ')) { s += name_len + 1; if ((p = strchr(s, ' ')) == NULL) { p = end; } if (p[-1] == ';') { p--; } if ((*s == '"') && (p[-1] == '"') && (p > s + 1)) { s++; p--; } if ((size_t)(p - s) < dst_size) { len = (int)(p - s); mg_strlcpy(dst, s, (size_t)len + 1); } else { len = -3; } break; } } } return len; } CIVETWEB_API int mg_base64_encode(const unsigned char *src, size_t src_len, char *dst, size_t *dst_len) { static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; size_t i, j; int a, b, c; if (dst_len != NULL) { /* Expected length including 0 termination: */ /* IN 1 -> OUT 5, IN 2 -> OUT 5, IN 3 -> OUT 5, IN 4 -> OUT 9, * IN 5 -> OUT 9, IN 6 -> OUT 9, IN 7 -> OUT 13, etc. */ size_t expected_len = ((src_len + 2) / 3) * 4 + 1; if (*dst_len < expected_len) { if (*dst_len > 0) { dst[0] = '\0'; } *dst_len = expected_len; return 0; } } for (i = j = 0; i < src_len; i += 3) { a = src[i]; b = ((i + 1) >= src_len) ? 0 : src[i + 1]; c = ((i + 2) >= src_len) ? 0 : src[i + 2]; dst[j++] = b64[a >> 2]; dst[j++] = b64[((a & 3) << 4) | (b >> 4)]; if (i + 1 < src_len) { dst[j++] = b64[(b & 15) << 2 | (c >> 6)]; } if (i + 2 < src_len) { dst[j++] = b64[c & 63]; } } while (j % 4 != 0) { dst[j++] = '='; } dst[j++] = '\0'; if (dst_len != NULL) { *dst_len = (size_t)j; } /* Return -1 for "OK" */ return -1; } static unsigned char b64reverse(char letter) { if ((letter >= 'A') && (letter <= 'Z')) { return (unsigned char)(letter - 'A'); } if ((letter >= 'a') && (letter <= 'z')) { return (unsigned char)(letter - 'a' + 26); } if ((letter >= '0') && (letter <= '9')) { return (unsigned char)(letter - '0' + 52); } if (letter == '+') { return 62; } if (letter == '/') { return 63; } if (letter == '=') { return 255; /* normal end */ } return 254; /* error */ } CIVETWEB_API int mg_base64_decode(const char *src, size_t src_len, unsigned char *dst, size_t *dst_len) { size_t i; unsigned char a, b, c, d; size_t dst_len_limit = (size_t)-1; size_t dst_len_used = 0; if (dst_len != NULL) { dst_len_limit = *dst_len; *dst_len = 0; } for (i = 0; i < src_len; i += 4) { /* Read 4 characters from BASE64 string */ a = b64reverse(src[i]); if (a >= 254) { return (int)i; } b = b64reverse(((i + 1) >= src_len) ? 0 : src[i + 1]); if (b >= 254) { return (int)i + 1; } c = b64reverse(((i + 2) >= src_len) ? 0 : src[i + 2]); if (c == 254) { return (int)i + 2; } d = b64reverse(((i + 3) >= src_len) ? 0 : src[i + 3]); if (d == 254) { return (int)i + 3; } /* Add first (of 3) decoded character */ if (dst_len_used < dst_len_limit) { dst[dst_len_used] = (unsigned char)((unsigned char)(a << 2) + (unsigned char)(b >> 4)); } dst_len_used++; if (c != 255) { if (dst_len_used < dst_len_limit) { dst[dst_len_used] = (unsigned char)((unsigned char)(b << 4) + (unsigned char)(c >> 2)); } dst_len_used++; if (d != 255) { if (dst_len_used < dst_len_limit) { dst[dst_len_used] = (unsigned char)((unsigned char)(c << 6) + d); } dst_len_used++; } } } /* Add terminating zero */ if (dst_len_used < dst_len_limit) { dst[dst_len_used] = '\0'; } dst_len_used++; if (dst_len != NULL) { *dst_len = dst_len_used; } if (dst_len_used > dst_len_limit) { /* Out of memory */ return 0; } /* Return -1 for "OK" */ return -1; } static int is_put_or_delete_method(const struct mg_connection *conn) { if (conn) { const char *s = conn->request_info.request_method; if (s != NULL) { /* PUT, DELETE, MKCOL, PATCH, LOCK, UNLOCK, PROPPATCH, MOVE, COPY */ return (!strcmp(s, "PUT") || !strcmp(s, "DELETE") || !strcmp(s, "MKCOL") || !strcmp(s, "PATCH") || !strcmp(s, "LOCK") || !strcmp(s, "UNLOCK") || !strcmp(s, "PROPPATCH") || !strcmp(s, "MOVE") || !strcmp(s, "COPY")); } } return 0; } static int is_civetweb_webdav_method(const struct mg_connection *conn) { /* Note: Here we only have to identify the WebDav methods that need special * handling in the CivetWeb code - not all methods used in WebDav. In * particular, methods used on directories (when using Windows Explorer as * WebDav client). */ if (conn) { const char *s = conn->request_info.request_method; if (s != NULL) { /* These are the civetweb builtin DAV methods */ return (!strcmp(s, "PROPFIND") || !strcmp(s, "PROPPATCH") || !strcmp(s, "LOCK") || !strcmp(s, "UNLOCK") || !strcmp(s, "MOVE") || !strcmp(s, "COPY")); } } return 0; } #if !defined(NO_FILES) static int extention_matches_script( struct mg_connection *conn, /* in: request (must be valid) */ const char *filename /* in: filename (must be valid) */ ) { #if !defined(NO_CGI) int cgi_config_idx, inc, max; #endif #if defined(USE_LUA) if (match_prefix_strlen(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS], filename) > 0) { return 1; } #endif #if defined(USE_DUKTAPE) if (match_prefix_strlen(conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS], filename) > 0) { return 1; } #endif #if !defined(NO_CGI) inc = CGI2_EXTENSIONS - CGI_EXTENSIONS; max = PUT_DELETE_PASSWORDS_FILE - CGI_EXTENSIONS; for (cgi_config_idx = 0; cgi_config_idx < max; cgi_config_idx += inc) { if ((conn->dom_ctx->config[CGI_EXTENSIONS + cgi_config_idx] != NULL) && (match_prefix_strlen( conn->dom_ctx->config[CGI_EXTENSIONS + cgi_config_idx], filename) > 0)) { return 1; } } #endif /* filename and conn could be unused, if all preocessor conditions * are false (no script language supported). */ (void)filename; (void)conn; return 0; } static int extention_matches_template_text( struct mg_connection *conn, /* in: request (must be valid) */ const char *filename /* in: filename (must be valid) */ ) { #if defined(USE_LUA) if (match_prefix_strlen(conn->dom_ctx->config[LUA_SERVER_PAGE_EXTENSIONS], filename) > 0) { return 1; } #endif if (match_prefix_strlen(conn->dom_ctx->config[SSI_EXTENSIONS], filename) > 0) { return 1; } return 0; } /* For given directory path, substitute it to valid index file. * Return 1 if index file has been found, 0 if not found. * If the file is found, it's stats is returned in stp. */ static int substitute_index_file(struct mg_connection *conn, char *path, size_t path_len, struct mg_file_stat *filestat) { const char *list = conn->dom_ctx->config[INDEX_FILES]; struct vec filename_vec; size_t n = strlen(path); int found = 0; /* The 'path' given to us points to the directory. Remove all trailing * directory separator characters from the end of the path, and * then append single directory separator character. */ while ((n > 0) && (path[n - 1] == '/')) { n--; } path[n] = '/'; /* Traverse index files list. For each entry, append it to the given * path and see if the file exists. If it exists, break the loop */ while ((list = next_option(list, &filename_vec, NULL)) != NULL) { /* Ignore too long entries that may overflow path buffer */ if ((filename_vec.len + 1) > (path_len - (n + 1))) { continue; } /* Prepare full path to the index file */ mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1); /* Does it exist? */ if (mg_stat(conn, path, filestat)) { /* Yes it does, break the loop */ found = 1; break; } } /* If no index file exists, restore directory path */ if (!found) { path[n] = '\0'; } return found; } #endif static void interpret_uri(struct mg_connection *conn, /* in/out: request (must be valid) */ char *filename, /* out: filename */ size_t filename_buf_len, /* in: size of filename buffer */ struct mg_file_stat *filestat, /* out: file status structure */ int *is_found, /* out: file found (directly) */ int *is_script_resource, /* out: handled by a script? */ int *is_websocket_request, /* out: websocket connection? */ int *is_put_or_delete_request, /* out: put/delete a file? */ int *is_webdav_request, /* out: webdav request? */ int *is_template_text /* out: SSI file or LSP file? */ ) { char const *accept_encoding; #if !defined(NO_FILES) const char *uri = conn->request_info.local_uri; const char *root = conn->dom_ctx->config[DOCUMENT_ROOT]; const char *rewrite; struct vec a, b; ptrdiff_t match_len; char gz_path[UTF8_PATH_MAX]; int truncated; #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) char *tmp_str; size_t tmp_str_len, sep_pos; int allow_substitute_script_subresources; #endif #else (void)filename_buf_len; /* unused if NO_FILES is defined */ #endif /* Step 1: Set all initially unknown outputs to zero */ memset(filestat, 0, sizeof(*filestat)); *filename = 0; *is_found = 0; *is_script_resource = 0; *is_template_text = 0; /* Step 2: Classify the request method */ /* Step 2a: Check if the request attempts to modify the file system */ *is_put_or_delete_request = is_put_or_delete_method(conn); /* Step 2b: Check if the request uses WebDav method that requires special * handling */ *is_webdav_request = is_civetweb_webdav_method(conn); /* Step 3: Check if it is a websocket request, and modify the document * root if required */ #if defined(USE_WEBSOCKET) *is_websocket_request = (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET); #if !defined(NO_FILES) if ((*is_websocket_request) && conn->dom_ctx->config[WEBSOCKET_ROOT]) { root = conn->dom_ctx->config[WEBSOCKET_ROOT]; } #endif /* !NO_FILES */ #else /* USE_WEBSOCKET */ *is_websocket_request = 0; #endif /* USE_WEBSOCKET */ /* Step 4: Check if gzip encoded response is allowed */ conn->accept_gzip = 0; if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) { if (strstr(accept_encoding, "gzip") != NULL) { conn->accept_gzip = 1; } } #if !defined(NO_FILES) /* Step 5: If there is no root directory, don't look for files. */ /* Note that root == NULL is a regular use case here. This occurs, * if all requests are handled by callbacks, so the WEBSOCKET_ROOT * config is not required. */ if (root == NULL) { /* all file related outputs have already been set to 0, just return */ return; } /* Step 6: Determine the local file path from the root path and the * request uri. */ /* Using filename_buf_len - 1 because memmove() for PATH_INFO may shift * part of the path one byte on the right. */ truncated = 0; mg_snprintf( conn, &truncated, filename, filename_buf_len - 1, "%s%s", root, uri); if (truncated) { goto interpret_cleanup; } /* Step 7: URI rewriting */ rewrite = conn->dom_ctx->config[URL_REWRITE_PATTERN]; while ((rewrite = next_option(rewrite, &a, &b)) != NULL) { if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) { mg_snprintf(conn, &truncated, filename, filename_buf_len - 1, "%.*s%s", (int)b.len, b.ptr, uri + match_len); break; } } if (truncated) { goto interpret_cleanup; } /* Step 8: Check if the file exists at the server */ /* Local file path and name, corresponding to requested URI * is now stored in "filename" variable. */ if (mg_stat(conn, filename, filestat)) { int uri_len = (int)strlen(uri); int is_uri_end_slash = (uri_len > 0) && (uri[uri_len - 1] == '/'); /* 8.1: File exists. */ *is_found = 1; /* 8.2: Check if it is a script type. */ if (extention_matches_script(conn, filename)) { /* The request addresses a CGI resource, Lua script or * server-side javascript. * The URI corresponds to the script itself (like * /path/script.cgi), and there is no additional resource * path (like /path/script.cgi/something). * Requests that modify (replace or delete) a resource, like * PUT and DELETE requests, should replace/delete the script * file. * Requests that read or write from/to a resource, like GET and * POST requests, should call the script and return the * generated response. */ *is_script_resource = (!*is_put_or_delete_request); } /* 8.3: Check for SSI and LSP files */ if (extention_matches_template_text(conn, filename)) { /* Same as above, but for *.lsp and *.shtml files. */ /* A "template text" is a file delivered directly to the client, * but with some text tags replaced by dynamic content. * E.g. a Server Side Include (SSI) or Lua Page/Lua Server Page * (LP, LSP) file. */ *is_template_text = (!*is_put_or_delete_request); } /* 8.4: If the request target is a directory, there could be * a substitute file (index.html, index.cgi, ...). */ /* But do not substitute a directory for a WebDav request */ if (filestat->is_directory && is_uri_end_slash && (!*is_webdav_request)) { /* Use a local copy here, since substitute_index_file will * change the content of the file status */ struct mg_file_stat tmp_filestat; memset(&tmp_filestat, 0, sizeof(tmp_filestat)); if (substitute_index_file( conn, filename, filename_buf_len, &tmp_filestat)) { /* Substitute file found. Copy stat to the output, then * check if the file is a script file */ *filestat = tmp_filestat; if (extention_matches_script(conn, filename)) { /* Substitute file is a script file */ *is_script_resource = 1; } else if (extention_matches_template_text(conn, filename)) { /* Substitute file is a LSP or SSI file */ *is_template_text = 1; } else { /* Substitute file is a regular file */ *is_script_resource = 0; *is_found = (mg_stat(conn, filename, filestat) ? 1 : 0); } } /* If there is no substitute file, the server could return * a directory listing in a later step */ } return; } /* Step 9: Check for zipped files: */ /* If we can't find the actual file, look for the file * with the same name but a .gz extension. If we find it, * use that and set the gzipped flag in the file struct * to indicate that the response need to have the content- * encoding: gzip header. * We can only do this if the browser declares support. */ if (conn->accept_gzip) { mg_snprintf( conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", filename); if (truncated) { goto interpret_cleanup; } if (mg_stat(conn, gz_path, filestat)) { if (filestat) { filestat->is_gzipped = 1; *is_found = 1; } /* Currently gz files can not be scripts. */ return; } } #if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) /* Step 10: Script resources may handle sub-resources */ /* Support PATH_INFO for CGI scripts. */ tmp_str_len = strlen(filename); tmp_str = (char *)mg_malloc_ctx(tmp_str_len + UTF8_PATH_MAX + 1, conn->phys_ctx); if (!tmp_str) { /* Out of memory */ goto interpret_cleanup; } memcpy(tmp_str, filename, tmp_str_len + 1); /* Check config, if index scripts may have sub-resources */ allow_substitute_script_subresources = !mg_strcasecmp(conn->dom_ctx->config[ALLOW_INDEX_SCRIPT_SUB_RES], "yes"); if (*is_webdav_request) { /* TO BE DEFINED: Should scripts handle special WebDAV methods lile * PROPFIND for their subresources? */ /* allow_substitute_script_subresources = 0; */ } sep_pos = tmp_str_len; while (sep_pos > 0) { sep_pos--; if (tmp_str[sep_pos] == '/') { int is_script = 0, does_exist = 0; tmp_str[sep_pos] = 0; if (tmp_str[0]) { is_script = extention_matches_script(conn, tmp_str); does_exist = mg_stat(conn, tmp_str, filestat); } if (does_exist && is_script) { filename[sep_pos] = 0; memmove(filename + sep_pos + 2, filename + sep_pos + 1, strlen(filename + sep_pos + 1) + 1); conn->path_info = filename + sep_pos + 1; filename[sep_pos + 1] = '/'; *is_script_resource = 1; *is_found = 1; break; } if (allow_substitute_script_subresources) { if (substitute_index_file( conn, tmp_str, tmp_str_len + UTF8_PATH_MAX, filestat)) { /* some intermediate directory has an index file */ if (extention_matches_script(conn, tmp_str)) { size_t script_name_len = strlen(tmp_str); /* subres_name read before this memory locatio will be overwritten */ char *subres_name = filename + sep_pos; size_t subres_name_len = strlen(subres_name); DEBUG_TRACE("Substitute script %s serving path %s", tmp_str, filename); /* this index file is a script */ if ((script_name_len + subres_name_len + 2) >= filename_buf_len) { mg_free(tmp_str); goto interpret_cleanup; } conn->path_info = filename + script_name_len + 1; /* new target */ memmove(conn->path_info, subres_name, subres_name_len); conn->path_info[subres_name_len] = 0; memcpy(filename, tmp_str, script_name_len + 1); *is_script_resource = 1; *is_found = 1; break; } else { DEBUG_TRACE("Substitute file %s serving path %s", tmp_str, filename); /* non-script files will not have sub-resources */ filename[sep_pos] = 0; conn->path_info = 0; *is_script_resource = 0; *is_found = 0; break; } } } tmp_str[sep_pos] = '/'; } } mg_free(tmp_str); #endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */ #endif /* !defined(NO_FILES) */ return; #if !defined(NO_FILES) /* Reset all outputs */ interpret_cleanup: memset(filestat, 0, sizeof(*filestat)); *filename = 0; *is_found = 0; *is_script_resource = 0; *is_websocket_request = 0; *is_put_or_delete_request = 0; #endif /* !defined(NO_FILES) */ } /* Check whether full request is buffered. Return: * -1 if request or response is malformed * 0 if request or response is not yet fully buffered * >0 actual request length, including last \r\n\r\n */ static int get_http_header_len(const char *buf, int buflen) { int i; for (i = 0; i < buflen; i++) { /* Do an unsigned comparison in some conditions below */ const unsigned char c = (unsigned char)buf[i]; if ((c < 128) && ((char)c != '\r') && ((char)c != '\n') && !isprint(c)) { /* abort scan as soon as one malformed character is found */ return -1; } if (i < buflen - 1) { if ((buf[i] == '\n') && (buf[i + 1] == '\n')) { /* Two newline, no carriage return - not standard compliant, * but it should be accepted */ return i + 2; } } if (i < buflen - 3) { if ((buf[i] == '\r') && (buf[i + 1] == '\n') && (buf[i + 2] == '\r') && (buf[i + 3] == '\n')) { /* Two \r\n - standard compliant */ return i + 4; } } } return 0; } #if !defined(NO_CACHING) /* Convert month to the month number. Return -1 on error, or month number */ static int get_month_index(const char *s) { size_t i; for (i = 0; i < ARRAY_SIZE(month_names); i++) { if (!strcmp(s, month_names[i])) { return (int)i; } } return -1; } /* Parse UTC date-time string, and return the corresponding time_t value. */ static time_t parse_date_string(const char *datetime) { char month_str[32] = {0}; int second, minute, hour, day, month, year; time_t result = (time_t)0; struct tm tm; if ((sscanf(datetime, "%d/%3s/%d %d:%d:%d", &day, month_str, &year, &hour, &minute, &second) == 6) || (sscanf(datetime, "%d %3s %d %d:%d:%d", &day, month_str, &year, &hour, &minute, &second) == 6) || (sscanf(datetime, "%*3s, %d %3s %d %d:%d:%d", &day, month_str, &year, &hour, &minute, &second) == 6) || (sscanf(datetime, "%d-%3s-%d %d:%d:%d", &day, month_str, &year, &hour, &minute, &second) == 6)) { month = get_month_index(month_str); if ((month >= 0) && (year >= 1970)) { memset(&tm, 0, sizeof(tm)); tm.tm_year = year - 1900; tm.tm_mon = month; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = minute; tm.tm_sec = second; result = timegm(&tm); } } return result; } #endif /* !NO_CACHING */ /* Pre-process URIs according to RFC + protect against directory disclosure * attacks by removing '..', excessive '/' and '\' characters */ static void remove_dot_segments(char *inout) { /* Windows backend protection * (https://tools.ietf.org/html/rfc3986#section-7.3): Replace backslash * in URI by slash */ char *out_end = inout; char *in = inout; if (!in) { /* Param error. */ return; } while (*in) { if (*in == '\\') { *in = '/'; } in++; } /* Algorithm "remove_dot_segments" from * https://tools.ietf.org/html/rfc3986#section-5.2.4 */ /* Step 1: * The input buffer is initialized. * The output buffer is initialized to the empty string. */ in = inout; /* Step 2: * While the input buffer is not empty, loop as follows: */ /* Less than out_end of the inout buffer is used as output, so keep * condition: out_end <= in */ while (*in) { /* Step 2a: * If the input buffer begins with a prefix of "../" or "./", * then remove that prefix from the input buffer; */ if (!strncmp(in, "../", 3)) { in += 3; } else if (!strncmp(in, "./", 2)) { in += 2; } /* otherwise */ /* Step 2b: * if the input buffer begins with a prefix of "/./" or "/.", * where "." is a complete path segment, then replace that * prefix with "/" in the input buffer; */ else if (!strncmp(in, "/./", 3)) { in += 2; } else if (!strcmp(in, "/.")) { in[1] = 0; } /* otherwise */ /* Step 2c: * if the input buffer begins with a prefix of "/../" or "/..", * where ".." is a complete path segment, then replace that * prefix with "/" in the input buffer and remove the last * segment and its preceding "/" (if any) from the output * buffer; */ else if (!strncmp(in, "/../", 4)) { in += 3; if (inout != out_end) { /* remove last segment */ do { out_end--; } while ((inout != out_end) && (*out_end != '/')); } } else if (!strcmp(in, "/..")) { in[1] = 0; if (inout != out_end) { /* remove last segment */ do { out_end--; } while ((inout != out_end) && (*out_end != '/')); } } /* otherwise */ /* Step 2d: * if the input buffer consists only of "." or "..", then remove * that from the input buffer; */ else if (!strcmp(in, ".") || !strcmp(in, "..")) { *in = 0; } /* otherwise */ /* Step 2e: * move the first path segment in the input buffer to the end of * the output buffer, including the initial "/" character (if * any) and any subsequent characters up to, but not including, * the next "/" character or the end of the input buffer. */ else { do { *out_end = *in; out_end++; in++; } while ((*in != 0) && (*in != '/')); } } /* Step 3: * Finally, the output buffer is returned as the result of * remove_dot_segments. */ /* Terminate output */ *out_end = 0; /* For Windows, the files/folders "x" and "x." (with a dot but without * extension) are identical. Replace all "./" by "/" and remove a "." at * the end. Also replace all "//" by "/". Repeat until there is no "./" * or "//" anymore. */ out_end = in = inout; while (*in) { if (*in == '.') { /* remove . at the end or preceding of / */ char *in_ahead = in; do { in_ahead++; } while (*in_ahead == '.'); if (*in_ahead == '/') { in = in_ahead; if ((out_end != inout) && (out_end[-1] == '/')) { /* remove generated // */ out_end--; } } else if (*in_ahead == 0) { in = in_ahead; } else { do { *out_end++ = '.'; in++; } while (in != in_ahead); } } else if (*in == '/') { /* replace // by / */ *out_end++ = '/'; do { in++; } while (*in == '/'); } else { *out_end++ = *in; in++; } } *out_end = 0; } static const struct { const char *extension; size_t ext_len; const char *mime_type; } builtin_mime_types[] = { /* IANA registered MIME types * (http://www.iana.org/assignments/media-types) * application types */ {".bin", 4, "application/octet-stream"}, {".deb", 4, "application/octet-stream"}, {".dmg", 4, "application/octet-stream"}, {".dll", 4, "application/octet-stream"}, {".doc", 4, "application/msword"}, {".eps", 4, "application/postscript"}, {".exe", 4, "application/octet-stream"}, {".iso", 4, "application/octet-stream"}, {".js", 3, "application/javascript"}, {".json", 5, "application/json"}, {".msi", 4, "application/octet-stream"}, {".pdf", 4, "application/pdf"}, {".ps", 3, "application/postscript"}, {".rtf", 4, "application/rtf"}, {".xhtml", 6, "application/xhtml+xml"}, {".xsl", 4, "application/xml"}, {".xslt", 5, "application/xml"}, /* fonts */ {".ttf", 4, "application/font-sfnt"}, {".cff", 4, "application/font-sfnt"}, {".otf", 4, "application/font-sfnt"}, {".aat", 4, "application/font-sfnt"}, {".sil", 4, "application/font-sfnt"}, {".pfr", 4, "application/font-tdpfr"}, {".woff", 5, "application/font-woff"}, {".woff2", 6, "application/font-woff2"}, /* audio */ {".mp3", 4, "audio/mpeg"}, {".oga", 4, "audio/ogg"}, {".ogg", 4, "audio/ogg"}, /* image */ {".gif", 4, "image/gif"}, {".ief", 4, "image/ief"}, {".jpeg", 5, "image/jpeg"}, {".jpg", 4, "image/jpeg"}, {".jpm", 4, "image/jpm"}, {".jpx", 4, "image/jpx"}, {".png", 4, "image/png"}, {".svg", 4, "image/svg+xml"}, {".tif", 4, "image/tiff"}, {".tiff", 5, "image/tiff"}, /* model */ {".wrl", 4, "model/vrml"}, /* text */ {".css", 4, "text/css"}, {".csv", 4, "text/csv"}, {".htm", 4, "text/html"}, {".html", 5, "text/html"}, {".sgm", 4, "text/sgml"}, {".shtm", 5, "text/html"}, {".shtml", 6, "text/html"}, {".txt", 4, "text/plain"}, {".xml", 4, "text/xml"}, /* video */ {".mov", 4, "video/quicktime"}, {".mp4", 4, "video/mp4"}, {".mpeg", 5, "video/mpeg"}, {".mpg", 4, "video/mpeg"}, {".ogv", 4, "video/ogg"}, {".qt", 3, "video/quicktime"}, /* not registered types * (http://reference.sitepoint.com/html/mime-types-full, * http://www.hansenb.pdx.edu/DMKB/dict/tutorials/mime_typ.php, ..) */ {".arj", 4, "application/x-arj-compressed"}, {".gz", 3, "application/x-gunzip"}, {".rar", 4, "application/x-arj-compressed"}, {".swf", 4, "application/x-shockwave-flash"}, {".tar", 4, "application/x-tar"}, {".tgz", 4, "application/x-tar-gz"}, {".torrent", 8, "application/x-bittorrent"}, {".ppt", 4, "application/x-mspowerpoint"}, {".xls", 4, "application/x-msexcel"}, {".zip", 4, "application/x-zip-compressed"}, {".aac", 4, "audio/aac"}, /* http://en.wikipedia.org/wiki/Advanced_Audio_Coding */ {".flac", 5, "audio/flac"}, {".aif", 4, "audio/x-aif"}, {".m3u", 4, "audio/x-mpegurl"}, {".mid", 4, "audio/x-midi"}, {".ra", 3, "audio/x-pn-realaudio"}, {".ram", 4, "audio/x-pn-realaudio"}, {".wav", 4, "audio/x-wav"}, {".bmp", 4, "image/bmp"}, {".ico", 4, "image/x-icon"}, {".pct", 4, "image/x-pct"}, {".pict", 5, "image/pict"}, {".rgb", 4, "image/x-rgb"}, {".webm", 5, "video/webm"}, /* http://en.wikipedia.org/wiki/WebM */ {".asf", 4, "video/x-ms-asf"}, {".avi", 4, "video/x-msvideo"}, {".m4v", 4, "video/x-m4v"}, {NULL, 0, NULL}}; CIVETWEB_API const char * mg_get_builtin_mime_type(const char *path) { const char *ext; size_t i, path_len; path_len = strlen(path); for (i = 0; builtin_mime_types[i].extension != NULL; i++) { ext = path + (path_len - builtin_mime_types[i].ext_len); if ((path_len > builtin_mime_types[i].ext_len) && (mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0)) { return builtin_mime_types[i].mime_type; } } return "text/plain"; } /* Look at the "path" extension and figure what mime type it has. * Store mime type in the vector. */ static void get_mime_type(struct mg_connection *conn, const char *path, struct vec *vec) { struct vec ext_vec, mime_vec; const char *list, *ext; size_t path_len; path_len = strlen(path); if ((conn == NULL) || (vec == NULL)) { if (vec != NULL) { memset(vec, '\0', sizeof(struct vec)); } return; } /* Scan user-defined mime types first, in case user wants to * override default mime types. */ list = conn->dom_ctx->config[EXTRA_MIME_TYPES]; while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) { /* ext now points to the path suffix */ ext = path + path_len - ext_vec.len; if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) { *vec = mime_vec; return; } } vec->ptr = mg_get_builtin_mime_type(path); vec->len = strlen(vec->ptr); } /* Stringify binary data. Output buffer must be twice as big as input, * because each byte takes 2 bytes in string representation */ static void bin2str(char *to, const unsigned char *p, size_t len) { static const char *hex = "0123456789abcdef"; for (; len--; p++) { *to++ = hex[p[0] >> 4]; *to++ = hex[p[0] & 0x0f]; } *to = '\0'; } /* Return stringified MD5 hash for list of strings. Buffer must be 33 bytes. */ CIVETWEB_API char * mg_md5(char buf[33], ...) { md5_byte_t hash[16]; const char *p; va_list ap; md5_state_t ctx; md5_init(&ctx); va_start(ap, buf); while ((p = va_arg(ap, const char *)) != NULL) { md5_append(&ctx, (const md5_byte_t *)p, strlen(p)); } va_end(ap); md5_finish(&ctx, hash); bin2str(buf, hash, sizeof(hash)); return buf; } /* Check the user's password, return 1 if OK */ static int check_password_digest(const char *method, const char *ha1, const char *uri, const char *nonce, const char *nc, const char *cnonce, const char *qop, const char *response) { char ha2[32 + 1], expected_response[32 + 1]; /* Some of the parameters may be NULL */ if ((method == NULL) || (nonce == NULL) || (nc == NULL) || (cnonce == NULL) || (qop == NULL) || (response == NULL)) { return 0; } /* NOTE(lsm): due to a bug in MSIE, we do not compare the URI */ if (strlen(response) != 32) { return 0; } mg_md5(ha2, method, ":", uri, NULL); mg_md5(expected_response, ha1, ":", nonce, ":", nc, ":", cnonce, ":", qop, ":", ha2, NULL); return mg_strcasecmp(response, expected_response) == 0; } #if !defined(NO_FILESYSTEMS) /* Use the global passwords file, if specified by auth_gpass option, * or search for .htpasswd in the requested directory. */ static void open_auth_file(struct mg_connection *conn, const char *path, struct mg_file *filep) { if ((conn != NULL) && (conn->dom_ctx != NULL)) { char name[UTF8_PATH_MAX]; const char *p, *e, *gpass = conn->dom_ctx->config[GLOBAL_PASSWORDS_FILE]; int truncated; if (gpass != NULL) { /* Use global passwords file */ if (!mg_fopen(conn, gpass, MG_FOPEN_MODE_READ, filep)) { #if defined(DEBUG) /* Use mg_cry_internal here, since gpass has been * configured. */ mg_cry_internal(conn, "fopen(%s): %s", gpass, strerror(ERRNO)); #endif } /* Important: using local struct mg_file to test path for * is_directory flag. If filep is used, mg_stat() makes it * appear as if auth file was opened. * TODO(mid): Check if this is still required after rewriting * mg_stat */ } else if (mg_stat(conn, path, &filep->stat) && filep->stat.is_directory) { mg_snprintf(conn, &truncated, name, sizeof(name), "%s/%s", path, PASSWORDS_FILE_NAME); if (truncated || !mg_fopen(conn, name, MG_FOPEN_MODE_READ, filep)) { #if defined(DEBUG) /* Don't use mg_cry_internal here, but only a trace, since * this is a typical case. It will occur for every directory * without a password file. */ DEBUG_TRACE("fopen(%s): %s", name, strerror(ERRNO)); #endif } } else { /* Try to find .htpasswd in requested directory. */ for (p = path, e = p + strlen(p) - 1; e > p; e--) { if (e[0] == '/') { break; } } mg_snprintf(conn, &truncated, name, sizeof(name), "%.*s/%s", (int)(e - p), p, PASSWORDS_FILE_NAME); if (truncated || !mg_fopen(conn, name, MG_FOPEN_MODE_READ, filep)) { #if defined(DEBUG) /* Don't use mg_cry_internal here, but only a trace, since * this is a typical case. It will occur for every directory * without a password file. */ DEBUG_TRACE("fopen(%s): %s", name, strerror(ERRNO)); #endif } } } } #endif /* NO_FILESYSTEMS */ /* Parsed Authorization header */ struct ah { char *user; int type; /* 1 = basic, 2 = digest */ char *plain_password; /* Basic only */ char *uri, *cnonce, *response, *qop, *nc, *nonce; /* Digest only */ }; /* Return 1 on success. Always initializes the ah structure. */ static int parse_auth_header(struct mg_connection *conn, char *buf, size_t buf_size, struct ah *ah) { char *name, *value, *s; const char *auth_header; uint64_t nonce; if (!ah || !conn) { return 0; } (void)memset(ah, 0, sizeof(*ah)); auth_header = mg_get_header(conn, "Authorization"); if (auth_header == NULL) { /* No Authorization header at all */ return 0; } if (0 == mg_strncasecmp(auth_header, "Basic ", 6)) { /* Basic Auth (we never asked for this, but some client may send it) */ char *split; const char *userpw_b64 = auth_header + 6; size_t userpw_b64_len = strlen(userpw_b64); size_t buf_len_r = buf_size; if (mg_base64_decode( userpw_b64, userpw_b64_len, (unsigned char *)buf, &buf_len_r) != -1) { return 0; /* decode error */ } split = strchr(buf, ':'); if (!split) { return 0; /* Format error */ } /* Separate string at ':' */ *split = 0; /* User name is before ':', Password is after ':' */ ah->user = buf; ah->type = 1; ah->plain_password = split + 1; return 1; } else if (0 == mg_strncasecmp(auth_header, "Digest ", 7)) { /* Digest Auth ... implemented below */ ah->type = 2; } else { /* Unknown or invalid Auth method */ return 0; } /* Make modifiable copy of the auth header */ (void)mg_strlcpy(buf, auth_header + 7, buf_size); s = buf; /* Parse authorization header */ for (;;) { /* Gobble initial spaces */ while (isspace((unsigned char)*s)) { s++; } name = skip_quoted(&s, "=", " ", 0); /* Value is either quote-delimited, or ends at first comma or space. */ if (s[0] == '\"') { s++; value = skip_quoted(&s, "\"", " ", '\\'); if (s[0] == ',') { s++; } } else { value = skip_quoted(&s, ", ", " ", 0); /* IE uses commas, FF * uses spaces */ } if (*name == '\0') { break; } if (!strcmp(name, "username")) { ah->user = value; } else if (!strcmp(name, "cnonce")) { ah->cnonce = value; } else if (!strcmp(name, "response")) { ah->response = value; } else if (!strcmp(name, "uri")) { ah->uri = value; } else if (!strcmp(name, "qop")) { ah->qop = value; } else if (!strcmp(name, "nc")) { ah->nc = value; } else if (!strcmp(name, "nonce")) { ah->nonce = value; } } #if !defined(NO_NONCE_CHECK) /* Read the nonce from the response. */ if (ah->nonce == NULL) { return 0; } s = NULL; nonce = strtoull(ah->nonce, &s, 10); if ((s == NULL) || (*s != 0)) { return 0; } /* Convert the nonce from the client to a number. */ nonce ^= conn->dom_ctx->auth_nonce_mask; /* The converted number corresponds to the time the nounce has been * created. This should not be earlier than the server start. */ /* Server side nonce check is valuable in all situations but one: * if the server restarts frequently, but the client should not see * that, so the server should accept nonces from previous starts. */ /* However, the reasonable default is to not accept a nonce from a * previous start, so if anyone changed the access rights between * two restarts, a new login is required. */ if (nonce < (uint64_t)conn->phys_ctx->start_time) { /* nonce is from a previous start of the server and no longer valid * (replay attack?) */ return 0; } /* Check if the nonce is too high, so it has not (yet) been used by the * server. */ if (nonce >= ((uint64_t)conn->phys_ctx->start_time + conn->dom_ctx->nonce_count)) { return 0; } #else (void)nonce; #endif return (ah->user != NULL); } static const char * mg_fgets(char *buf, size_t size, struct mg_file *filep) { if (!filep) { return NULL; } if (filep->access.fp != NULL) { return fgets(buf, (int)size, filep->access.fp); } else { return NULL; } } /* Define the initial recursion depth for procesesing htpasswd files that * include other htpasswd * (or even the same) files. It is not difficult to provide a file or files * s.t. they force civetweb * to infinitely recurse and then crash. */ #define INITIAL_DEPTH 9 #if INITIAL_DEPTH <= 0 #error Bad INITIAL_DEPTH for recursion, set to at least 1 #endif #if !defined(NO_FILESYSTEMS) struct read_auth_file_struct { struct mg_connection *conn; struct ah ah; const char *domain; char buf[256 + 256 + 40]; const char *f_user; const char *f_domain; const char *f_ha1; }; static int read_auth_file(struct mg_file *filep, struct read_auth_file_struct *workdata, int depth) { int is_authorized = 0; struct mg_file fp; size_t l; if (!filep || !workdata || (0 == depth)) { return 0; } /* Loop over passwords file */ while (mg_fgets(workdata->buf, sizeof(workdata->buf), filep) != NULL) { l = strlen(workdata->buf); while (l > 0) { if (isspace((unsigned char)workdata->buf[l - 1]) || iscntrl((unsigned char)workdata->buf[l - 1])) { l--; workdata->buf[l] = 0; } else break; } if (l < 1) { continue; } workdata->f_user = workdata->buf; if (workdata->f_user[0] == ':') { /* user names may not contain a ':' and may not be empty, * so lines starting with ':' may be used for a special purpose */ if (workdata->f_user[1] == '#') { /* :# is a comment */ continue; } else if (!strncmp(workdata->f_user + 1, "include=", 8)) { if (mg_fopen(workdata->conn, workdata->f_user + 9, MG_FOPEN_MODE_READ, &fp)) { is_authorized = read_auth_file(&fp, workdata, depth - 1); (void)mg_fclose( &fp.access); /* ignore error on read only file */ /* No need to continue processing files once we have a * match, since nothing will reset it back * to 0. */ if (is_authorized) { return is_authorized; } } else { mg_cry_internal(workdata->conn, "%s: cannot open authorization file: %s", __func__, workdata->buf); } continue; } /* everything is invalid for the moment (might change in the * future) */ mg_cry_internal(workdata->conn, "%s: syntax error in authorization file: %s", __func__, workdata->buf); continue; } workdata->f_domain = strchr(workdata->f_user, ':'); if (workdata->f_domain == NULL) { mg_cry_internal(workdata->conn, "%s: syntax error in authorization file: %s", __func__, workdata->buf); continue; } *(char *)(workdata->f_domain) = 0; (workdata->f_domain)++; workdata->f_ha1 = strchr(workdata->f_domain, ':'); if (workdata->f_ha1 == NULL) { mg_cry_internal(workdata->conn, "%s: syntax error in authorization file: %s", __func__, workdata->buf); continue; } *(char *)(workdata->f_ha1) = 0; (workdata->f_ha1)++; if (!strcmp(workdata->ah.user, workdata->f_user) && !strcmp(workdata->domain, workdata->f_domain)) { switch (workdata->ah.type) { case 1: /* Basic */ { char md5[33]; mg_md5(md5, workdata->f_user, ":", workdata->domain, ":", workdata->ah.plain_password, NULL); return 0 == memcmp(workdata->f_ha1, md5, 33); } case 2: /* Digest */ return check_password_digest( workdata->conn->request_info.request_method, workdata->f_ha1, workdata->ah.uri, workdata->ah.nonce, workdata->ah.nc, workdata->ah.cnonce, workdata->ah.qop, workdata->ah.response); default: /* None/Other/Unknown */ return 0; } } } return is_authorized; } /* Authorize against the opened passwords file. Return 1 if authorized. */ static int authorize(struct mg_connection *conn, struct mg_file *filep, const char *realm) { struct read_auth_file_struct workdata; char buf[MG_BUF_LEN]; if (!conn || !conn->dom_ctx) { return 0; } memset(&workdata, 0, sizeof(workdata)); workdata.conn = conn; if (!parse_auth_header(conn, buf, sizeof(buf), &workdata.ah)) { return 0; } /* CGI needs it as REMOTE_USER */ conn->request_info.remote_user = mg_strdup_ctx(workdata.ah.user, conn->phys_ctx); if (realm) { workdata.domain = realm; } else { workdata.domain = conn->dom_ctx->config[AUTHENTICATION_DOMAIN]; } return read_auth_file(filep, &workdata, INITIAL_DEPTH); } /* Public function to check http digest authentication header */ CIVETWEB_API int mg_check_digest_access_authentication(struct mg_connection *conn, const char *realm, const char *filename) { struct mg_file file = STRUCT_FILE_INITIALIZER; int auth; if (!conn || !filename) { return -1; } if (!mg_fopen(conn, filename, MG_FOPEN_MODE_READ, &file)) { return -2; } auth = authorize(conn, &file, realm); mg_fclose(&file.access); return auth; } #endif /* NO_FILESYSTEMS */ /* Return 1 if request is authorised, 0 otherwise. */ static int check_authorization(struct mg_connection *conn, const char *path) { #if !defined(NO_FILESYSTEMS) char fname[UTF8_PATH_MAX]; struct vec uri_vec, filename_vec; const char *list; struct mg_file file = STRUCT_FILE_INITIALIZER; int authorized = 1, truncated; if (!conn || !conn->dom_ctx) { return 0; } list = conn->dom_ctx->config[PROTECT_URI]; while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) { if (!memcmp(conn->request_info.local_uri, uri_vec.ptr, uri_vec.len)) { mg_snprintf(conn, &truncated, fname, sizeof(fname), "%.*s", (int)filename_vec.len, filename_vec.ptr); if (truncated || !mg_fopen(conn, fname, MG_FOPEN_MODE_READ, &file)) { mg_cry_internal(conn, "%s: cannot open %s: %s", __func__, fname, strerror(errno)); } break; } } if (!is_file_opened(&file.access)) { open_auth_file(conn, path, &file); } if (is_file_opened(&file.access)) { authorized = authorize(conn, &file, NULL); (void)mg_fclose(&file.access); /* ignore error on read only file */ } return authorized; #else (void)conn; (void)path; return 1; #endif /* NO_FILESYSTEMS */ } /* Internal function. Assumes conn is valid */ static void send_authorization_request(struct mg_connection *conn, const char *realm) { uint64_t nonce = (uint64_t)(conn->phys_ctx->start_time); int trunc = 0; char buf[128]; if (!realm) { realm = conn->dom_ctx->config[AUTHENTICATION_DOMAIN]; } mg_lock_context(conn->phys_ctx); nonce += conn->dom_ctx->nonce_count; ++conn->dom_ctx->nonce_count; mg_unlock_context(conn->phys_ctx); nonce ^= conn->dom_ctx->auth_nonce_mask; conn->must_close = 1; /* Create 401 response */ mg_response_header_start(conn, 401); send_no_cache_header(conn); send_additional_header(conn); mg_response_header_add(conn, "Content-Length", "0", -1); /* Content for "WWW-Authenticate" header */ mg_snprintf(conn, &trunc, buf, sizeof(buf), "Digest qop=\"auth\", realm=\"%s\", " "nonce=\"%" UINT64_FMT "\"", realm, nonce); if (!trunc) { /* !trunc should always be true */ mg_response_header_add(conn, "WWW-Authenticate", buf, -1); } /* Send all headers */ mg_response_header_send(conn); } /* Interface function. Parameters are provided by the user, so do * at least some basic checks. */ CIVETWEB_API int mg_send_digest_access_authentication_request(struct mg_connection *conn, const char *realm) { if (conn && conn->dom_ctx) { send_authorization_request(conn, realm); return 0; } return -1; } #if !defined(NO_FILES) static int is_authorized_for_put(struct mg_connection *conn) { int ret = 0; if (conn) { struct mg_file file = STRUCT_FILE_INITIALIZER; const char *passfile = conn->dom_ctx->config[PUT_DELETE_PASSWORDS_FILE]; if (passfile != NULL && mg_fopen(conn, passfile, MG_FOPEN_MODE_READ, &file)) { ret = authorize(conn, &file, NULL); (void)mg_fclose(&file.access); /* ignore error on read only file */ } } DEBUG_TRACE("file write authorization: %i", ret); return ret; } #endif CIVETWEB_API int mg_modify_passwords_file_ha1(const char *fname, const char *domain, const char *user, const char *ha1) { int found = 0, i, result = 1; char line[512], u[256], d[256], h[256]; struct stat st = {0}; FILE *fp = NULL; char *temp_file = NULL; int temp_file_offs = 0; /* Regard empty password as no password - remove user record. */ if ((ha1 != NULL) && (ha1[0] == '\0')) { ha1 = NULL; } /* Other arguments must not be empty */ if ((fname == NULL) || (domain == NULL) || (user == NULL)) { return 0; } /* Using the given file format, user name and domain must not contain * the ':' character */ if (strchr(user, ':') != NULL) { return 0; } if (strchr(domain, ':') != NULL) { return 0; } /* Do not allow control characters like newline in user name and domain. * Do not allow excessively long names either. */ for (i = 0; ((i < 255) && (user[i] != 0)); i++) { if (iscntrl((unsigned char)user[i])) { return 0; } } if (user[i]) { return 0; /* user name too long */ } for (i = 0; ((i < 255) && (domain[i] != 0)); i++) { if (iscntrl((unsigned char)domain[i])) { return 0; } } if (domain[i]) { return 0; /* domain name too long */ } /* The maximum length of the path to the password file is limited */ if (strlen(fname) >= UTF8_PATH_MAX) { return 0; } /* Check if the file exists, and get file size */ if (0 == stat(fname, &st)) { int temp_buf_len; if (st.st_size > 10485760) { /* Some funster provided a >10 MB text file */ return 0; } /* Add enough space for one more line */ temp_buf_len = (int)st.st_size + 1024; /* Allocate memory (instead of using a temporary file) */ temp_file = (char *)mg_calloc((size_t)temp_buf_len, 1); if (!temp_file) { /* Out of memory */ return 0; } /* File exists. Read it into a memory buffer. */ fp = fopen(fname, "r"); if (fp == NULL) { /* Cannot read file. No permission? */ mg_free(temp_file); return 0; } /* Read content and store in memory */ while ((fgets(line, sizeof(line), fp) != NULL) && ((temp_file_offs + 600) < temp_buf_len)) { /* file format is "user:domain:hash\n" */ if (sscanf(line, "%255[^:]:%255[^:]:%255s", u, d, h) != 3) { continue; } u[255] = 0; d[255] = 0; h[255] = 0; if (!strcmp(u, user) && !strcmp(d, domain)) { /* Found the user: change the password hash or drop the user */ if ((ha1 != NULL) && (!found)) { i = snprintf(temp_file + temp_file_offs, temp_buf_len - temp_file_offs, "%s:%s:%s\n", user, domain, ha1); if (i < 1) { fclose(fp); mg_free(temp_file); return 0; } temp_file_offs += i; } found = 1; } else { /* Copy existing user, including password hash */ i = snprintf(temp_file + temp_file_offs, temp_buf_len - temp_file_offs, "%s:%s:%s\n", u, d, h); if (i < 1) { fclose(fp); mg_free(temp_file); return 0; } temp_file_offs += i; } } fclose(fp); } /* Create new file */ fp = fopen(fname, "w"); if (!fp) { mg_free(temp_file); return 0; } #if !defined(_WIN32) /* On Linux & co., restrict file read/write permissions to the owner */ if (fchmod(fileno(fp), S_IRUSR | S_IWUSR) != 0) { result = 0; } #endif if ((temp_file != NULL) && (temp_file_offs > 0)) { /* Store buffered content of old file */ if (fwrite(temp_file, 1, (size_t)temp_file_offs, fp) != (size_t)temp_file_offs) { result = 0; } } /* If new user, just add it */ if ((ha1 != NULL) && (!found)) { if (fprintf(fp, "%s:%s:%s\n", user, domain, ha1) < 6) { result = 0; } } /* All data written */ if (fclose(fp) != 0) { result = 0; } mg_free(temp_file); return result; } CIVETWEB_API int mg_modify_passwords_file(const char *fname, const char *domain, const char *user, const char *pass) { char ha1buf[33]; if ((fname == NULL) || (domain == NULL) || (user == NULL)) { return 0; } if ((pass == NULL) || (pass[0] == 0)) { return mg_modify_passwords_file_ha1(fname, domain, user, NULL); } mg_md5(ha1buf, user, ":", domain, ":", pass, NULL); return mg_modify_passwords_file_ha1(fname, domain, user, ha1buf); } static int is_valid_port(unsigned long port) { return (port <= 0xffff); } static int mg_inet_pton(int af, const char *src, void *dst, size_t dstlen, int resolve_src) { struct addrinfo hints, *res, *ressave; int func_ret = 0; int gai_ret; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = af; if (!resolve_src) { hints.ai_flags = AI_NUMERICHOST; } gai_ret = getaddrinfo(src, NULL, &hints, &res); if (gai_ret != 0) { /* gai_strerror could be used to convert gai_ret to a string */ /* POSIX return values: see * http://pubs.opengroup.org/onlinepubs/9699919799/functions/freeaddrinfo.html */ /* Windows return values: see * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520%28v=vs.85%29.aspx */ return 0; } ressave = res; while (res) { if ((dstlen >= (size_t)res->ai_addrlen) && (res->ai_addr->sa_family == af)) { memcpy(dst, res->ai_addr, res->ai_addrlen); func_ret = 1; } res = res->ai_next; } freeaddrinfo(ressave); return func_ret; } static int connect_socket( struct mg_context *ctx /* may be NULL */, const char *host, int port, /* 1..65535, or -99 for domain sockets (may be changed) */ int use_ssl, /* 0 or 1 */ struct mg_error_data *error, SOCKET *sock /* output: socket, must not be NULL */, union usa *sa /* output: socket address, must not be NULL */ ) { int ip_ver = 0; int conn_ret = -1; int sockerr = 0; *sock = INVALID_SOCKET; memset(sa, 0, sizeof(*sa)); if (host == NULL) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_PARAM; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "%s", "NULL host"); } return 0; } #if defined(USE_X_DOM_SOCKET) if (port == -99) { /* Unix domain socket */ size_t hostlen = strlen(host); if (hostlen >= sizeof(sa->sun.sun_path)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_PARAM; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "%s", "host length exceeds limit"); } return 0; } } else #endif if ((port <= 0) || !is_valid_port((unsigned)port)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_PARAM; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "%s", "invalid port"); } return 0; } #if !defined(NO_SSL) && !defined(USE_MBEDTLS) && !defined(NO_SSL_DL) #if defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0) if (use_ssl && (TLS_client_method == NULL)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "%s", "SSL is not initialized"); } return 0; } #else if (use_ssl && (SSLv23_client_method == NULL)) { if (error != 0) { error->code = MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "%s", "SSL is not initialized"); } return 0; } #endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0*/ #else (void)use_ssl; #endif /* NO SSL */ #if defined(USE_X_DOM_SOCKET) if (port == -99) { size_t hostlen = strlen(host); /* check (hostlen < sizeof(sun.sun_path)) already passed above */ ip_ver = -99; sa->sun.sun_family = AF_UNIX; memset(sa->sun.sun_path, 0, sizeof(sa->sun.sun_path)); memcpy(sa->sun.sun_path, host, hostlen); } else #endif if (mg_inet_pton(AF_INET, host, &sa->sin, sizeof(sa->sin), 1)) { sa->sin.sin_port = htons((uint16_t)port); ip_ver = 4; #if defined(USE_IPV6) } else if (mg_inet_pton(AF_INET6, host, &sa->sin6, sizeof(sa->sin6), 1)) { sa->sin6.sin6_port = htons((uint16_t)port); ip_ver = 6; } else if (host[0] == '[') { /* While getaddrinfo on Windows will work with [::1], * getaddrinfo on Linux only works with ::1 (without []). */ size_t l = strlen(host + 1); char *h = (l > 1) ? mg_strdup_ctx(host + 1, ctx) : NULL; if (h) { h[l - 1] = 0; if (mg_inet_pton(AF_INET6, h, &sa->sin6, sizeof(sa->sin6), 0)) { sa->sin6.sin6_port = htons((uint16_t)port); ip_ver = 6; } mg_free(h); } #endif } if (ip_ver == 0) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_HOST_NOT_FOUND; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "%s", "host not found"); } return 0; } if (ip_ver == 4) { *sock = socket(PF_INET, SOCK_STREAM, 0); } #if defined(USE_IPV6) else if (ip_ver == 6) { *sock = socket(PF_INET6, SOCK_STREAM, 0); } #endif #if defined(USE_X_DOM_SOCKET) else if (ip_ver == -99) { *sock = socket(AF_UNIX, SOCK_STREAM, 0); } #endif if (*sock == INVALID_SOCKET) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OS_ERROR; error->code_sub = (unsigned)ERRNO; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "socket(): %s", strerror(ERRNO)); } return 0; } if (0 != set_non_blocking_mode(*sock)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OS_ERROR; error->code_sub = (unsigned)ERRNO; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "Cannot set socket to non-blocking: %s", strerror(ERRNO)); } closesocket(*sock); *sock = INVALID_SOCKET; return 0; } set_close_on_exec(*sock, NULL, ctx); if (ip_ver == 4) { /* connected with IPv4 */ conn_ret = connect(*sock, (struct sockaddr *)((void *)&sa->sin), sizeof(sa->sin)); } #if defined(USE_IPV6) else if (ip_ver == 6) { /* connected with IPv6 */ conn_ret = connect(*sock, (struct sockaddr *)((void *)&sa->sin6), sizeof(sa->sin6)); } #endif #if defined(USE_X_DOM_SOCKET) else if (ip_ver == -99) { /* connected to domain socket */ conn_ret = connect(*sock, (struct sockaddr *)((void *)&sa->sun), sizeof(sa->sun)); } #endif if (conn_ret != 0) { sockerr = ERRNO; } #if defined(_WIN32) if ((conn_ret != 0) && (sockerr == WSAEWOULDBLOCK)) { #else if ((conn_ret != 0) && (sockerr == EINPROGRESS)) { #endif /* Data for getsockopt */ void *psockerr = &sockerr; int ret; #if defined(_WIN32) int len = (int)sizeof(sockerr); #else socklen_t len = (socklen_t)sizeof(sockerr); #endif /* Data for poll */ struct mg_pollfd pfd[1]; int pollres; int ms_wait = 10000; /* 10 second timeout */ stop_flag_t nonstop; STOP_FLAG_ASSIGN(&nonstop, 0); /* For a non-blocking socket, the connect sequence is: * 1) call connect (will not block) * 2) wait until the socket is ready for writing (select or poll) * 3) check connection state with getsockopt */ pfd[0].fd = *sock; pfd[0].events = POLLOUT; pollres = mg_poll(pfd, 1, ms_wait, ctx ? &(ctx->stop_flag) : &nonstop); if (pollres != 1) { /* Not connected */ if (error != NULL) { error->code = MG_ERROR_DATA_CODE_CONNECT_TIMEOUT; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "connect(%s:%d): timeout", host, port); } closesocket(*sock); *sock = INVALID_SOCKET; return 0; } #if defined(_WIN32) ret = getsockopt(*sock, SOL_SOCKET, SO_ERROR, (char *)psockerr, &len); #else ret = getsockopt(*sock, SOL_SOCKET, SO_ERROR, psockerr, &len); #endif if ((ret == 0) && (sockerr == 0)) { conn_ret = 0; } } if (conn_ret != 0) { /* Not connected */ if (error != NULL) { error->code = MG_ERROR_DATA_CODE_CONNECT_FAILED; error->code_sub = (unsigned)ERRNO; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "connect(%s:%d): error %s", host, port, strerror(sockerr)); } closesocket(*sock); *sock = INVALID_SOCKET; return 0; } return 1; } CIVETWEB_API int mg_url_encode(const char *src, char *dst, size_t dst_len) { static const char *dont_escape = "._-$,;~()"; static const char *hex = "0123456789abcdef"; char *pos = dst; const char *end = dst + dst_len - 1; for (; ((*src != '\0') && (pos < end)); src++, pos++) { if (isalnum((unsigned char)*src) || (strchr(dont_escape, *src) != NULL)) { *pos = *src; } else if (pos + 2 < end) { pos[0] = '%'; pos[1] = hex[(unsigned char)*src >> 4]; pos[2] = hex[(unsigned char)*src & 0xf]; pos += 2; } else { break; } } *pos = '\0'; return (*src == '\0') ? (int)(pos - dst) : -1; } /* Return 0 on success, non-zero if an error occurs. */ static int print_dir_entry(struct mg_connection *conn, struct de *de) { size_t namesize, escsize, i; char *href, *esc, *p; char size[64], mod[64]; #if defined(REENTRANT_TIME) struct tm _tm; struct tm *tm = &_tm; #else struct tm *tm; #endif /* Estimate worst case size for encoding and escaping */ namesize = strlen(de->file_name) + 1; escsize = de->file_name[strcspn(de->file_name, "&<>")] ? namesize * 5 : 0; href = (char *)mg_malloc(namesize * 3 + escsize); if (href == NULL) { return -1; } mg_url_encode(de->file_name, href, namesize * 3); esc = NULL; if (escsize > 0) { /* HTML escaping needed */ esc = href + namesize * 3; for (i = 0, p = esc; de->file_name[i]; i++, p += strlen(p)) { mg_strlcpy(p, de->file_name + i, 2); if (*p == '&') { strcpy(p, "&"); } else if (*p == '<') { strcpy(p, "<"); } else if (*p == '>') { strcpy(p, ">"); } } } if (de->file.is_directory) { mg_snprintf(conn, NULL, /* Buffer is big enough */ size, sizeof(size), "%s", "[DIRECTORY]"); } else { /* We use (signed) cast below because MSVC 6 compiler cannot * convert unsigned __int64 to double. Sigh. */ if (de->file.size < 1024) { mg_snprintf(conn, NULL, /* Buffer is big enough */ size, sizeof(size), "%d", (int)de->file.size); } else if (de->file.size < 0x100000) { mg_snprintf(conn, NULL, /* Buffer is big enough */ size, sizeof(size), "%.1fk", (double)de->file.size / 1024.0); } else if (de->file.size < 0x40000000) { mg_snprintf(conn, NULL, /* Buffer is big enough */ size, sizeof(size), "%.1fM", (double)de->file.size / 1048576); } else { mg_snprintf(conn, NULL, /* Buffer is big enough */ size, sizeof(size), "%.1fG", (double)de->file.size / 1073741824); } } /* Note: mg_snprintf will not cause a buffer overflow above. * So, string truncation checks are not required here. */ #if defined(REENTRANT_TIME) localtime_r(&de->file.last_modified, tm); #else tm = localtime(&de->file.last_modified); #endif if (tm != NULL) { strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", tm); } else { mg_strlcpy(mod, "01-Jan-1970 00:00", sizeof(mod)); } mg_printf(conn, "%s%s" " %s  %s\n", href, de->file.is_directory ? "/" : "", esc ? esc : de->file_name, de->file.is_directory ? "/" : "", mod, size); mg_free(href); return 0; } /* This function is called from send_directory() and used for * sorting directory entries by size, name, or modification time. */ static int compare_dir_entries(const void *p1, const void *p2, void *arg) { const char *query_string = (const char *)(arg != NULL ? arg : ""); if (p1 && p2) { const struct de *a = (const struct de *)p1, *b = (const struct de *)p2; int cmp_result = 0; if ((query_string == NULL) || (query_string[0] == '\0')) { query_string = "n"; } /* Sort Directories vs Files */ if (a->file.is_directory && !b->file.is_directory) { return -1; /* Always put directories on top */ } else if (!a->file.is_directory && b->file.is_directory) { return 1; /* Always put directories on top */ } /* Sort by size or date */ if (*query_string == 's') { cmp_result = (a->file.size == b->file.size) ? 0 : ((a->file.size > b->file.size) ? 1 : -1); } else if (*query_string == 'd') { cmp_result = (a->file.last_modified == b->file.last_modified) ? 0 : ((a->file.last_modified > b->file.last_modified) ? 1 : -1); } /* Sort by name: * if (*query_string == 'n') ... * but also sort files of same size/date by name as secondary criterion. */ if (cmp_result == 0) { cmp_result = strcmp(a->file_name, b->file_name); } /* For descending order, invert result */ return (query_string[1] == 'd') ? -cmp_result : cmp_result; } return 0; } static int must_hide_file(struct mg_connection *conn, const char *path) { if (conn && conn->dom_ctx) { const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$"; const char *pattern = conn->dom_ctx->config[HIDE_FILES]; return (match_prefix_strlen(pw_pattern, path) > 0) || (match_prefix_strlen(pattern, path) > 0); } return 0; } #if !defined(NO_FILESYSTEMS) static int scan_directory(struct mg_connection *conn, const char *dir, void *data, int (*cb)(struct de *, void *)) { char path[UTF8_PATH_MAX]; struct dirent *dp; DIR *dirp; struct de de; int truncated; if ((dirp = mg_opendir(conn, dir)) == NULL) { return 0; } else { while ((dp = mg_readdir(dirp)) != NULL) { /* Do not show current dir and hidden files */ if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") || must_hide_file(conn, dp->d_name)) { continue; } mg_snprintf( conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name); /* If we don't memset stat structure to zero, mtime will have * garbage and strftime() will segfault later on in * print_dir_entry(). memset is required only if mg_stat() * fails. For more details, see * http://code.google.com/p/mongoose/issues/detail?id=79 */ memset(&de.file, 0, sizeof(de.file)); if (truncated) { /* If the path is not complete, skip processing. */ continue; } if (!mg_stat(conn, path, &de.file)) { mg_cry_internal(conn, "%s: mg_stat(%s) failed: %s", __func__, path, strerror(ERRNO)); } de.file_name = dp->d_name; if (cb(&de, data)) { /* stopped */ break; } } (void)mg_closedir(dirp); } return 1; } #endif /* NO_FILESYSTEMS */ #if !defined(NO_FILES) static int remove_directory(struct mg_connection *conn, const char *dir) { char path[UTF8_PATH_MAX]; struct dirent *dp; DIR *dirp; struct de de; int truncated; int ok = 1; if ((dirp = mg_opendir(conn, dir)) == NULL) { return 0; } else { while ((dp = mg_readdir(dirp)) != NULL) { /* Do not show current dir (but show hidden files as they will * also be removed) */ if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) { continue; } mg_snprintf( conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name); /* If we don't memset stat structure to zero, mtime will have * garbage and strftime() will segfault later on in * print_dir_entry(). memset is required only if mg_stat() * fails. For more details, see * http://code.google.com/p/mongoose/issues/detail?id=79 */ memset(&de.file, 0, sizeof(de.file)); if (truncated) { /* Do not delete anything shorter */ ok = 0; continue; } if (!mg_stat(conn, path, &de.file)) { mg_cry_internal(conn, "%s: mg_stat(%s) failed: %s", __func__, path, strerror(ERRNO)); ok = 0; } if (de.file.is_directory) { if (remove_directory(conn, path) == 0) { ok = 0; } } else { /* This will fail file is the file is in memory */ if (mg_remove(conn, path) == 0) { ok = 0; } } } (void)mg_closedir(dirp); IGNORE_UNUSED_RESULT(rmdir(dir)); } return ok; } #endif struct dir_scan_data { struct de *entries; size_t num_entries; size_t arr_size; }; #if !defined(NO_FILESYSTEMS) static int dir_scan_callback(struct de *de, void *data) { struct dir_scan_data *dsd = (struct dir_scan_data *)data; struct de *entries = dsd->entries; if ((entries == NULL) || (dsd->num_entries >= dsd->arr_size)) { /* Here "entries" is a temporary pointer and can be replaced, * "dsd->entries" is the original pointer */ entries = (struct de *)mg_realloc(entries, dsd->arr_size * 2 * sizeof(entries[0])); if (entries == NULL) { /* stop scan */ return 1; } dsd->entries = entries; dsd->arr_size *= 2; } entries[dsd->num_entries].file_name = mg_strdup(de->file_name); if (entries[dsd->num_entries].file_name == NULL) { /* stop scan */ return 1; } entries[dsd->num_entries].file = de->file; dsd->num_entries++; return 0; } static void handle_directory_request(struct mg_connection *conn, const char *dir) { size_t i; int sort_direction; struct dir_scan_data data = {NULL, 0, 128}; char date[64], *esc, *p; const char *title; time_t curtime = time(NULL); if (!conn) { return; } if (!scan_directory(conn, dir, &data, dir_scan_callback)) { mg_send_http_error(conn, 500, "Error: Cannot open directory\nopendir(%s): %s", dir, strerror(ERRNO)); return; } gmt_time_string(date, sizeof(date), &curtime); esc = NULL; title = conn->request_info.local_uri; if (title[strcspn(title, "&<>")]) { /* HTML escaping needed */ esc = (char *)mg_malloc(strlen(title) * 5 + 1); if (esc) { for (i = 0, p = esc; title[i]; i++, p += strlen(p)) { mg_strlcpy(p, title + i, 2); if (*p == '&') { strcpy(p, "&"); } else if (*p == '<') { strcpy(p, "<"); } else if (*p == '>') { strcpy(p, ">"); } } } else { title = ""; } } sort_direction = ((conn->request_info.query_string != NULL) && (conn->request_info.query_string[0] != '\0') && (conn->request_info.query_string[1] == 'd')) ? 'a' : 'd'; conn->must_close = 1; /* Create 200 OK response */ mg_response_header_start(conn, 200); send_static_cache_header(conn); send_additional_header(conn); mg_response_header_add(conn, "Content-Type", "text/html; charset=utf-8", -1); /* Send all headers */ mg_response_header_send(conn); /* Body */ mg_printf(conn, "" "Index of %s" "" "

Index of %s

"
	          ""
	          ""
	          ""
	          "",
	          esc ? esc : title,
	          esc ? esc : title,
	          sort_direction,
	          sort_direction,
	          sort_direction);
	mg_free(esc);

	/* Print first entry - link to a parent directory */
	mg_printf(conn,
	          ""
	          "\n",
	          "..",
	          "Parent directory",
	          "-",
	          "-");

	/* Sort and print directory entries */
	if (data.entries != NULL) {
		mg_sort(data.entries,
		        data.num_entries,
		        sizeof(data.entries[0]),
		        compare_dir_entries,
		        (void *)conn->request_info.query_string);
		for (i = 0; i < data.num_entries; i++) {
			print_dir_entry(conn, &data.entries[i]);
			mg_free(data.entries[i].file_name);
		}
		mg_free(data.entries);
	}

	mg_printf(conn, "%s", "
NameModifiedSize

%s %s  %s
"); conn->status_code = 200; } #endif /* NO_FILESYSTEMS */ /* Send len bytes from the opened file to the client. */ static void send_file_data(struct mg_connection *conn, struct mg_file *filep, int64_t offset, int64_t len, int no_buffering) { char buf[MG_BUF_LEN]; int to_read, num_read, num_written; int64_t size; if (!filep || !conn) { return; } /* Sanity check the offset */ size = (filep->stat.size > INT64_MAX) ? INT64_MAX : (int64_t)(filep->stat.size); offset = (offset < 0) ? 0 : ((offset > size) ? size : offset); if (len > 0 && filep->access.fp != NULL) { /* file stored on disk */ #if defined(__linux__) /* sendfile is only available for Linux */ if ((conn->ssl == 0) && (conn->throttle == 0) && (!mg_strcasecmp(conn->dom_ctx->config[ALLOW_SENDFILE_CALL], "yes"))) { off_t sf_offs = (off_t)offset; ssize_t sf_sent; int sf_file = fileno(filep->access.fp); int loop_cnt = 0; do { /* 2147479552 (0x7FFFF000) is a limit found by experiment on * 64 bit Linux (2^31 minus one memory page of 4k?). */ size_t sf_tosend = (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000); sf_sent = sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend); if (sf_sent > 0) { len -= sf_sent; offset += sf_sent; } else if (loop_cnt == 0) { /* This file can not be sent using sendfile. * This might be the case for pseudo-files in the * /sys/ and /proc/ file system. * Use the regular user mode copy code instead. */ break; } else if (sf_sent == 0) { /* No error, but 0 bytes sent. May be EOF? */ return; } loop_cnt++; } while ((len > 0) && (sf_sent >= 0)); if (sf_sent > 0) { return; /* OK */ } /* sf_sent<0 means error, thus fall back to the classic way */ /* This is always the case, if sf_file is not a "normal" file, * e.g., for sending data from the output of a CGI process. */ offset = (int64_t)sf_offs; } #endif if ((offset > 0) && (fseeko(filep->access.fp, offset, SEEK_SET) != 0)) { mg_cry_internal(conn, "%s: fseeko() failed: %s", __func__, strerror(ERRNO)); mg_send_http_error( conn, 500, "%s", "Error: Unable to access file at requested position."); } else { while (len > 0) { /* Calculate how much to read from the file into the buffer. */ /* If no_buffering is set, we should not wait until the * CGI->Server buffer is filled, but send everything * immediately. In theory buffering could be turned off using * setbuf(filep->access.fp, NULL); * setvbuf(filep->access.fp, NULL, _IONBF, 0); * but in practice this does not work. A "Linux only" solution * may be to use select(). The only portable way is to read byte * by byte, but this is quite inefficient from a performance * point of view. */ to_read = no_buffering ? 1 : sizeof(buf); if ((int64_t)to_read > len) { to_read = (int)len; } /* Read from file, exit the loop on error */ if ((num_read = (int)fread(buf, 1, (size_t)to_read, filep->access.fp)) <= 0) { break; } /* Send read bytes to the client, exit the loop on error */ if ((num_written = mg_write(conn, buf, (size_t)num_read)) != num_read) { break; } /* Both read and were successful, adjust counters */ len -= num_written; } } } } static int parse_range_header(const char *header, int64_t *a, int64_t *b) { return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b); // NOLINT(cert-err34-c) 'sscanf' used to convert a string // to an integer value, but function will not report // conversion errors; consider using 'strtol' instead } static void construct_etag(char *buf, size_t buf_len, const struct mg_file_stat *filestat) { if ((filestat != NULL) && (buf != NULL)) { mg_snprintf(NULL, NULL, /* All calls to construct_etag use 64 byte buffer */ buf, buf_len, "\"%lx.%" INT64_FMT "\"", (unsigned long)filestat->last_modified, filestat->size); } } static void fclose_on_exec(struct mg_file_access *filep, struct mg_connection *conn) { if (filep != NULL && filep->fp != NULL) { #if defined(_WIN32) (void)conn; /* Unused. */ #else if (fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC) != 0) { mg_cry_internal(conn, "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s", __func__, strerror(ERRNO)); } #endif } } #if defined(USE_ZLIB) #include "mod_zlib.h" #endif #if !defined(NO_FILESYSTEMS) static void handle_static_file_request(struct mg_connection *conn, const char *path, struct mg_file *filep, const char *mime_type, const char *additional_headers) { char lm[64], etag[64]; char range[128]; /* large enough, so there will be no overflow */ const char *range_hdr; int64_t cl, r1, r2; struct vec mime_vec; int n, truncated; char gz_path[UTF8_PATH_MAX]; const char *encoding = 0; int is_head_request; #if defined(USE_ZLIB) /* Compression is allowed, unless there is a reason not to use * compression. If the file is already compressed, too small or a * "range" request was made, on the fly compression is not possible. */ int allow_on_the_fly_compression = 1; #endif if ((conn == NULL) || (conn->dom_ctx == NULL) || (filep == NULL)) { return; } is_head_request = !strcmp(conn->request_info.request_method, "HEAD"); if (mime_type == NULL) { get_mime_type(conn, path, &mime_vec); } else { mime_vec.ptr = mime_type; mime_vec.len = strlen(mime_type); } if (filep->stat.size > INT64_MAX) { mg_send_http_error(conn, 500, "Error: File size is too large to send\n%" INT64_FMT, filep->stat.size); return; } cl = (int64_t)filep->stat.size; conn->status_code = 200; range[0] = '\0'; #if defined(USE_ZLIB) /* if this file is in fact a pre-gzipped file, rewrite its filename * it's important to rewrite the filename after resolving * the mime type from it, to preserve the actual file's type */ if (!conn->accept_gzip) { allow_on_the_fly_compression = 0; } #endif /* Check if there is a range header */ range_hdr = mg_get_header(conn, "Range"); /* For gzipped files, add *.gz */ if (filep->stat.is_gzipped) { mg_snprintf(conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", path); if (truncated) { mg_send_http_error(conn, 500, "Error: Path of zipped file too long (%s)", path); return; } path = gz_path; encoding = "gzip"; #if defined(USE_ZLIB) /* File is already compressed. No "on the fly" compression. */ allow_on_the_fly_compression = 0; #endif } else if ((conn->accept_gzip) && (range_hdr == NULL) && (filep->stat.size >= MG_FILE_COMPRESSION_SIZE_LIMIT)) { struct mg_file_stat file_stat; mg_snprintf(conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", path); if (!truncated && mg_stat(conn, gz_path, &file_stat) && !file_stat.is_directory) { file_stat.is_gzipped = 1; filep->stat = file_stat; cl = (int64_t)filep->stat.size; path = gz_path; encoding = "gzip"; #if defined(USE_ZLIB) /* File is already compressed. No "on the fly" compression. */ allow_on_the_fly_compression = 0; #endif } } if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, filep)) { mg_send_http_error(conn, 500, "Error: Cannot open file\nfopen(%s): %s", path, strerror(ERRNO)); return; } fclose_on_exec(&filep->access, conn); /* If "Range" request was made: parse header, send only selected part * of the file. */ r1 = r2 = 0; if ((range_hdr != NULL) && ((n = parse_range_header(range_hdr, &r1, &r2)) > 0) && (r1 >= 0) && (r2 >= 0)) { /* actually, range requests don't play well with a pre-gzipped * file (since the range is specified in the uncompressed space) */ if (filep->stat.is_gzipped) { mg_send_http_error( conn, 416, /* 416 = Range Not Satisfiable */ "%s", "Error: Range requests in gzipped files are not supported"); (void)mg_fclose( &filep->access); /* ignore error on read only file */ return; } conn->status_code = 206; cl = (n == 2) ? (((r2 > cl) ? cl : r2) - r1 + 1) : (cl - r1); mg_snprintf(conn, NULL, /* range buffer is big enough */ range, sizeof(range), "bytes " "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT, r1, r1 + cl - 1, filep->stat.size); #if defined(USE_ZLIB) /* Do not compress ranges. */ allow_on_the_fly_compression = 0; #endif } /* Do not compress small files. Small files do not benefit from file * compression, but there is still some overhead. */ #if defined(USE_ZLIB) if (filep->stat.size < MG_FILE_COMPRESSION_SIZE_LIMIT) { /* File is below the size limit. */ allow_on_the_fly_compression = 0; } #endif /* Prepare Etag, and Last-Modified headers. */ gmt_time_string(lm, sizeof(lm), &filep->stat.last_modified); construct_etag(etag, sizeof(etag), &filep->stat); /* Create 2xx (200, 206) response */ mg_response_header_start(conn, conn->status_code); send_static_cache_header(conn); send_additional_header(conn); send_cors_header(conn); mg_response_header_add(conn, "Content-Type", mime_vec.ptr, (int)mime_vec.len); mg_response_header_add(conn, "Last-Modified", lm, -1); mg_response_header_add(conn, "Etag", etag, -1); #if defined(USE_ZLIB) /* On the fly compression allowed */ if (allow_on_the_fly_compression) { /* For on the fly compression, we don't know the content size in * advance, so we have to use chunked encoding */ encoding = "gzip"; if (conn->protocol_type == PROTOCOL_TYPE_HTTP1) { /* HTTP/2 is always using "chunks" (frames) */ mg_response_header_add(conn, "Transfer-Encoding", "chunked", -1); } } else #endif { /* Without on-the-fly compression, we know the content-length * and we can use ranges (with on-the-fly compression we cannot). * So we send these response headers only in this case. */ char len[32]; int trunc = 0; mg_snprintf(conn, &trunc, len, sizeof(len), "%" INT64_FMT, cl); if (!trunc) { mg_response_header_add(conn, "Content-Length", len, -1); } mg_response_header_add(conn, "Accept-Ranges", "bytes", -1); } if (encoding) { mg_response_header_add(conn, "Content-Encoding", encoding, -1); } if (range[0] != 0) { mg_response_header_add(conn, "Content-Range", range, -1); } /* The code above does not add any header starting with X- to make * sure no one of the additional_headers is included twice */ if ((additional_headers != NULL) && (*additional_headers != 0)) { mg_response_header_add_lines(conn, additional_headers); } /* Send all headers */ mg_response_header_send(conn); if (!is_head_request) { #if defined(USE_ZLIB) if (allow_on_the_fly_compression) { /* Compress and send */ send_compressed_data(conn, filep); } else #endif { /* Send file directly */ send_file_data(conn, filep, r1, cl, 0); /* send static file */ } } (void)mg_fclose(&filep->access); /* ignore error on read only file */ } CIVETWEB_API int mg_send_file_body(struct mg_connection *conn, const char *path) { struct mg_file file = STRUCT_FILE_INITIALIZER; if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, &file)) { return -1; } fclose_on_exec(&file.access, conn); send_file_data(conn, &file, 0, INT64_MAX, 0); /* send static file */ (void)mg_fclose(&file.access); /* Ignore errors for readonly files */ return 0; /* >= 0 for OK */ } #endif /* NO_FILESYSTEMS */ #if !defined(NO_CACHING) /* Return True if we should reply 304 Not Modified. */ static int is_not_modified(const struct mg_connection *conn, const struct mg_file_stat *filestat) { char etag[64]; const char *ims = mg_get_header(conn, "If-Modified-Since"); const char *inm = mg_get_header(conn, "If-None-Match"); construct_etag(etag, sizeof(etag), filestat); return ((inm != NULL) && !mg_strcasecmp(etag, inm)) || ((ims != NULL) && (filestat->last_modified <= parse_date_string(ims))); } static void handle_not_modified_static_file_request(struct mg_connection *conn, struct mg_file *filep) { char lm[64], etag[64]; if ((conn == NULL) || (filep == NULL)) { return; } gmt_time_string(lm, sizeof(lm), &filep->stat.last_modified); construct_etag(etag, sizeof(etag), &filep->stat); /* Create 304 "not modified" response */ mg_response_header_start(conn, 304); send_static_cache_header(conn); send_additional_header(conn); mg_response_header_add(conn, "Last-Modified", lm, -1); mg_response_header_add(conn, "Etag", etag, -1); /* Send all headers */ mg_response_header_send(conn); } #endif #if !defined(NO_FILESYSTEMS) CIVETWEB_API void mg_send_file(struct mg_connection *conn, const char *path) { mg_send_mime_file2(conn, path, NULL, NULL); } CIVETWEB_API void mg_send_mime_file(struct mg_connection *conn, const char *path, const char *mime_type) { mg_send_mime_file2(conn, path, mime_type, NULL); } CIVETWEB_API void mg_send_mime_file2(struct mg_connection *conn, const char *path, const char *mime_type, const char *additional_headers) { struct mg_file file = STRUCT_FILE_INITIALIZER; if (!conn) { /* No conn */ return; } if (mg_stat(conn, path, &file.stat)) { #if !defined(NO_CACHING) if (is_not_modified(conn, &file.stat)) { /* Send 304 "Not Modified" - this must not send any body data */ handle_not_modified_static_file_request(conn, &file); } else #endif /* NO_CACHING */ if (file.stat.is_directory) { if (!mg_strcasecmp(conn->dom_ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) { handle_directory_request(conn, path); } else { mg_send_http_error(conn, 403, "%s", "Error: Directory listing denied"); } } else { handle_static_file_request( conn, path, &file, mime_type, additional_headers); } } else { mg_send_http_error(conn, 404, "%s", "Error: File not found"); } } /* For a given PUT path, create all intermediate subdirectories. * Return 0 if the path itself is a directory. * Return 1 if the path leads to a file. * Return -1 for if the path is too long. * Return -2 if path can not be created. */ static int put_dir(struct mg_connection *conn, const char *path) { char buf[UTF8_PATH_MAX]; const char *s, *p; struct mg_file file = STRUCT_FILE_INITIALIZER; size_t len; int res = 1; for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) { len = (size_t)(p - path); if (len >= sizeof(buf)) { /* path too long */ res = -1; break; } memcpy(buf, path, len); buf[len] = '\0'; /* Try to create intermediate directory */ DEBUG_TRACE("mkdir(%s)", buf); if (!mg_stat(conn, buf, &file.stat) && mg_mkdir(conn, buf, 0755) != 0) { /* path does not exist and can not be created */ res = -2; break; } /* Is path itself a directory? */ if (p[1] == '\0') { res = 0; } } return res; } static void remove_bad_file(const struct mg_connection *conn, const char *path) { int r = mg_remove(conn, path); if (r != 0) { mg_cry_internal(conn, "%s: Cannot remove invalid file %s", __func__, path); } } CIVETWEB_API long long mg_store_body(struct mg_connection *conn, const char *path) { char buf[MG_BUF_LEN]; long long len = 0; int ret, n; struct mg_file fi; if (conn->consumed_content != 0) { mg_cry_internal(conn, "%s: Contents already consumed", __func__); return -11; } ret = put_dir(conn, path); if (ret < 0) { /* -1 for path too long, * -2 for path can not be created. */ return ret; } if (ret != 1) { /* Return 0 means, path itself is a directory. */ return 0; } if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fi) == 0) { return -12; } ret = mg_read(conn, buf, sizeof(buf)); while (ret > 0) { n = (int)fwrite(buf, 1, (size_t)ret, fi.access.fp); if (n != ret) { (void)mg_fclose( &fi.access); /* File is bad and will be removed anyway. */ remove_bad_file(conn, path); return -13; } len += ret; ret = mg_read(conn, buf, sizeof(buf)); } /* File is open for writing. If fclose fails, there was probably an * error flushing the buffer to disk, so the file on disk might be * broken. Delete it and return an error to the caller. */ if (mg_fclose(&fi.access) != 0) { remove_bad_file(conn, path); return -14; } return len; } #endif /* NO_FILESYSTEMS */ /* Parse a buffer: * Forward the string pointer till the end of a word, then * terminate it and forward till the begin of the next word. */ static int skip_to_end_of_word_and_terminate(char **ppw, int eol) { /* Forward until a space is found - use isgraph here */ /* See http://www.cplusplus.com/reference/cctype/ */ while (isgraph((unsigned char)**ppw)) { (*ppw)++; } /* Check end of word */ if (eol) { /* must be a end of line */ if ((**ppw != '\r') && (**ppw != '\n')) { return -1; } } else { /* must be a end of a word, but not a line */ if (**ppw != ' ') { return -1; } } /* Terminate and forward to the next word */ do { **ppw = 0; (*ppw)++; } while (isspace((unsigned char)**ppw)); /* Check after term */ if (!eol) { /* if it's not the end of line, there must be a next word */ if (!isgraph((unsigned char)**ppw)) { return -1; } } /* ok */ return 1; } /* Parse HTTP headers from the given buffer, advance buf pointer * to the point where parsing stopped. * All parameters must be valid pointers (not NULL). * Return <0 on error. */ static int parse_http_headers(char **buf, struct mg_header hdr[MG_MAX_HEADERS]) { int i; int num_headers = 0; for (i = 0; i < (int)MG_MAX_HEADERS; i++) { char *dp = *buf; /* Skip all ASCII characters (>SPACE, <127), to find a ':' */ while ((*dp != ':') && (*dp >= 33) && (*dp <= 126)) { dp++; } if (dp == *buf) { /* End of headers reached. */ break; } /* Drop all spaces after header name before : */ while (*dp == ' ') { *dp = 0; dp++; } if (*dp != ':') { /* This is not a valid field. */ return -1; } /* End of header key (*dp == ':') */ /* Truncate here and set the key name */ *dp = 0; hdr[i].name = *buf; /* Skip all spaces */ do { dp++; } while ((*dp == ' ') || (*dp == '\t')); /* The rest of the line is the value */ hdr[i].value = dp; /* Find end of line */ while ((*dp != 0) && (*dp != '\r') && (*dp != '\n')) { dp++; }; /* eliminate \r */ if (*dp == '\r') { *dp = 0; dp++; if (*dp != '\n') { /* This is not a valid line. */ return -1; } } /* here *dp is either 0 or '\n' */ /* in any case, we have a new header */ num_headers = i + 1; if (*dp) { *dp = 0; dp++; *buf = dp; if ((dp[0] == '\r') || (dp[0] == '\n')) { /* This is the end of the header */ break; } } else { *buf = dp; break; } } return num_headers; } struct mg_http_method_info { const char *name; int request_has_body; int response_has_body; int is_safe; int is_idempotent; int is_cacheable; }; /* https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods */ static const struct mg_http_method_info http_methods[] = { /* HTTP (RFC 2616) */ {"GET", 0, 1, 1, 1, 1}, {"POST", 1, 1, 0, 0, 0}, {"PUT", 1, 0, 0, 1, 0}, {"DELETE", 0, 0, 0, 1, 0}, {"HEAD", 0, 0, 1, 1, 1}, {"OPTIONS", 0, 0, 1, 1, 0}, {"CONNECT", 1, 1, 0, 0, 0}, /* TRACE method (RFC 2616) is not supported for security reasons */ /* PATCH method (RFC 5789) */ {"PATCH", 1, 0, 0, 0, 0}, /* PATCH method only allowed for CGI/Lua/LSP and callbacks. */ /* WEBDAV (RFC 2518) */ {"PROPFIND", 0, 1, 1, 1, 0}, /* http://www.webdav.org/specs/rfc4918.html, 9.1: * Some PROPFIND results MAY be cached, with care, * as there is no cache validation mechanism for * most properties. This method is both safe and * idempotent (see Section 9.1 of [RFC2616]). */ {"MKCOL", 0, 0, 0, 1, 0}, /* http://www.webdav.org/specs/rfc4918.html, 9.1: * When MKCOL is invoked without a request body, * the newly created collection SHOULD have no * members. A MKCOL request message may contain * a message body. The precise behavior of a MKCOL * request when the body is present is undefined, * ... ==> We do not support MKCOL with body data. * This method is idempotent, but not safe (see * Section 9.1 of [RFC2616]). Responses to this * method MUST NOT be cached. */ /* Methods for write access to files on WEBDAV (RFC 2518) */ {"LOCK", 1, 1, 0, 0, 0}, {"UNLOCK", 1, 0, 0, 0, 0}, {"PROPPATCH", 1, 1, 0, 0, 0}, {"COPY", 1, 0, 0, 0, 0}, {"MOVE", 1, 1, 0, 0, 0}, /* Unsupported WEBDAV Methods: */ /* + 11 methods from RFC 3253 */ /* ORDERPATCH (RFC 3648) */ /* ACL (RFC 3744) */ /* SEARCH (RFC 5323) */ /* + MicroSoft extensions * https://msdn.microsoft.com/en-us/library/aa142917.aspx */ /* REPORT method (RFC 3253) */ {"REPORT", 1, 1, 1, 1, 1}, /* REPORT method only allowed for CGI/Lua/LSP and callbacks. */ /* It was defined for WEBDAV in RFC 3253, Sec. 3.6 * (https://tools.ietf.org/html/rfc3253#section-3.6), but seems * to be useful for REST in case a "GET request with body" is * required. */ {NULL, 0, 0, 0, 0, 0} /* end of list */ }; /* All method names */ static char *all_methods = NULL; /* Built by mg_init_library */ static const struct mg_http_method_info * get_http_method_info(const char *method) { /* Check if the method is known to the server. The list of all known * HTTP methods can be found here at * http://www.iana.org/assignments/http-methods/http-methods.xhtml */ const struct mg_http_method_info *m = http_methods; while (m->name) { if (!strcmp(m->name, method)) { return m; } m++; } return NULL; } static int is_valid_http_method(const char *method) { return (get_http_method_info(method) != NULL); } /* Parse HTTP request, fill in mg_request_info structure. * This function modifies the buffer by NUL-terminating * HTTP request components, header names and header values. * Parameters: * buf (in/out): pointer to the HTTP header to parse and split * len (in): length of HTTP header buffer * re (out): parsed header as mg_request_info * buf and ri must be valid pointers (not NULL), len>0. * Returns <0 on error. */ static int parse_http_request(char *buf, int len, struct mg_request_info *ri) { int request_length; int init_skip = 0; /* Reset attributes. DO NOT TOUCH is_ssl, remote_addr, * remote_port */ ri->remote_user = ri->request_method = ri->request_uri = ri->http_version = NULL; ri->num_headers = 0; /* RFC says that all initial whitespaces should be ignored */ /* This included all leading \r and \n (isspace) */ /* See table: http://www.cplusplus.com/reference/cctype/ */ while ((len > 0) && isspace((unsigned char)*buf)) { buf++; len--; init_skip++; } if (len == 0) { /* Incomplete request */ return 0; } /* Control characters are not allowed, including zero */ if (iscntrl((unsigned char)*buf)) { return -1; } /* Find end of HTTP header */ request_length = get_http_header_len(buf, len); if (request_length <= 0) { return request_length; } buf[request_length - 1] = '\0'; if ((*buf == 0) || (*buf == '\r') || (*buf == '\n')) { return -1; } /* The first word has to be the HTTP method */ ri->request_method = buf; if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) { return -1; } /* The second word is the URI */ ri->request_uri = buf; if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) { return -1; } /* Next would be the HTTP version */ ri->http_version = buf; if (skip_to_end_of_word_and_terminate(&buf, 1) <= 0) { return -1; } /* Check for a valid HTTP version key */ if (strncmp(ri->http_version, "HTTP/", 5) != 0) { /* Invalid request */ return -1; } ri->http_version += 5; /* Check for a valid http method */ if (!is_valid_http_method(ri->request_method)) { return -1; } /* Parse all HTTP headers */ ri->num_headers = parse_http_headers(&buf, ri->http_headers); if (ri->num_headers < 0) { /* Error while parsing headers */ return -1; } return request_length + init_skip; } static int parse_http_response(char *buf, int len, struct mg_response_info *ri) { int response_length; int init_skip = 0; char *tmp, *tmp2; long l; /* Initialize elements. */ ri->http_version = ri->status_text = NULL; ri->num_headers = ri->status_code = 0; /* RFC says that all initial whitespaces should be ignored */ /* This included all leading \r and \n (isspace) */ /* See table: http://www.cplusplus.com/reference/cctype/ */ while ((len > 0) && isspace((unsigned char)*buf)) { buf++; len--; init_skip++; } if (len == 0) { /* Incomplete request */ return 0; } /* Control characters are not allowed, including zero */ if (iscntrl((unsigned char)*buf)) { return -1; } /* Find end of HTTP header */ response_length = get_http_header_len(buf, len); if (response_length <= 0) { return response_length; } buf[response_length - 1] = '\0'; if ((*buf == 0) || (*buf == '\r') || (*buf == '\n')) { return -1; } /* The first word is the HTTP version */ /* Check for a valid HTTP version key */ if (strncmp(buf, "HTTP/", 5) != 0) { /* Invalid request */ return -1; } buf += 5; if (!isgraph((unsigned char)buf[0])) { /* Invalid request */ return -1; } ri->http_version = buf; if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) { return -1; } /* The second word is the status as a number */ tmp = buf; if (skip_to_end_of_word_and_terminate(&buf, 0) <= 0) { return -1; } l = strtol(tmp, &tmp2, 10); if ((l < 100) || (l >= 1000) || ((tmp2 - tmp) != 3) || (*tmp2 != 0)) { /* Everything else but a 3 digit code is invalid */ return -1; } ri->status_code = (int)l; /* The rest of the line is the status text */ ri->status_text = buf; /* Find end of status text */ /* isgraph or isspace = isprint */ while (isprint((unsigned char)*buf)) { buf++; } if ((*buf != '\r') && (*buf != '\n')) { return -1; } /* Terminate string and forward buf to next line */ do { *buf = 0; buf++; } while (isspace((unsigned char)*buf)); /* Parse all HTTP headers */ ri->num_headers = parse_http_headers(&buf, ri->http_headers); if (ri->num_headers < 0) { /* Error while parsing headers */ return -1; } return response_length + init_skip; } /* Keep reading the input (either opened file descriptor fd, or socket sock, * or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the * buffer (which marks the end of HTTP request). Buffer buf may already * have some data. The length of the data is stored in nread. * Upon every read operation, increase nread by the number of bytes read. */ static int read_message(FILE *fp, struct mg_connection *conn, char *buf, int bufsiz, int *nread) { int request_len, n = 0; struct timespec last_action_time; double request_timeout; if (!conn) { return 0; } memset(&last_action_time, 0, sizeof(last_action_time)); if (conn->dom_ctx->config[REQUEST_TIMEOUT]) { /* value of request_timeout is in seconds, config in milliseconds */ request_timeout = strtod(conn->dom_ctx->config[REQUEST_TIMEOUT], NULL) / 1000.0; } else { request_timeout = strtod(config_options[REQUEST_TIMEOUT].default_value, NULL) / 1000.0; } if (conn->handled_requests > 0) { if (conn->dom_ctx->config[KEEP_ALIVE_TIMEOUT]) { request_timeout = strtod(conn->dom_ctx->config[KEEP_ALIVE_TIMEOUT], NULL) / 1000.0; } } request_len = get_http_header_len(buf, *nread); while (request_len == 0) { /* Full request not yet received */ if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) { /* Server is to be stopped. */ return -1; } if (*nread >= bufsiz) { /* Request too long */ return -2; } n = pull_inner( fp, conn, buf + *nread, bufsiz - *nread, request_timeout); if (n == -2) { /* Receive error */ return -1; } /* update clock after every read request */ clock_gettime(CLOCK_MONOTONIC, &last_action_time); if (n > 0) { *nread += n; request_len = get_http_header_len(buf, *nread); } if ((request_len == 0) && (request_timeout >= 0)) { if (mg_difftimespec(&last_action_time, &(conn->req_time)) > request_timeout) { /* Timeout */ return -1; } } } return request_len; } #if !defined(NO_CGI) || !defined(NO_FILES) static int forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl) { const char *expect; char buf[MG_BUF_LEN]; int success = 0; if (!conn) { return 0; } expect = mg_get_header(conn, "Expect"); DEBUG_ASSERT(fp != NULL); if (!fp) { mg_send_http_error(conn, 500, "%s", "Error: NULL File"); return 0; } if ((expect != NULL) && (mg_strcasecmp(expect, "100-continue") != 0)) { /* Client sent an "Expect: xyz" header and xyz is not 100-continue. */ mg_send_http_error(conn, 417, "Error: Can not fulfill expectation"); } else { if (expect != NULL) { (void)mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n"); conn->status_code = 100; } else { conn->status_code = 200; } DEBUG_ASSERT(conn->consumed_content == 0); if (conn->consumed_content != 0) { mg_send_http_error(conn, 500, "%s", "Error: Size mismatch"); return 0; } for (;;) { int nread = mg_read(conn, buf, sizeof(buf)); if (nread <= 0) { success = (nread == 0); break; } if (push_all(conn->phys_ctx, fp, sock, ssl, buf, nread) != nread) { break; } } /* Each error code path in this function must send an error */ if (!success) { /* NOTE: Maybe some data has already been sent. */ /* TODO (low): If some data has been sent, a correct error * reply can no longer be sent, so just close the connection */ mg_send_http_error(conn, 500, "%s", ""); } } return success; } #endif #if defined(USE_TIMERS) #define TIMER_API static #include "timer.h" #endif /* USE_TIMERS */ #if !defined(NO_CGI) /* This structure helps to create an environment for the spawned CGI * program. * Environment is an array of "VARIABLE=VALUE\0" ASCII strings, * last element must be NULL. * However, on Windows there is a requirement that all these * VARIABLE=VALUE\0 * strings must reside in a contiguous buffer. The end of the buffer is * marked by two '\0' characters. * We satisfy both worlds: we create an envp array (which is vars), all * entries are actually pointers inside buf. */ struct cgi_environment { struct mg_connection *conn; /* Data block */ char *buf; /* Environment buffer */ size_t buflen; /* Space available in buf */ size_t bufused; /* Space taken in buf */ /* Index block */ char **var; /* char **envp */ size_t varlen; /* Number of variables available in var */ size_t varused; /* Number of variables stored in var */ }; static void addenv(struct cgi_environment *env, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3); /* Append VARIABLE=VALUE\0 string to the buffer, and add a respective * pointer into the vars array. Assumes env != NULL and fmt != NULL. */ static void addenv(struct cgi_environment *env, const char *fmt, ...) { size_t i, n, space; int truncated = 0; char *added; va_list ap; if ((env->varlen - env->varused) < 2) { mg_cry_internal(env->conn, "%s: Cannot register CGI variable [%s]", __func__, fmt); return; } /* Calculate how much space is left in the buffer */ space = (env->buflen - env->bufused); do { /* Space for "\0\0" is always needed. */ if (space <= 2) { /* Allocate new buffer */ n = env->buflen + CGI_ENVIRONMENT_SIZE; added = (char *)mg_realloc_ctx(env->buf, n, env->conn->phys_ctx); if (!added) { /* Out of memory */ mg_cry_internal( env->conn, "%s: Cannot allocate memory for CGI variable [%s]", __func__, fmt); return; } /* Retarget pointers */ env->buf = added; env->buflen = n; for (i = 0, n = 0; i < env->varused; i++) { env->var[i] = added + n; n += strlen(added + n) + 1; } space = (env->buflen - env->bufused); } /* Make a pointer to the free space int the buffer */ added = env->buf + env->bufused; /* Copy VARIABLE=VALUE\0 string into the free space */ va_start(ap, fmt); mg_vsnprintf(env->conn, &truncated, added, space - 1, fmt, ap); va_end(ap); /* Do not add truncated strings to the environment */ if (truncated) { /* Reallocate the buffer */ space = 0; } } while (truncated); /* Calculate number of bytes added to the environment */ n = strlen(added) + 1; env->bufused += n; /* Append a pointer to the added string into the envp array */ env->var[env->varused] = added; env->varused++; } /* Return 0 on success, non-zero if an error occurs. */ static int prepare_cgi_environment(struct mg_connection *conn, const char *prog, struct cgi_environment *env, int cgi_config_idx) { const char *s; struct vec var_vec; char *p, src_addr[IP_ADDR_STR_LEN], http_var_name[128]; int i, truncated, uri_len; if ((conn == NULL) || (prog == NULL) || (env == NULL)) { return -1; } env->conn = conn; env->buflen = CGI_ENVIRONMENT_SIZE; env->bufused = 0; env->buf = (char *)mg_malloc_ctx(env->buflen, conn->phys_ctx); if (env->buf == NULL) { mg_cry_internal(conn, "%s: Not enough memory for environmental buffer", __func__); return -1; } env->varlen = MAX_CGI_ENVIR_VARS; env->varused = 0; env->var = (char **)mg_malloc_ctx(env->varlen * sizeof(char *), conn->phys_ctx); if (env->var == NULL) { mg_cry_internal(conn, "%s: Not enough memory for environmental variables", __func__); mg_free(env->buf); return -1; } addenv(env, "SERVER_NAME=%s", conn->dom_ctx->config[AUTHENTICATION_DOMAIN]); addenv(env, "SERVER_ROOT=%s", conn->dom_ctx->config[DOCUMENT_ROOT]); addenv(env, "DOCUMENT_ROOT=%s", conn->dom_ctx->config[DOCUMENT_ROOT]); addenv(env, "SERVER_SOFTWARE=CivetWeb/%s", mg_version()); /* Prepare the environment block */ addenv(env, "%s", "GATEWAY_INTERFACE=CGI/1.1"); addenv(env, "%s", "SERVER_PROTOCOL=HTTP/1.1"); addenv(env, "%s", "REDIRECT_STATUS=200"); /* For PHP */ addenv(env, "SERVER_PORT=%d", conn->request_info.server_port); sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); addenv(env, "REMOTE_ADDR=%s", src_addr); addenv(env, "REQUEST_METHOD=%s", conn->request_info.request_method); addenv(env, "REMOTE_PORT=%d", conn->request_info.remote_port); addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri); addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri); addenv(env, "LOCAL_URI_RAW=%s", conn->request_info.local_uri_raw); /* SCRIPT_NAME */ uri_len = (int)strlen(conn->request_info.local_uri); if (conn->path_info == NULL) { if (conn->request_info.local_uri[uri_len - 1] != '/') { /* URI: /path_to_script/script.cgi */ addenv(env, "SCRIPT_NAME=%s", conn->request_info.local_uri); } else { /* URI: /path_to_script/ ... using index.cgi */ const char *index_file = strrchr(prog, '/'); if (index_file) { addenv(env, "SCRIPT_NAME=%s%s", conn->request_info.local_uri, index_file + 1); } } } else { /* URI: /path_to_script/script.cgi/path_info */ addenv(env, "SCRIPT_NAME=%.*s", uri_len - (int)strlen(conn->path_info), conn->request_info.local_uri); } addenv(env, "SCRIPT_FILENAME=%s", prog); if (conn->path_info == NULL) { addenv(env, "PATH_TRANSLATED=%s", conn->dom_ctx->config[DOCUMENT_ROOT]); } else { addenv(env, "PATH_TRANSLATED=%s%s", conn->dom_ctx->config[DOCUMENT_ROOT], conn->path_info); } addenv(env, "HTTPS=%s", (conn->ssl == NULL) ? "off" : "on"); if ((s = mg_get_header(conn, "Content-Type")) != NULL) { addenv(env, "CONTENT_TYPE=%s", s); } if (conn->request_info.query_string != NULL) { addenv(env, "QUERY_STRING=%s", conn->request_info.query_string); } if ((s = mg_get_header(conn, "Content-Length")) != NULL) { addenv(env, "CONTENT_LENGTH=%s", s); } if ((s = getenv("PATH")) != NULL) { addenv(env, "PATH=%s", s); } if (conn->path_info != NULL) { addenv(env, "PATH_INFO=%s", conn->path_info); } if (conn->status_code > 0) { /* CGI error handler should show the status code */ addenv(env, "STATUS=%d", conn->status_code); } #if defined(_WIN32) if ((s = getenv("COMSPEC")) != NULL) { addenv(env, "COMSPEC=%s", s); } if ((s = getenv("SYSTEMROOT")) != NULL) { addenv(env, "SYSTEMROOT=%s", s); } if ((s = getenv("SystemDrive")) != NULL) { addenv(env, "SystemDrive=%s", s); } if ((s = getenv("ProgramFiles")) != NULL) { addenv(env, "ProgramFiles=%s", s); } if ((s = getenv("ProgramFiles(x86)")) != NULL) { addenv(env, "ProgramFiles(x86)=%s", s); } #else if ((s = getenv("LD_LIBRARY_PATH")) != NULL) { addenv(env, "LD_LIBRARY_PATH=%s", s); } #endif /* _WIN32 */ if ((s = getenv("PERLLIB")) != NULL) { addenv(env, "PERLLIB=%s", s); } if (conn->request_info.remote_user != NULL) { addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user); addenv(env, "%s", "AUTH_TYPE=Digest"); } /* Add all headers as HTTP_* variables */ for (i = 0; i < conn->request_info.num_headers; i++) { (void)mg_snprintf(conn, &truncated, http_var_name, sizeof(http_var_name), "HTTP_%s", conn->request_info.http_headers[i].name); if (truncated) { mg_cry_internal(conn, "%s: HTTP header variable too long [%s]", __func__, conn->request_info.http_headers[i].name); continue; } /* Convert variable name into uppercase, and change - to _ */ for (p = http_var_name; *p != '\0'; p++) { if (*p == '-') { *p = '_'; } *p = (char)toupper((unsigned char)*p); } addenv(env, "%s=%s", http_var_name, conn->request_info.http_headers[i].value); } /* Add user-specified variables */ s = conn->dom_ctx->config[CGI_ENVIRONMENT + cgi_config_idx]; while ((s = next_option(s, &var_vec, NULL)) != NULL) { addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr); } env->var[env->varused] = NULL; env->buf[env->bufused] = '\0'; return 0; } /* Data for CGI process control: PID and number of references */ struct process_control_data { pid_t pid; ptrdiff_t references; }; static int abort_cgi_process(void *data) { /* Waitpid checks for child status and won't work for a pid that does * not identify a child of the current process. Thus, if the pid is * reused, we will not affect a different process. */ struct process_control_data *proc = (struct process_control_data *)data; int status = 0; ptrdiff_t refs; pid_t ret_pid; ret_pid = waitpid(proc->pid, &status, WNOHANG); if ((ret_pid != (pid_t)-1) && (status == 0)) { /* Stop child process */ DEBUG_TRACE("CGI timer: Stop child process %d\n", proc->pid); kill(proc->pid, SIGABRT); /* Wait until process is terminated (don't leave zombies) */ while (waitpid(proc->pid, &status, 0) != (pid_t)-1) /* nop */ ; } else { DEBUG_TRACE("CGI timer: Child process %d already stopped\n", proc->pid); } /* Dec reference counter */ refs = mg_atomic_dec(&proc->references); if (refs == 0) { /* no more references - free data */ mg_free(data); } return 0; } /* Local (static) function assumes all arguments are valid. */ static void handle_cgi_request(struct mg_connection *conn, const char *prog, int cgi_config_idx) { char *buf; size_t buflen; int headers_len, data_len, i, truncated; int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1}; const char *status, *status_text; char *pbuf, dir[UTF8_PATH_MAX], *p; struct mg_request_info ri; struct cgi_environment blk; FILE *in = NULL, *out = NULL, *err = NULL; struct mg_file fout = STRUCT_FILE_INITIALIZER; pid_t pid = (pid_t)-1; struct process_control_data *proc = NULL; char *cfg_buffering = conn->dom_ctx->config[CGI_BUFFERING + cgi_config_idx]; int no_buffering = 0; #if defined(USE_TIMERS) double cgi_timeout; if (conn->dom_ctx->config[CGI_TIMEOUT + cgi_config_idx]) { /* Get timeout in seconds */ cgi_timeout = atof(conn->dom_ctx->config[CGI_TIMEOUT + cgi_config_idx]) * 0.001; } else { cgi_timeout = atof(config_options[REQUEST_TIMEOUT].default_value) * 0.001; } #endif if (cfg_buffering != NULL) { if (!mg_strcasecmp(cfg_buffering, "no")) { no_buffering = 1; } } buf = NULL; buflen = conn->phys_ctx->max_request_size; i = prepare_cgi_environment(conn, prog, &blk, cgi_config_idx); if (i != 0) { blk.buf = NULL; blk.var = NULL; goto done; } /* CGI must be executed in its own directory. 'dir' must point to the * directory containing executable program, 'p' must point to the * executable program name relative to 'dir'. */ (void)mg_snprintf(conn, &truncated, dir, sizeof(dir), "%s", prog); if (truncated) { mg_cry_internal(conn, "Error: CGI program \"%s\": Path too long", prog); mg_send_http_error(conn, 500, "Error: %s", "CGI path too long"); goto done; } if ((p = strrchr(dir, '/')) != NULL) { *p++ = '\0'; } else { dir[0] = '.'; dir[1] = '\0'; p = (char *)prog; } if ((pipe(fdin) != 0) || (pipe(fdout) != 0) || (pipe(fderr) != 0)) { status = strerror(ERRNO); mg_cry_internal( conn, "Error: CGI program \"%s\": Can not create CGI pipes: %s", prog, status); mg_send_http_error(conn, 500, "Error: Cannot create CGI pipe: %s", status); goto done; } proc = (struct process_control_data *) mg_malloc_ctx(sizeof(struct process_control_data), conn->phys_ctx); if (proc == NULL) { mg_cry_internal(conn, "Error: CGI program \"%s\": Out or memory", prog); mg_send_http_error(conn, 500, "Error: Out of memory [%s]", prog); goto done; } DEBUG_TRACE("CGI: spawn %s %s\n", dir, p); pid = spawn_process( conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir, cgi_config_idx); if (pid == (pid_t)-1) { status = strerror(ERRNO); mg_cry_internal( conn, "Error: CGI program \"%s\": Can not spawn CGI process: %s", prog, status); mg_send_http_error(conn, 500, "Error: Cannot spawn CGI process"); mg_free(proc); proc = NULL; goto done; } /* Store data in shared process_control_data */ proc->pid = pid; proc->references = 1; #if defined(USE_TIMERS) if (cgi_timeout > 0.0) { proc->references = 2; // Start a timer for CGI timer_add(conn->phys_ctx, cgi_timeout /* in seconds */, 0.0, 1, abort_cgi_process, (void *)proc, NULL); } #endif /* Parent closes only one side of the pipes. * If we don't mark them as closed, close() attempt before * return from this function throws an exception on Windows. * Windows does not like when closed descriptor is closed again. */ (void)close(fdin[0]); (void)close(fdout[1]); (void)close(fderr[1]); fdin[0] = fdout[1] = fderr[1] = -1; if (((in = fdopen(fdin[1], "wb")) == NULL) || ((out = fdopen(fdout[0], "rb")) == NULL) || ((err = fdopen(fderr[0], "rb")) == NULL)) { status = strerror(ERRNO); mg_cry_internal(conn, "Error: CGI program \"%s\": Can not open fd: %s", prog, status); mg_send_http_error(conn, 500, "Error: CGI can not open fd\nfdopen: %s", status); goto done; } setbuf(in, NULL); setbuf(out, NULL); setbuf(err, NULL); fout.access.fp = out; if ((conn->content_len != 0) || (conn->is_chunked)) { DEBUG_TRACE("CGI: send body data (%" INT64_FMT ")\n", conn->content_len); /* This is a POST/PUT request, or another request with body data. */ if (!forward_body_data(conn, in, INVALID_SOCKET, NULL)) { /* Error sending the body data */ mg_cry_internal( conn, "Error: CGI program \"%s\": Forward body data failed", prog); goto done; } } /* Close so child gets an EOF. */ fclose(in); in = NULL; fdin[1] = -1; /* Now read CGI reply into a buffer. We need to set correct * status code, thus we need to see all HTTP headers first. * Do not send anything back to client, until we buffer in all * HTTP headers. */ data_len = 0; buf = (char *)mg_malloc_ctx(buflen, conn->phys_ctx); if (buf == NULL) { mg_send_http_error(conn, 500, "Error: Not enough memory for CGI buffer (%u bytes)", (unsigned int)buflen); mg_cry_internal( conn, "Error: CGI program \"%s\": Not enough memory for buffer (%u " "bytes)", prog, (unsigned int)buflen); goto done; } DEBUG_TRACE("CGI: %s", "wait for response"); headers_len = read_message(out, conn, buf, (int)buflen, &data_len); DEBUG_TRACE("CGI: response: %li", (signed long)headers_len); if (headers_len <= 0) { /* Could not parse the CGI response. Check if some error message on * stderr. */ i = pull_all(err, conn, buf, (int)buflen); if (i > 0) { /* CGI program explicitly sent an error */ /* Write the error message to the internal log */ mg_cry_internal(conn, "Error: CGI program \"%s\" sent error " "message: [%.*s]", prog, i, buf); /* Don't send the error message back to the client */ mg_send_http_error(conn, 500, "Error: CGI program \"%s\" failed.", prog); } else { /* CGI program did not explicitly send an error, but a broken * respon header */ mg_cry_internal(conn, "Error: CGI program sent malformed or too big " "(>%u bytes) HTTP headers: [%.*s]", (unsigned)buflen, data_len, buf); mg_send_http_error(conn, 500, "Error: CGI program sent malformed or too big " "(>%u bytes) HTTP headers: [%.*s]", (unsigned)buflen, data_len, buf); } /* in both cases, abort processing CGI */ goto done; } pbuf = buf; buf[headers_len - 1] = '\0'; ri.num_headers = parse_http_headers(&pbuf, ri.http_headers); /* Make up and send the status line */ status_text = "OK"; if ((status = get_header(ri.http_headers, ri.num_headers, "Status")) != NULL) { conn->status_code = atoi(status); status_text = status; while (isdigit((unsigned char)*status_text) || *status_text == ' ') { status_text++; } } else if (get_header(ri.http_headers, ri.num_headers, "Location") != NULL) { conn->status_code = 307; } else { conn->status_code = 200; } if (!should_keep_alive(conn)) { conn->must_close = 1; } DEBUG_TRACE("CGI: response %u %s", conn->status_code, status_text); (void)mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, status_text); /* Send headers */ for (i = 0; i < ri.num_headers; i++) { DEBUG_TRACE("CGI header: %s: %s", ri.http_headers[i].name, ri.http_headers[i].value); mg_printf(conn, "%s: %s\r\n", ri.http_headers[i].name, ri.http_headers[i].value); } mg_write(conn, "\r\n", 2); /* Send chunk of data that may have been read after the headers */ mg_write(conn, buf + headers_len, (size_t)(data_len - headers_len)); /* Read the rest of CGI output and send to the client */ DEBUG_TRACE("CGI: %s", "forward all data"); send_file_data(conn, &fout, 0, INT64_MAX, no_buffering); /* send CGI data */ DEBUG_TRACE("CGI: %s", "all data sent"); done: mg_free(blk.var); mg_free(blk.buf); if (pid != (pid_t)-1) { abort_cgi_process((void *)proc); } if (fdin[0] != -1) { close(fdin[0]); } if (fdout[1] != -1) { close(fdout[1]); } if (fderr[1] != -1) { close(fderr[1]); } if (in != NULL) { fclose(in); } else if (fdin[1] != -1) { close(fdin[1]); } if (out != NULL) { fclose(out); } else if (fdout[0] != -1) { close(fdout[0]); } if (err != NULL) { fclose(err); } else if (fderr[0] != -1) { close(fderr[0]); } mg_free(buf); } #endif /* !NO_CGI */ #if !defined(NO_FILES) static void dav_mkcol(struct mg_connection *conn, const char *path) { int rc, body_len; struct de de; if (conn == NULL) { return; } /* TODO (mid): Check the mg_send_http_error situations in this function */ memset(&de.file, 0, sizeof(de.file)); if (!mg_stat(conn, path, &de.file)) { mg_cry_internal(conn, "%s: mg_stat(%s) failed: %s", __func__, path, strerror(ERRNO)); } if (de.file.last_modified) { /* TODO (mid): This check does not seem to make any sense ! */ /* TODO (mid): Add a webdav unit test first, before changing * anything here. */ mg_send_http_error( conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO)); return; } body_len = conn->data_len - conn->request_len; if (body_len > 0) { mg_send_http_error( conn, 415, "Error: mkcol(%s): %s", path, strerror(ERRNO)); return; } rc = mg_mkdir(conn, path, 0755); DEBUG_TRACE("mkdir %s: %i", path, rc); if (rc == 0) { /* Create 201 "Created" response */ mg_response_header_start(conn, 201); send_static_cache_header(conn); send_additional_header(conn); mg_response_header_add(conn, "Content-Length", "0", -1); /* Send all headers - there is no body */ mg_response_header_send(conn); } else { int http_status = 500; switch (errno) { case EEXIST: http_status = 405; break; case EACCES: http_status = 403; break; case ENOENT: http_status = 409; break; } mg_send_http_error(conn, http_status, "Error processing %s: %s", path, strerror(ERRNO)); } } /* Forward decrlaration */ static int get_uri_type(const char *uri); static const char * get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn); static void dav_move_file(struct mg_connection *conn, const char *path, int do_copy) { const char *overwrite_hdr; const char *destination_hdr; const char *root; int rc, dest_uri_type; int http_status = 400; int do_overwrite = 0; int destination_ok = 0; char dest_path[UTF8_PATH_MAX]; struct mg_file_stat ignored; if (conn == NULL) { return; } root = conn->dom_ctx->config[DOCUMENT_ROOT]; overwrite_hdr = mg_get_header(conn, "Overwrite"); destination_hdr = mg_get_header(conn, "Destination"); if ((overwrite_hdr != NULL) && (toupper(overwrite_hdr[0]) == 'T')) { do_overwrite = 1; } if ((destination_hdr == NULL) || (destination_hdr[0] == 0)) { mg_send_http_error(conn, 400, "%s", "Missing destination"); return; } if (root != NULL) { char *local_dest = NULL; dest_uri_type = get_uri_type(destination_hdr); if (dest_uri_type == 2) { local_dest = mg_strdup_ctx(destination_hdr, conn->phys_ctx); } else if ((dest_uri_type == 3) || (dest_uri_type == 4)) { const char *h = get_rel_url_at_current_server(destination_hdr, conn); if (h) { size_t len = strlen(h); local_dest = mg_malloc_ctx(len + 1, conn->phys_ctx); mg_url_decode(h, (int)len, local_dest, (int)len + 1, 0); } } if (local_dest != NULL) { remove_dot_segments(local_dest); if (local_dest[0] == '/') { int trunc_check = 0; mg_snprintf(conn, &trunc_check, dest_path, sizeof(dest_path), "%s/%s", root, local_dest); if (trunc_check == 0) { destination_ok = 1; } } mg_free(local_dest); } } if (!destination_ok) { mg_send_http_error(conn, 502, "%s", "Illegal destination"); return; } /* Check now if this file exists */ if (mg_stat(conn, dest_path, &ignored)) { /* File exists */ if (do_overwrite) { /* Overwrite allowed: delete the file first */ if (0 != remove(dest_path)) { /* No overwrite: return error */ mg_send_http_error(conn, 403, "Cannot overwrite file: %s", dest_path); return; } } else { /* No overwrite: return error */ mg_send_http_error(conn, 412, "Destination already exists: %s", dest_path); return; } } /* Copy / Move / Rename operation. */ DEBUG_TRACE("%s %s to %s", (do_copy ? "copy" : "move"), path, dest_path); #if defined(_WIN32) { /* For Windows, we need to convert from UTF-8 to UTF-16 first. */ wchar_t wSource[UTF16_PATH_MAX]; wchar_t wDest[UTF16_PATH_MAX]; BOOL ok; path_to_unicode(conn, path, wSource, ARRAY_SIZE(wSource)); path_to_unicode(conn, dest_path, wDest, ARRAY_SIZE(wDest)); if (do_copy) { ok = CopyFileW(wSource, wDest, do_overwrite ? FALSE : TRUE); } else { ok = MoveFileExW(wSource, wDest, do_overwrite ? MOVEFILE_REPLACE_EXISTING : 0); } if (ok) { rc = 0; } else { DWORD lastErr = GetLastError(); if (lastErr == ERROR_ALREADY_EXISTS) { mg_send_http_error(conn, 412, "Destination already exists: %s", dest_path); return; } rc = -1; http_status = 400; } } #else { /* Linux uses already UTF-8, we don't need to convert file names. */ if (do_copy) { /* TODO: COPY for Linux. */ mg_send_http_error(conn, 403, "%s", "COPY forbidden"); return; } rc = rename(path, dest_path); if (rc) { switch (errno) { case EEXIST: http_status = 412; break; case EACCES: http_status = 403; break; case ENOENT: http_status = 409; break; } } } #endif if (rc == 0) { /* Create 204 "No Content" response */ mg_response_header_start(conn, 204); mg_response_header_add(conn, "Content-Length", "0", -1); /* Send all headers - there is no body */ mg_response_header_send(conn); } else { mg_send_http_error(conn, http_status, "Operation failed"); } } static void put_file(struct mg_connection *conn, const char *path) { struct mg_file file = STRUCT_FILE_INITIALIZER; const char *range; int64_t r1, r2; int rc; if (conn == NULL) { return; } DEBUG_TRACE("store %s", path); if (mg_stat(conn, path, &file.stat)) { /* File already exists */ conn->status_code = 200; if (file.stat.is_directory) { /* This is an already existing directory, * so there is nothing to do for the server. */ rc = 0; } else { /* File exists and is not a directory. */ /* Can it be replaced? */ /* Check if the server may write this file */ if (access(path, W_OK) == 0) { /* Access granted */ rc = 1; } else { mg_send_http_error( conn, 403, "Error: Put not possible\nReplacing %s is not allowed", path); return; } } } else { /* File should be created */ conn->status_code = 201; rc = put_dir(conn, path); } if (rc == 0) { /* put_dir returns 0 if path is a directory */ /* Create response */ mg_response_header_start(conn, conn->status_code); send_no_cache_header(conn); send_additional_header(conn); mg_response_header_add(conn, "Content-Length", "0", -1); /* Send all headers - there is no body */ mg_response_header_send(conn); /* Request to create a directory has been fulfilled successfully. * No need to put a file. */ return; } if (rc == -1) { /* put_dir returns -1 if the path is too long */ mg_send_http_error(conn, 414, "Error: Path too long\nput_dir(%s): %s", path, strerror(ERRNO)); return; } if (rc == -2) { /* put_dir returns -2 if the directory can not be created */ mg_send_http_error(conn, 500, "Error: Can not create directory\nput_dir(%s): %s", path, strerror(ERRNO)); return; } /* A file should be created or overwritten. */ /* Currently CivetWeb does not need read+write access. */ if (!mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &file) || file.access.fp == NULL) { (void)mg_fclose(&file.access); mg_send_http_error(conn, 500, "Error: Can not create file\nfopen(%s): %s", path, strerror(ERRNO)); return; } fclose_on_exec(&file.access, conn); range = mg_get_header(conn, "Content-Range"); r1 = r2 = 0; if ((range != NULL) && parse_range_header(range, &r1, &r2) > 0) { conn->status_code = 206; /* Partial content */ if (0 != fseeko(file.access.fp, r1, SEEK_SET)) { mg_send_http_error(conn, 500, "Error: Internal error processing file %s", path); return; } } if (!forward_body_data(conn, file.access.fp, INVALID_SOCKET, NULL)) { /* forward_body_data failed. * The error code has already been sent to the client, * and conn->status_code is already set. */ (void)mg_fclose(&file.access); return; } if (mg_fclose(&file.access) != 0) { /* fclose failed. This might have different reasons, but a likely * one is "no space on disk", http 507. */ conn->status_code = 507; } /* Create response (status_code has been set before) */ mg_response_header_start(conn, conn->status_code); send_no_cache_header(conn); send_additional_header(conn); mg_response_header_add(conn, "Content-Length", "0", -1); /* Send all headers - there is no body */ mg_response_header_send(conn); } static void delete_file(struct mg_connection *conn, const char *path) { struct de de; memset(&de.file, 0, sizeof(de.file)); if (!mg_stat(conn, path, &de.file)) { /* mg_stat returns 0 if the file does not exist */ mg_send_http_error(conn, 404, "Error: Cannot delete file\nFile %s not found", path); return; } DEBUG_TRACE("delete %s", path); if (de.file.is_directory) { if (remove_directory(conn, path)) { /* Delete is successful: Return 204 without content. */ mg_send_http_error(conn, 204, "%s", ""); } else { /* Delete is not successful: Return 500 (Server error). */ mg_send_http_error(conn, 500, "Error: Could not delete %s", path); } return; } /* This is an existing file (not a directory). * Check if write permission is granted. */ if (access(path, W_OK) != 0) { /* File is read only */ mg_send_http_error( conn, 403, "Error: Delete not possible\nDeleting %s is not allowed", path); return; } /* Try to delete it. */ if (mg_remove(conn, path) == 0) { /* Delete was successful: Return 204 without content. */ mg_response_header_start(conn, 204); send_no_cache_header(conn); send_additional_header(conn); mg_response_header_add(conn, "Content-Length", "0", -1); mg_response_header_send(conn); } else { /* Delete not successful (file locked). */ mg_send_http_error(conn, 423, "Error: Cannot delete file\nremove(%s): %s", path, strerror(ERRNO)); } } #endif /* !NO_FILES */ #if !defined(NO_FILESYSTEMS) static void send_ssi_file(struct mg_connection *, const char *, struct mg_file *, int); static void do_ssi_include(struct mg_connection *conn, const char *ssi, char *tag, int include_level) { char file_name[MG_BUF_LEN], path[512], *p; struct mg_file file = STRUCT_FILE_INITIALIZER; size_t len; int truncated = 0; if (conn == NULL) { return; } /* sscanf() is safe here, since send_ssi_file() also uses buffer * of size MG_BUF_LEN to get the tag. So strlen(tag) is * always < MG_BUF_LEN. */ if (sscanf(tag, " virtual=\"%511[^\"]\"", file_name) == 1) { /* File name is relative to the webserver root */ file_name[511] = 0; (void)mg_snprintf(conn, &truncated, path, sizeof(path), "%s/%s", conn->dom_ctx->config[DOCUMENT_ROOT], file_name); } else if (sscanf(tag, " abspath=\"%511[^\"]\"", file_name) == 1) { /* File name is relative to the webserver working directory * or it is absolute system path */ file_name[511] = 0; (void) mg_snprintf(conn, &truncated, path, sizeof(path), "%s", file_name); } else if ((sscanf(tag, " file=\"%511[^\"]\"", file_name) == 1) || (sscanf(tag, " \"%511[^\"]\"", file_name) == 1)) { /* File name is relative to the current document */ file_name[511] = 0; (void)mg_snprintf(conn, &truncated, path, sizeof(path), "%s", ssi); if (!truncated) { if ((p = strrchr(path, '/')) != NULL) { p[1] = '\0'; } len = strlen(path); (void)mg_snprintf(conn, &truncated, path + len, sizeof(path) - len, "%s", file_name); } } else { mg_cry_internal(conn, "Bad SSI #include: [%s]", tag); return; } if (truncated) { mg_cry_internal(conn, "SSI #include path length overflow: [%s]", tag); return; } if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, &file)) { mg_cry_internal(conn, "Cannot open SSI #include: [%s]: fopen(%s): %s", tag, path, strerror(ERRNO)); } else { fclose_on_exec(&file.access, conn); if (match_prefix_strlen(conn->dom_ctx->config[SSI_EXTENSIONS], path) > 0) { send_ssi_file(conn, path, &file, include_level + 1); } else { send_file_data(conn, &file, 0, INT64_MAX, 0); /* send static file */ } (void)mg_fclose(&file.access); /* Ignore errors for readonly files */ } } #if !defined(NO_POPEN) static void do_ssi_exec(struct mg_connection *conn, char *tag) { char cmd[1024] = ""; struct mg_file file = STRUCT_FILE_INITIALIZER; if (sscanf(tag, " \"%1023[^\"]\"", cmd) != 1) { mg_cry_internal(conn, "Bad SSI #exec: [%s]", tag); } else { cmd[1023] = 0; if ((file.access.fp = popen(cmd, "r")) == NULL) { mg_cry_internal(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO)); } else { send_file_data(conn, &file, 0, INT64_MAX, 0); /* send static file */ pclose(file.access.fp); } } } #endif /* !NO_POPEN */ static int mg_fgetc(struct mg_file *filep) { if (filep == NULL) { return EOF; } if (filep->access.fp != NULL) { return fgetc(filep->access.fp); } else { return EOF; } } static void send_ssi_file(struct mg_connection *conn, const char *path, struct mg_file *filep, int include_level) { char buf[MG_BUF_LEN]; int ch, len, in_tag, in_ssi_tag; if (include_level > 10) { mg_cry_internal(conn, "SSI #include level is too deep (%s)", path); return; } in_tag = in_ssi_tag = len = 0; /* Read file, byte by byte, and look for SSI include tags */ while ((ch = mg_fgetc(filep)) != EOF) { if (in_tag) { /* We are in a tag, either SSI tag or html tag */ if (ch == '>') { /* Tag is closing */ buf[len++] = '>'; if (in_ssi_tag) { /* Handle SSI tag */ buf[len] = 0; if ((len > 12) && !memcmp(buf + 5, "include", 7)) { do_ssi_include(conn, path, buf + 12, include_level + 1); #if !defined(NO_POPEN) } else if ((len > 9) && !memcmp(buf + 5, "exec", 4)) { do_ssi_exec(conn, buf + 9); #endif /* !NO_POPEN */ } else { mg_cry_internal(conn, "%s: unknown SSI " "command: \"%s\"", path, buf); } len = 0; in_ssi_tag = in_tag = 0; } else { /* Not an SSI tag */ /* Flush buffer */ (void)mg_write(conn, buf, (size_t)len); len = 0; in_tag = 0; } } else { /* Tag is still open */ buf[len++] = (char)(ch & 0xff); if ((len == 5) && !memcmp(buf, " Error */ return -1; } /* Upgrade to ... */ if (0 != mg_strcasestr(upgrade_to, "websocket")) { /* The headers "Host", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol" and * "Sec-WebSocket-Version" are also required. * Don't check them here, since even an unsupported websocket protocol * request still IS a websocket request (in contrast to a standard HTTP * request). It will fail later in handle_websocket_request. */ return PROTOCOL_TYPE_WEBSOCKET; /* Websocket */ } if (0 != mg_strcasestr(upgrade_to, "h2")) { return PROTOCOL_TYPE_HTTP2; /* Websocket */ } /* Upgrade to another protocol */ return -1; } static int parse_match_net(const struct vec *vec, const union usa *sa, int no_strict) { int n; unsigned int a, b, c, d, slash; if (sscanf(vec->ptr, "%u.%u.%u.%u/%u%n", &a, &b, &c, &d, &slash, &n) != 5) { // NOLINT(cert-err34-c) 'sscanf' used to convert a string to an // integer value, but function will not report conversion // errors; consider using 'strtol' instead slash = 32; if (sscanf(vec->ptr, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) != 4) { // NOLINT(cert-err34-c) 'sscanf' used to convert a string to // an integer value, but function will not report conversion // errors; consider using 'strtol' instead n = 0; } } if ((n > 0) && ((size_t)n == vec->len)) { if ((a < 256) && (b < 256) && (c < 256) && (d < 256) && (slash < 33)) { /* IPv4 format */ if (sa->sa.sa_family == AF_INET) { uint32_t ip = ntohl(sa->sin.sin_addr.s_addr); uint32_t net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d; uint32_t mask = slash ? (0xFFFFFFFFu << (32 - slash)) : 0; return (ip & mask) == net; } return 0; } } #if defined(USE_IPV6) else { char ad[50]; const char *p; if (sscanf(vec->ptr, "[%49[^]]]/%u%n", ad, &slash, &n) != 2) { slash = 128; if (sscanf(vec->ptr, "[%49[^]]]%n", ad, &n) != 1) { n = 0; } } if ((n <= 0) && no_strict) { /* no square brackets? */ p = strchr(vec->ptr, '/'); if (p && (p < (vec->ptr + vec->len))) { if (((size_t)(p - vec->ptr) < sizeof(ad)) && (sscanf(p, "/%u%n", &slash, &n) == 1)) { n += (int)(p - vec->ptr); mg_strlcpy(ad, vec->ptr, (size_t)(p - vec->ptr) + 1); } else { n = 0; } } else if (vec->len < sizeof(ad)) { n = (int)vec->len; slash = 128; mg_strlcpy(ad, vec->ptr, vec->len + 1); } } if ((n > 0) && ((size_t)n == vec->len) && (slash < 129)) { p = ad; c = 0; /* zone indexes are unsupported, at least two colons are needed */ while (isxdigit((unsigned char)*p) || (*p == '.') || (*p == ':')) { if (*(p++) == ':') { c++; } } if ((*p == '\0') && (c >= 2)) { struct sockaddr_in6 sin6; unsigned int i; /* for strict validation, an actual IPv6 argument is needed */ if (sa->sa.sa_family != AF_INET6) { return 0; } if (mg_inet_pton(AF_INET6, ad, &sin6, sizeof(sin6), 0)) { /* IPv6 format */ for (i = 0; i < 16; i++) { uint8_t ip = sa->sin6.sin6_addr.s6_addr[i]; uint8_t net = sin6.sin6_addr.s6_addr[i]; uint8_t mask = 0; if (8 * i + 8 < slash) { mask = 0xFFu; } else if (8 * i < slash) { mask = (uint8_t)(0xFFu << (8 * i + 8 - slash)); } if ((ip & mask) != net) { return 0; } } return 1; } } } } #else (void)no_strict; #endif /* malformed */ return -1; } static int set_throttle(const char *spec, const union usa *rsa, const char *uri) { int throttle = 0; struct vec vec, val; char mult; double v; while ((spec = next_option(spec, &vec, &val)) != NULL) { mult = ','; if ((val.ptr == NULL) || (sscanf(val.ptr, "%lf%c", &v, &mult) < 1) // NOLINT(cert-err34-c) 'sscanf' used to convert a string // to an integer value, but function will not report // conversion errors; consider using 'strtol' instead || (v < 0) || ((lowercase(&mult) != 'k') && (lowercase(&mult) != 'm') && (mult != ','))) { continue; } v *= (lowercase(&mult) == 'k') ? 1024 : ((lowercase(&mult) == 'm') ? 1048576 : 1); if (vec.len == 1 && vec.ptr[0] == '*') { throttle = (int)v; } else { int matched = parse_match_net(&vec, rsa, 0); if (matched >= 0) { /* a valid IP subnet */ if (matched) { throttle = (int)v; } } else if (match_prefix(vec.ptr, vec.len, uri) > 0) { throttle = (int)v; } } } return throttle; } /* The mg_upload function is superseded by mg_handle_form_request. */ #include "handle_form.h" static int get_first_ssl_listener_index(const struct mg_context *ctx) { unsigned int i; int idx = -1; if (ctx) { for (i = 0; ((idx == -1) && (i < ctx->num_listening_sockets)); i++) { idx = ctx->listening_sockets[i].is_ssl ? ((int)(i)) : -1; } } return idx; } /* Return host (without port) */ static void get_host_from_request_info(struct vec *host, const struct mg_request_info *ri) { const char *host_header = get_header(ri->http_headers, ri->num_headers, "Host"); host->ptr = NULL; host->len = 0; if (host_header != NULL) { const char *pos; /* If the "Host" is an IPv6 address, like [::1], parse until ] * is found. */ if (*host_header == '[') { pos = strchr(host_header, ']'); if (!pos) { /* Malformed hostname starts with '[', but no ']' found */ DEBUG_TRACE("%s", "Host name format error '[' without ']'"); return; } /* terminate after ']' */ host->ptr = host_header; host->len = (size_t)(pos + 1 - host_header); } else { /* Otherwise, a ':' separates hostname and port number */ pos = strchr(host_header, ':'); if (pos != NULL) { host->len = (size_t)(pos - host_header); } else { host->len = strlen(host_header); } host->ptr = host_header; } } } static int switch_domain_context(struct mg_connection *conn) { struct vec host; get_host_from_request_info(&host, &conn->request_info); if (host.ptr) { if (conn->ssl) { /* This is a HTTPS connection, maybe we have a hostname * from SNI (set in ssl_servername_callback). */ const char *sslhost = conn->dom_ctx->config[AUTHENTICATION_DOMAIN]; if (sslhost && (conn->dom_ctx != &(conn->phys_ctx->dd))) { /* We are not using the default domain */ if ((strlen(sslhost) != host.len) || mg_strncasecmp(host.ptr, sslhost, host.len)) { /* Mismatch between SNI domain and HTTP domain */ DEBUG_TRACE("Host mismatch: SNI: %s, HTTPS: %.*s", sslhost, (int)host.len, host.ptr); return 0; } } } else { struct mg_domain_context *dom = &(conn->phys_ctx->dd); while (dom) { const char *domName = dom->config[AUTHENTICATION_DOMAIN]; size_t domNameLen = strlen(domName); if ((domNameLen == host.len) && !mg_strncasecmp(host.ptr, domName, host.len)) { /* Found matching domain */ DEBUG_TRACE("HTTP domain %s found", dom->config[AUTHENTICATION_DOMAIN]); /* TODO: Check if this is a HTTP or HTTPS domain */ conn->dom_ctx = dom; break; } mg_lock_context(conn->phys_ctx); dom = dom->next; mg_unlock_context(conn->phys_ctx); } } DEBUG_TRACE("HTTP%s Host: %.*s", conn->ssl ? "S" : "", (int)host.len, host.ptr); } else { DEBUG_TRACE("HTTP%s Host is not set", conn->ssl ? "S" : ""); return 1; } return 1; } static void redirect_to_https_port(struct mg_connection *conn, int port) { char target_url[MG_BUF_LEN]; int truncated = 0; const char *expect_proto = (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET) ? "wss" : "https"; /* Use "308 Permanent Redirect" */ int redirect_code = 308; /* In any case, close the current connection */ conn->must_close = 1; /* Send host, port, uri and (if it exists) ?query_string */ if (mg_construct_local_link( conn, target_url, sizeof(target_url), expect_proto, port, NULL) < 0) { truncated = 1; } else if (conn->request_info.query_string != NULL) { size_t slen1 = strlen(target_url); size_t slen2 = strlen(conn->request_info.query_string); if ((slen1 + slen2 + 2) < sizeof(target_url)) { target_url[slen1] = '?'; memcpy(target_url + slen1 + 1, conn->request_info.query_string, slen2); target_url[slen1 + slen2 + 1] = 0; } else { truncated = 1; } } /* Check overflow in location buffer (will not occur if MG_BUF_LEN * is used as buffer size) */ if (truncated) { mg_send_http_error(conn, 500, "%s", "Redirect URL too long"); return; } /* Use redirect helper function */ mg_send_http_redirect(conn, target_url, redirect_code); } static void mg_set_handler_type(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx, const char *uri, int handler_type, int is_delete_request, mg_request_handler handler, struct mg_websocket_subprotocols *subprotocols, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, mg_authorization_handler auth_handler, void *cbdata) { struct mg_handler_info *tmp_rh, **lastref; size_t urilen = strlen(uri); if (handler_type == WEBSOCKET_HANDLER) { DEBUG_ASSERT(handler == NULL); DEBUG_ASSERT(is_delete_request || connect_handler != NULL || ready_handler != NULL || data_handler != NULL || close_handler != NULL); DEBUG_ASSERT(auth_handler == NULL); if (handler != NULL) { return; } if (!is_delete_request && (connect_handler == NULL) && (ready_handler == NULL) && (data_handler == NULL) && (close_handler == NULL)) { return; } if (auth_handler != NULL) { return; } } else if (handler_type == REQUEST_HANDLER) { DEBUG_ASSERT(connect_handler == NULL && ready_handler == NULL && data_handler == NULL && close_handler == NULL); DEBUG_ASSERT(is_delete_request || (handler != NULL)); DEBUG_ASSERT(auth_handler == NULL); if ((connect_handler != NULL) || (ready_handler != NULL) || (data_handler != NULL) || (close_handler != NULL)) { return; } if (!is_delete_request && (handler == NULL)) { return; } if (auth_handler != NULL) { return; } } else if (handler_type == AUTH_HANDLER) { DEBUG_ASSERT(handler == NULL); DEBUG_ASSERT(connect_handler == NULL && ready_handler == NULL && data_handler == NULL && close_handler == NULL); DEBUG_ASSERT(is_delete_request || (auth_handler != NULL)); if (handler != NULL) { return; } if ((connect_handler != NULL) || (ready_handler != NULL) || (data_handler != NULL) || (close_handler != NULL)) { return; } if (!is_delete_request && (auth_handler == NULL)) { return; } } else { /* Unknown handler type. */ return; } if (!phys_ctx || !dom_ctx) { /* no context available */ return; } mg_lock_context(phys_ctx); /* first try to find an existing handler */ do { lastref = &(dom_ctx->handlers); for (tmp_rh = dom_ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) { if (tmp_rh->handler_type == handler_type && (urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) { if (!is_delete_request) { /* update existing handler */ if (handler_type == REQUEST_HANDLER) { /* Wait for end of use before updating */ if (tmp_rh->refcount) { mg_unlock_context(phys_ctx); mg_sleep(1); mg_lock_context(phys_ctx); /* tmp_rh might have been freed, search again. */ break; } /* Ok, the handler is no more use -> Update it */ tmp_rh->handler = handler; } else if (handler_type == WEBSOCKET_HANDLER) { tmp_rh->subprotocols = subprotocols; tmp_rh->connect_handler = connect_handler; tmp_rh->ready_handler = ready_handler; tmp_rh->data_handler = data_handler; tmp_rh->close_handler = close_handler; } else { /* AUTH_HANDLER */ tmp_rh->auth_handler = auth_handler; } tmp_rh->cbdata = cbdata; } else { /* remove existing handler */ if (handler_type == REQUEST_HANDLER) { /* Wait for end of use before removing */ if (tmp_rh->refcount) { tmp_rh->removing = 1; mg_unlock_context(phys_ctx); mg_sleep(1); mg_lock_context(phys_ctx); /* tmp_rh might have been freed, search again. */ break; } /* Ok, the handler is no more used */ } *lastref = tmp_rh->next; mg_free(tmp_rh->uri); mg_free(tmp_rh); } mg_unlock_context(phys_ctx); return; } lastref = &(tmp_rh->next); } } while (tmp_rh != NULL); if (is_delete_request) { /* no handler to set, this was a remove request to a non-existing * handler */ mg_unlock_context(phys_ctx); return; } tmp_rh = (struct mg_handler_info *)mg_calloc_ctx(1, sizeof(struct mg_handler_info), phys_ctx); if (tmp_rh == NULL) { mg_unlock_context(phys_ctx); mg_cry_ctx_internal(phys_ctx, "%s", "Cannot create new request handler struct, OOM"); return; } tmp_rh->uri = mg_strdup_ctx(uri, phys_ctx); if (!tmp_rh->uri) { mg_unlock_context(phys_ctx); mg_free(tmp_rh); mg_cry_ctx_internal(phys_ctx, "%s", "Cannot create new request handler struct, OOM"); return; } tmp_rh->uri_len = urilen; if (handler_type == REQUEST_HANDLER) { tmp_rh->refcount = 0; tmp_rh->removing = 0; tmp_rh->handler = handler; } else if (handler_type == WEBSOCKET_HANDLER) { tmp_rh->subprotocols = subprotocols; tmp_rh->connect_handler = connect_handler; tmp_rh->ready_handler = ready_handler; tmp_rh->data_handler = data_handler; tmp_rh->close_handler = close_handler; } else { /* AUTH_HANDLER */ tmp_rh->auth_handler = auth_handler; } tmp_rh->cbdata = cbdata; tmp_rh->handler_type = handler_type; tmp_rh->next = NULL; *lastref = tmp_rh; mg_unlock_context(phys_ctx); } CIVETWEB_API void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata) { mg_set_handler_type(ctx, &(ctx->dd), uri, REQUEST_HANDLER, handler == NULL, handler, NULL, NULL, NULL, NULL, NULL, NULL, cbdata); } CIVETWEB_API void mg_set_websocket_handler(struct mg_context *ctx, const char *uri, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata) { mg_set_websocket_handler_with_subprotocols(ctx, uri, NULL, connect_handler, ready_handler, data_handler, close_handler, cbdata); } CIVETWEB_API void mg_set_websocket_handler_with_subprotocols( struct mg_context *ctx, const char *uri, struct mg_websocket_subprotocols *subprotocols, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata) { int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL) && (data_handler == NULL) && (close_handler == NULL); mg_set_handler_type(ctx, &(ctx->dd), uri, WEBSOCKET_HANDLER, is_delete_request, NULL, subprotocols, connect_handler, ready_handler, data_handler, close_handler, NULL, cbdata); } CIVETWEB_API void mg_set_auth_handler(struct mg_context *ctx, const char *uri, mg_authorization_handler handler, void *cbdata) { mg_set_handler_type(ctx, &(ctx->dd), uri, AUTH_HANDLER, handler == NULL, NULL, NULL, NULL, NULL, NULL, NULL, handler, cbdata); } static int get_request_handler(struct mg_connection *conn, int handler_type, mg_request_handler *handler, struct mg_websocket_subprotocols **subprotocols, mg_websocket_connect_handler *connect_handler, mg_websocket_ready_handler *ready_handler, mg_websocket_data_handler *data_handler, mg_websocket_close_handler *close_handler, mg_authorization_handler *auth_handler, void **cbdata, struct mg_handler_info **handler_info) { const struct mg_request_info *request_info = mg_get_request_info(conn); if (request_info) { const char *uri = request_info->local_uri; size_t urilen = strlen(uri); struct mg_handler_info *tmp_rh; int step, matched; if (!conn || !conn->phys_ctx || !conn->dom_ctx) { return 0; } mg_lock_context(conn->phys_ctx); for (step = 0; step < 3; step++) { for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) { if (tmp_rh->handler_type != handler_type) { continue; } if (step == 0) { /* first try for an exact match */ matched = (tmp_rh->uri_len == urilen) && (strcmp(tmp_rh->uri, uri) == 0); } else if (step == 1) { /* next try for a partial match, we will accept uri/something */ matched = (tmp_rh->uri_len < urilen) && (uri[tmp_rh->uri_len] == '/') && (memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0); } else { /* finally try for pattern match */ matched = match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0; } if (matched) { if (handler_type == WEBSOCKET_HANDLER) { *subprotocols = tmp_rh->subprotocols; *connect_handler = tmp_rh->connect_handler; *ready_handler = tmp_rh->ready_handler; *data_handler = tmp_rh->data_handler; *close_handler = tmp_rh->close_handler; } else if (handler_type == REQUEST_HANDLER) { if (tmp_rh->removing) { /* Treat as none found */ step = 2; break; } *handler = tmp_rh->handler; /* Acquire handler and give it back */ tmp_rh->refcount++; *handler_info = tmp_rh; } else { /* AUTH_HANDLER */ *auth_handler = tmp_rh->auth_handler; } *cbdata = tmp_rh->cbdata; mg_unlock_context(conn->phys_ctx); return 1; } } } mg_unlock_context(conn->phys_ctx); } return 0; /* none found */ } /* Check if the script file is in a path, allowed for script files. * This can be used if uploading files is possible not only for the server * admin, and the upload mechanism does not check the file extension. */ static int is_in_script_path(const struct mg_connection *conn, const char *path) { /* TODO (Feature): Add config value for allowed script path. * Default: All allowed. */ (void)conn; (void)path; return 1; } #if defined(USE_WEBSOCKET) && defined(MG_EXPERIMENTAL_INTERFACES) static int experimental_websocket_client_data_wrapper(struct mg_connection *conn, int bits, char *data, size_t len, void *cbdata) { struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata; if (pcallbacks->websocket_data) { return pcallbacks->websocket_data(conn, bits, data, len); } /* No handler set - assume "OK" */ return 1; } static void experimental_websocket_client_close_wrapper(const struct mg_connection *conn, void *cbdata) { struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata; if (pcallbacks->connection_close) { pcallbacks->connection_close(conn); } } #endif /* Decrement recount of handler. conn must not be NULL, handler_info may be NULL */ static void release_handler_ref(struct mg_connection *conn, struct mg_handler_info *handler_info) { if (handler_info != NULL) { /* Use context lock for ref counter */ mg_lock_context(conn->phys_ctx); handler_info->refcount--; mg_unlock_context(conn->phys_ctx); } } /* This is the heart of the Civetweb's logic. * This function is called when the request is read, parsed and validated, * and Civetweb must decide what action to take: serve a file, or * a directory, or call embedded function, etcetera. */ static void handle_request(struct mg_connection *conn) { struct mg_request_info *ri = &conn->request_info; char path[UTF8_PATH_MAX]; int uri_len, ssl_index; int is_found = 0, is_script_resource = 0, is_websocket_request = 0, is_put_or_delete_request = 0, is_callback_resource = 0, is_template_text_file = 0, is_webdav_request = 0; int i; struct mg_file file = STRUCT_FILE_INITIALIZER; mg_request_handler callback_handler = NULL; struct mg_handler_info *handler_info = NULL; struct mg_websocket_subprotocols *subprotocols; mg_websocket_connect_handler ws_connect_handler = NULL; mg_websocket_ready_handler ws_ready_handler = NULL; mg_websocket_data_handler ws_data_handler = NULL; mg_websocket_close_handler ws_close_handler = NULL; void *callback_data = NULL; mg_authorization_handler auth_handler = NULL; void *auth_callback_data = NULL; int handler_type; time_t curtime = time(NULL); char date[64]; char *tmp; path[0] = 0; /* 0. Reset internal state (required for HTTP/2 proxy) */ conn->request_state = 0; /* 1. get the request url */ /* 1.1. split into url and query string */ if ((conn->request_info.query_string = strchr(ri->request_uri, '?')) != NULL) { *((char *)conn->request_info.query_string++) = '\0'; } /* 1.2. do a https redirect, if required. Do not decode URIs yet. */ if (!conn->client.is_ssl && conn->client.ssl_redir) { ssl_index = get_first_ssl_listener_index(conn->phys_ctx); if (ssl_index >= 0) { int port = (int)ntohs(USA_IN_PORT_UNSAFE( &(conn->phys_ctx->listening_sockets[ssl_index].lsa))); redirect_to_https_port(conn, port); } else { /* A http to https forward port has been specified, * but no https port to forward to. */ mg_send_http_error(conn, 503, "%s", "Error: SSL forward not configured properly"); mg_cry_internal(conn, "%s", "Can not redirect to SSL, no SSL port available"); } return; } uri_len = (int)strlen(ri->local_uri); /* 1.3. decode url (if config says so) */ if (should_decode_url(conn)) { url_decode_in_place((char *)ri->local_uri); } /* URL decode the query-string only if explicitly set in the configuration */ if (conn->request_info.query_string) { if (should_decode_query_string(conn)) { url_decode_in_place((char *)conn->request_info.query_string); } } /* 1.4. clean URIs, so a path like allowed_dir/../forbidden_file is not * possible. The fact that we cleaned the URI is stored in that the * pointer to ri->local_ur and ri->local_uri_raw are now different. * ri->local_uri_raw still points to memory allocated in * worker_thread_run(). ri->local_uri is private to the request so we * don't have to use preallocated memory here. */ tmp = mg_strdup(ri->local_uri_raw); if (!tmp) { /* Out of memory. We cannot do anything reasonable here. */ return; } remove_dot_segments(tmp); ri->local_uri = tmp; /* step 1. completed, the url is known now */ DEBUG_TRACE("REQUEST: %s %s", ri->request_method, ri->local_uri); /* 2. if this ip has limited speed, set it for this connection */ conn->throttle = set_throttle(conn->dom_ctx->config[THROTTLE], &conn->client.rsa, ri->local_uri); /* 3. call a "handle everything" callback, if registered */ if (conn->phys_ctx->callbacks.begin_request != NULL) { /* Note that since V1.7 the "begin_request" function is called * before an authorization check. If an authorization check is * required, use a request_handler instead. */ i = conn->phys_ctx->callbacks.begin_request(conn); if (i > 0) { /* callback already processed the request. Store the return value as a status code for the access log. */ conn->status_code = i; if (!conn->must_close) { discard_unread_request_data(conn); } DEBUG_TRACE("%s", "begin_request handled request"); return; } else if (i == 0) { /* civetweb should process the request */ } else { /* unspecified - may change with the next version */ DEBUG_TRACE("%s", "done (undocumented behavior)"); return; } } /* request not yet handled by a handler or redirect, so the request * is processed here */ /* 4. Check for CORS preflight requests and handle them (if configured). * https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS */ if (!strcmp(ri->request_method, "OPTIONS")) { /* Send a response to CORS preflights only if * access_control_allow_methods is not NULL and not an empty string. * In this case, scripts can still handle CORS. */ const char *cors_meth_cfg = conn->dom_ctx->config[ACCESS_CONTROL_ALLOW_METHODS]; const char *cors_orig_cfg = conn->dom_ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN]; const char *cors_origin = get_header(ri->http_headers, ri->num_headers, "Origin"); const char *cors_acrm = get_header(ri->http_headers, ri->num_headers, "Access-Control-Request-Method"); /* Todo: check if cors_origin is in cors_orig_cfg. * Or, let the client check this. */ if ((cors_meth_cfg != NULL) && (*cors_meth_cfg != 0) && (cors_orig_cfg != NULL) && (*cors_orig_cfg != 0) && (cors_origin != NULL) && (cors_acrm != NULL)) { /* This is a valid CORS preflight, and the server is configured * to handle it automatically. */ const char *cors_acrh = get_header(ri->http_headers, ri->num_headers, "Access-Control-Request-Headers"); gmt_time_string(date, sizeof(date), &curtime); mg_printf(conn, "HTTP/1.1 200 OK\r\n" "Date: %s\r\n" "Access-Control-Allow-Origin: %s\r\n" "Access-Control-Allow-Methods: %s\r\n" "Content-Length: 0\r\n" "Connection: %s\r\n", date, cors_orig_cfg, ((cors_meth_cfg[0] == '*') ? cors_acrm : cors_meth_cfg), suggest_connection_header(conn)); if (cors_acrh != NULL) { /* CORS request is asking for additional headers */ const char *cors_hdr_cfg = conn->dom_ctx->config[ACCESS_CONTROL_ALLOW_HEADERS]; if ((cors_hdr_cfg != NULL) && (*cors_hdr_cfg != 0)) { /* Allow only if access_control_allow_headers is * not NULL and not an empty string. If this * configuration is set to *, allow everything. * Otherwise this configuration must be a list * of allowed HTTP header names. */ mg_printf(conn, "Access-Control-Allow-Headers: %s\r\n", ((cors_hdr_cfg[0] == '*') ? cors_acrh : cors_hdr_cfg)); } } mg_printf(conn, "Access-Control-Max-Age: 60\r\n"); mg_printf(conn, "\r\n"); DEBUG_TRACE("%s", "OPTIONS done"); return; } } /* 5. interpret the url to find out how the request must be handled */ /* 5.1. first test, if the request targets the regular http(s):// * protocol namespace or the websocket ws(s):// protocol namespace. */ is_websocket_request = (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET); #if defined(USE_WEBSOCKET) handler_type = is_websocket_request ? WEBSOCKET_HANDLER : REQUEST_HANDLER; #else handler_type = REQUEST_HANDLER; #endif /* defined(USE_WEBSOCKET) */ if (is_websocket_request) { HTTP1_only; } /* 5.2. check if the request will be handled by a callback */ if (get_request_handler(conn, handler_type, &callback_handler, &subprotocols, &ws_connect_handler, &ws_ready_handler, &ws_data_handler, &ws_close_handler, NULL, &callback_data, &handler_info)) { /* 5.2.1. A callback will handle this request. All requests * handled by a callback have to be considered as requests * to a script resource. */ is_callback_resource = 1; is_script_resource = 1; is_put_or_delete_request = is_put_or_delete_method(conn); /* Never handle a C callback according to File WebDav rules, * even if it is a webdav method */ is_webdav_request = 0; /* is_civetweb_webdav_method(conn); */ } else { no_callback_resource: /* 5.2.2. No callback is responsible for this request. The URI * addresses a file based resource (static content or Lua/cgi * scripts in the file system). */ is_callback_resource = 0; interpret_uri(conn, path, sizeof(path), &file.stat, &is_found, &is_script_resource, &is_websocket_request, &is_put_or_delete_request, &is_webdav_request, &is_template_text_file); } /* 5.3. A webdav request (PROPFIND/PROPPATCH/LOCK/UNLOCK) */ if (is_webdav_request) { /* TODO: Do we need a config option? */ const char *webdav_enable = conn->dom_ctx->config[ENABLE_WEBDAV]; if (webdav_enable[0] != 'y') { mg_send_http_error(conn, 405, "%s method not allowed", conn->request_info.request_method); DEBUG_TRACE("%s", "webdav rejected"); return; } } /* 6. authorization check */ /* 6.1. a custom authorization handler is installed */ if (get_request_handler(conn, AUTH_HANDLER, NULL, NULL, NULL, NULL, NULL, NULL, &auth_handler, &auth_callback_data, NULL)) { if (!auth_handler(conn, auth_callback_data)) { /* Callback handler will not be used anymore. Release it */ release_handler_ref(conn, handler_info); DEBUG_TRACE("%s", "auth handler rejected request"); return; } } else if (is_put_or_delete_request && !is_script_resource && !is_callback_resource) { HTTP1_only; /* 6.2. this request is a PUT/DELETE to a real file */ /* 6.2.1. thus, the server must have real files */ #if defined(NO_FILES) if (1) { #else if (conn->dom_ctx->config[DOCUMENT_ROOT] == NULL || conn->dom_ctx->config[PUT_DELETE_PASSWORDS_FILE] == NULL) { #endif /* This code path will not be called for request handlers */ DEBUG_ASSERT(handler_info == NULL); /* This server does not have any real files, thus the * PUT/DELETE methods are not valid. */ mg_send_http_error(conn, 405, "%s method not allowed", conn->request_info.request_method); DEBUG_TRACE("%s", "all file based put/delete requests rejected"); return; } #if !defined(NO_FILES) /* 6.2.2. Check if put authorization for static files is * available. */ if (!is_authorized_for_put(conn)) { send_authorization_request(conn, NULL); DEBUG_TRACE("%s", "file write needs authorization"); return; } #endif } else { /* 6.3. This is either a OPTIONS, GET, HEAD or POST request, * or it is a PUT or DELETE request to a resource that does not * correspond to a file. Check authorization. */ if (!check_authorization(conn, path)) { send_authorization_request(conn, NULL); /* Callback handler will not be used anymore. Release it */ release_handler_ref(conn, handler_info); DEBUG_TRACE("%s", "access authorization required"); return; } } /* request is authorized or does not need authorization */ /* 7. check if there are request handlers for this uri */ if (is_callback_resource) { HTTP1_only; if (!is_websocket_request) { i = callback_handler(conn, callback_data); /* Callback handler will not be used anymore. Release it */ release_handler_ref(conn, handler_info); if (i > 0) { /* Do nothing, callback has served the request. Store * then return value as status code for the log and discard * all data from the client not used by the callback. */ conn->status_code = i; if (!conn->must_close) { discard_unread_request_data(conn); } } else { /* The handler did NOT handle the request. */ /* Some proper reactions would be: * a) close the connections without sending anything * b) send a 404 not found * c) try if there is a file matching the URI * It would be possible to do a, b or c in the callback * implementation, and return 1 - we cannot do anything * here, that is not possible in the callback. * * TODO: What would be the best reaction here? * (Note: The reaction may change, if there is a better * idea.) */ /* For the moment, use option c: We look for a proper file, * but since a file request is not always a script resource, * the authorization check might be different. */ callback_handler = NULL; /* Here we are at a dead end: * According to URI matching, a callback should be * responsible for handling the request, * we called it, but the callback declared itself * not responsible. * We use a goto here, to get out of this dead end, * and continue with the default handling. * A goto here is simpler and better to understand * than some curious loop. */ goto no_callback_resource; } } else { #if defined(USE_WEBSOCKET) handle_websocket_request(conn, path, is_callback_resource, subprotocols, ws_connect_handler, ws_ready_handler, ws_data_handler, ws_close_handler, callback_data); #endif } DEBUG_TRACE("%s", "websocket handling done"); return; } /* 8. handle websocket requests */ #if defined(USE_WEBSOCKET) if (is_websocket_request) { HTTP1_only; if (is_script_resource) { if (is_in_script_path(conn, path)) { /* Websocket Lua script */ handle_websocket_request(conn, path, 0 /* Lua Script */, NULL, NULL, NULL, NULL, NULL, conn->phys_ctx->user_data); } else { /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } } else { mg_send_http_error(conn, 404, "%s", "Not found"); } DEBUG_TRACE("%s", "websocket script done"); return; } else #endif #if defined(NO_FILES) /* 9a. In case the server uses only callbacks, this uri is * unknown. * Then, all request handling ends here. */ mg_send_http_error(conn, 404, "%s", "Not Found"); #else /* 9b. This request is either for a static file or resource handled * by a script file. Thus, a DOCUMENT_ROOT must exist. */ if (conn->dom_ctx->config[DOCUMENT_ROOT] == NULL) { mg_send_http_error(conn, 404, "%s", "Not Found"); DEBUG_TRACE("%s", "no document root available"); return; } /* 10. Request is handled by a script */ if (is_script_resource) { HTTP1_only; handle_file_based_request(conn, path, &file); DEBUG_TRACE("%s", "script handling done"); return; } /* Request was not handled by a callback or script. It will be * handled by a server internal method. */ /* 11. Handle put/delete/mkcol requests */ if (is_put_or_delete_request) { HTTP1_only; /* 11.1. PUT method */ if (!strcmp(ri->request_method, "PUT")) { put_file(conn, path); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 11.2. DELETE method */ if (!strcmp(ri->request_method, "DELETE")) { delete_file(conn, path); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 11.3. MKCOL method */ if (!strcmp(ri->request_method, "MKCOL")) { dav_mkcol(conn, path); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 11.4. MOVE method */ if (!strcmp(ri->request_method, "MOVE")) { dav_move_file(conn, path, 0); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } if (!strcmp(ri->request_method, "COPY")) { dav_move_file(conn, path, 1); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 11.5. LOCK method */ if (!strcmp(ri->request_method, "LOCK")) { dav_lock_file(conn, path); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 11.6. UNLOCK method */ if (!strcmp(ri->request_method, "UNLOCK")) { dav_unlock_file(conn, path); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 11.7. PROPPATCH method */ if (!strcmp(ri->request_method, "PROPPATCH")) { dav_proppatch(conn, path); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 11.8. Other methods, e.g.: PATCH * This method is not supported for static resources, * only for scripts (Lua, CGI) and callbacks. */ mg_send_http_error(conn, 405, "%s method not allowed", conn->request_info.request_method); DEBUG_TRACE("method %s on %s is not supported", ri->request_method, path); return; } /* 11. File does not exist, or it was configured that it should be * hidden */ if (!is_found || (must_hide_file(conn, path))) { mg_send_http_error(conn, 404, "%s", "Not found"); DEBUG_TRACE("handling %s request to %s: file not found", ri->request_method, path); return; } /* 12. Directory uris should end with a slash */ if (file.stat.is_directory && ((uri_len = (int)strlen(ri->local_uri)) > 0) && (ri->local_uri[uri_len - 1] != '/')) { /* Path + server root */ size_t buflen = UTF8_PATH_MAX * 2 + 2; char *new_path; if (ri->query_string) { buflen += strlen(ri->query_string); } new_path = (char *)mg_malloc_ctx(buflen, conn->phys_ctx); if (!new_path) { mg_send_http_error(conn, 500, "out or memory"); } else { mg_get_request_link(conn, new_path, buflen - 1); strcat(new_path, "/"); if (ri->query_string) { /* Append ? and query string */ strcat(new_path, "?"); strcat(new_path, ri->query_string); } mg_send_http_redirect(conn, new_path, 301); mg_free(new_path); } DEBUG_TRACE("%s request to %s: directory redirection sent", ri->request_method, path); return; } /* 13. Handle other methods than GET/HEAD */ /* 13.1. Handle PROPFIND */ if (!strcmp(ri->request_method, "PROPFIND")) { handle_propfind(conn, path, &file.stat); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 13.2. Handle OPTIONS for files */ if (!strcmp(ri->request_method, "OPTIONS")) { /* This standard handler is only used for real files. * Scripts should support the OPTIONS method themselves, to allow a * maximum flexibility. * Lua and CGI scripts may fully support CORS this way (including * preflights). */ send_options(conn); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 13.3. everything but GET and HEAD (e.g. POST) */ if ((0 != strcmp(ri->request_method, "GET")) && (0 != strcmp(ri->request_method, "HEAD"))) { mg_send_http_error(conn, 405, "%s method not allowed", conn->request_info.request_method); DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 14. directories */ if (file.stat.is_directory) { /* Substitute files have already been handled above. */ /* Here we can either generate and send a directory listing, * or send an "access denied" error. */ if (!mg_strcasecmp(conn->dom_ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) { handle_directory_request(conn, path); } else { mg_send_http_error(conn, 403, "%s", "Error: Directory listing denied"); } DEBUG_TRACE("handling %s request to %s done", ri->request_method, path); return; } /* 15. Files with search/replace patterns: LSP and SSI */ if (is_template_text_file) { HTTP1_only; handle_file_based_request(conn, path, &file); DEBUG_TRACE("handling %s request to %s done (template)", ri->request_method, path); return; } /* 16. Static file - maybe cached */ #if !defined(NO_CACHING) if ((!conn->in_error_handler) && is_not_modified(conn, &file.stat)) { /* Send 304 "Not Modified" - this must not send any body data */ handle_not_modified_static_file_request(conn, &file); DEBUG_TRACE("handling %s request to %s done (not modified)", ri->request_method, path); return; } #endif /* !NO_CACHING */ /* 17. Static file - not cached */ handle_static_file_request(conn, path, &file, NULL, NULL); DEBUG_TRACE("handling %s request to %s done (static)", ri->request_method, path); #endif /* !defined(NO_FILES) */ } #if !defined(NO_FILESYSTEMS) static void handle_file_based_request(struct mg_connection *conn, const char *path, struct mg_file *file) { #if !defined(NO_CGI) int cgi_config_idx, inc, max; #endif if (!conn || !conn->dom_ctx) { return; } #if defined(USE_LUA) if (match_prefix_strlen(conn->dom_ctx->config[LUA_SERVER_PAGE_EXTENSIONS], path) > 0) { if (is_in_script_path(conn, path)) { /* Lua server page: an SSI like page containing mostly plain * html code plus some tags with server generated contents. */ handle_lsp_request(conn, path, file, NULL); } else { /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } return; } if (match_prefix_strlen(conn->dom_ctx->config[LUA_SCRIPT_EXTENSIONS], path) > 0) { if (is_in_script_path(conn, path)) { /* Lua in-server module script: a CGI like script used to * generate the entire reply. */ mg_exec_lua_script(conn, path, NULL); } else { /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } return; } #endif #if defined(USE_DUKTAPE) if (match_prefix_strlen(conn->dom_ctx->config[DUKTAPE_SCRIPT_EXTENSIONS], path) > 0) { if (is_in_script_path(conn, path)) { /* Call duktape to generate the page */ mg_exec_duktape_script(conn, path); } else { /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } return; } #endif #if !defined(NO_CGI) inc = CGI2_EXTENSIONS - CGI_EXTENSIONS; max = PUT_DELETE_PASSWORDS_FILE - CGI_EXTENSIONS; for (cgi_config_idx = 0; cgi_config_idx < max; cgi_config_idx += inc) { if (conn->dom_ctx->config[CGI_EXTENSIONS + cgi_config_idx] != NULL) { if (match_prefix_strlen( conn->dom_ctx->config[CGI_EXTENSIONS + cgi_config_idx], path) > 0) { if (is_in_script_path(conn, path)) { /* CGI scripts may support all HTTP methods */ handle_cgi_request(conn, path, cgi_config_idx); } else { /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } return; } } } #endif /* !NO_CGI */ if (match_prefix_strlen(conn->dom_ctx->config[SSI_EXTENSIONS], path) > 0) { if (is_in_script_path(conn, path)) { handle_ssi_file_request(conn, path, file); } else { /* Script was in an illegal path */ mg_send_http_error(conn, 403, "%s", "Forbidden"); } return; } #if !defined(NO_CACHING) if ((!conn->in_error_handler) && is_not_modified(conn, &file->stat)) { /* Send 304 "Not Modified" - this must not send any body data */ handle_not_modified_static_file_request(conn, file); return; } #endif /* !NO_CACHING */ handle_static_file_request(conn, path, file, NULL, NULL); } #endif /* NO_FILESYSTEMS */ static void close_all_listening_sockets(struct mg_context *ctx) { unsigned int i; if (!ctx) { return; } for (i = 0; i < ctx->num_listening_sockets; i++) { closesocket(ctx->listening_sockets[i].sock); #if defined(USE_X_DOM_SOCKET) /* For unix domain sockets, the socket name represents a file that has * to be deleted. */ /* See * https://stackoverflow.com/questions/15716302/so-reuseaddr-and-af-unix */ if ((ctx->listening_sockets[i].lsa.sin.sin_family == AF_UNIX) && (ctx->listening_sockets[i].sock != INVALID_SOCKET)) { IGNORE_UNUSED_RESULT( remove(ctx->listening_sockets[i].lsa.sun.sun_path)); } #endif ctx->listening_sockets[i].sock = INVALID_SOCKET; } mg_free(ctx->listening_sockets); ctx->listening_sockets = NULL; mg_free(ctx->listening_socket_fds); ctx->listening_socket_fds = NULL; } /* Valid listening port specification is: [ip_address:]port[s] * Examples for IPv4: 80, 443s, 127.0.0.1:3128, 192.0.2.3:8080s * Examples for IPv6: [::]:80, [::1]:80, * [2001:0db8:7654:3210:FEDC:BA98:7654:3210]:443s * see https://tools.ietf.org/html/rfc3513#section-2.2 * In order to bind to both, IPv4 and IPv6, you can either add * both ports using 8080,[::]:8080, or the short form +8080. * Both forms differ in detail: 8080,[::]:8080 create two sockets, * one only accepting IPv4 the other only IPv6. +8080 creates * one socket accepting IPv4 and IPv6. Depending on the IPv6 * environment, they might work differently, or might not work * at all - it must be tested what options work best in the * relevant network environment. */ static int parse_port_string(const struct vec *vec, struct socket *so, int *ip_version) { unsigned int a, b, c, d; unsigned port; unsigned long portUL; int ch, len; const char *cb; char *endptr; #if defined(USE_IPV6) char buf[100] = {0}; #endif /* MacOS needs that. If we do not zero it, subsequent bind() will fail. * Also, all-zeroes in the socket address means binding to all addresses * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */ memset(so, 0, sizeof(*so)); so->lsa.sin.sin_family = AF_INET; *ip_version = 0; /* Initialize len as invalid. */ port = 0; len = 0; /* Test for different ways to format this string */ if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len) // NOLINT(cert-err34-c) 'sscanf' used to convert a string // to an integer value, but function will not report // conversion errors; consider using 'strtol' instead == 5) { /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */ so->lsa.sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d); so->lsa.sin.sin_port = htons((uint16_t)port); *ip_version = 4; #if defined(USE_IPV6) } else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2 && ((size_t)len <= vec->len) && mg_inet_pton( AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6), 0)) { /* IPv6 address, examples: see above */ /* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton */ so->lsa.sin6.sin6_port = htons((uint16_t)port); *ip_version = 6; #endif } else if ((vec->ptr[0] == '+') && (sscanf(vec->ptr + 1, "%u%n", &port, &len) == 1)) { // NOLINT(cert-err34-c) 'sscanf' used to convert a // string to an integer value, but function will not // report conversion errors; consider using 'strtol' // instead /* Port is specified with a +, bind to IPv6 and IPv4, INADDR_ANY */ /* Add 1 to len for the + character we skipped before */ len++; #if defined(USE_IPV6) /* Set socket family to IPv6, do not use IPV6_V6ONLY */ so->lsa.sin6.sin6_family = AF_INET6; so->lsa.sin6.sin6_port = htons((uint16_t)port); *ip_version = 4 + 6; #else /* Bind to IPv4 only, since IPv6 is not built in. */ so->lsa.sin.sin_port = htons((uint16_t)port); *ip_version = 4; #endif } else if (is_valid_port(portUL = strtoul(vec->ptr, &endptr, 0)) && (vec->ptr != endptr)) { len = (int)(endptr - vec->ptr); port = (uint16_t)portUL; /* If only port is specified, bind to IPv4, INADDR_ANY */ so->lsa.sin.sin_port = htons((uint16_t)port); *ip_version = 4; } else if ((cb = strchr(vec->ptr, ':')) != NULL) { /* String could be a hostname. This check algorithm * will only work for RFC 952 compliant hostnames, * starting with a letter, containing only letters, * digits and hyphen ('-'). Newer specs may allow * more, but this is not guaranteed here, since it * may interfere with rules for port option lists. */ /* According to RFC 1035, hostnames are restricted to 255 characters * in total (63 between two dots). */ char hostname[256]; size_t hostnlen = (size_t)(cb - vec->ptr); if ((hostnlen >= vec->len) || (hostnlen >= sizeof(hostname))) { /* This would be invalid in any case */ *ip_version = 0; return 0; } mg_strlcpy(hostname, vec->ptr, hostnlen + 1); if (mg_inet_pton( AF_INET, hostname, &so->lsa.sin, sizeof(so->lsa.sin), 1)) { if (sscanf(cb + 1, "%u%n", &port, &len) == 1) { // NOLINT(cert-err34-c) 'sscanf' used to convert a // string to an integer value, but function will not // report conversion errors; consider using 'strtol' // instead *ip_version = 4; so->lsa.sin.sin_port = htons((uint16_t)port); len += (int)(hostnlen + 1); } else { len = 0; } #if defined(USE_IPV6) } else if (mg_inet_pton(AF_INET6, hostname, &so->lsa.sin6, sizeof(so->lsa.sin6), 1)) { if (sscanf(cb + 1, "%u%n", &port, &len) == 1) { *ip_version = 6; so->lsa.sin6.sin6_port = htons((uint16_t)port); len += (int)(hostnlen + 1); } else { len = 0; } #endif } else { len = 0; } #if defined(USE_X_DOM_SOCKET) } else if (vec->ptr[0] == 'x') { /* unix (linux) domain socket */ if (vec->len < sizeof(so->lsa.sun.sun_path)) { len = vec->len; so->lsa.sun.sun_family = AF_UNIX; memset(so->lsa.sun.sun_path, 0, sizeof(so->lsa.sun.sun_path)); memcpy(so->lsa.sun.sun_path, (char *)vec->ptr + 1, vec->len - 1); port = 0; *ip_version = 99; } else { /* String too long */ len = 0; } #endif } else { /* Parsing failure. */ len = 0; } /* sscanf and the option splitting code ensure the following condition * Make sure the port is valid and vector ends with the port, 's' or 'r' */ if ((len > 0) && is_valid_port(port) && (((size_t)len == vec->len) || (((size_t)len + 1) == vec->len))) { /* Next character after the port number */ ch = ((size_t)len < vec->len) ? vec->ptr[len] : '\0'; so->is_ssl = (ch == 's'); so->ssl_redir = (ch == 'r'); if ((ch == '\0') || (ch == 's') || (ch == 'r')) { return 1; } } /* Reset ip_version to 0 if there is an error */ *ip_version = 0; return 0; } /* Is there any SSL port in use? */ static int is_ssl_port_used(const char *ports) { if (ports) { /* There are several different allowed syntax variants: * - "80" for a single port using every network interface * - "localhost:80" for a single port using only localhost * - "80,localhost:8080" for two ports, one bound to localhost * - "80,127.0.0.1:8084,[::1]:8086" for three ports, one bound * to IPv4 localhost, one to IPv6 localhost * - "+80" use port 80 for IPv4 and IPv6 * - "+80r,+443s" port 80 (HTTP) is a redirect to port 443 (HTTPS), * for both: IPv4 and IPv4 * - "+443s,localhost:8080" port 443 (HTTPS) for every interface, * additionally port 8080 bound to localhost connections * * If we just look for 's' anywhere in the string, "localhost:80" * will be detected as SSL (false positive). * Looking for 's' after a digit may cause false positives in * "my24service:8080". * Looking from 's' backward if there are only ':' and numbers * before will not work for "24service:8080" (non SSL, port 8080) * or "24s" (SSL, port 24). * * Remark: Initially hostnames were not allowed to start with a * digit (according to RFC 952), this was allowed later (RFC 1123, * Section 2.1). * * To get this correct, the entire string must be parsed as a whole, * reading it as a list element for element and parsing with an * algorithm equivalent to parse_port_string. * * In fact, we use local interface names here, not arbitrary * hostnames, so in most cases the only name will be "localhost". * * So, for now, we use this simple algorithm, that may still return * a false positive in bizarre cases. */ int i; int portslen = (int)strlen(ports); char prevIsNumber = 0; for (i = 0; i < portslen; i++) { if (prevIsNumber && (ports[i] == 's' || ports[i] == 'r')) { return 1; } if (ports[i] >= '0' && ports[i] <= '9') { prevIsNumber = 1; } else { prevIsNumber = 0; } } } return 0; } static int set_ports_option(struct mg_context *phys_ctx) { const char *list; int on = 1; #if defined(USE_IPV6) int off = 0; #endif struct vec vec; struct socket so, *ptr; struct mg_pollfd *pfd; union usa usa; socklen_t len; int ip_version; int portsTotal = 0; int portsOk = 0; const char *opt_txt; long opt_listen_backlog; if (!phys_ctx) { return 0; } memset(&so, 0, sizeof(so)); memset(&usa, 0, sizeof(usa)); len = sizeof(usa); list = phys_ctx->dd.config[LISTENING_PORTS]; while ((list = next_option(list, &vec, NULL)) != NULL) { portsTotal++; if (!parse_port_string(&vec, &so, &ip_version)) { mg_cry_ctx_internal( phys_ctx, "%.*s: invalid port spec (entry %i). Expecting list of: %s", (int)vec.len, vec.ptr, portsTotal, "[IP_ADDRESS:]PORT[s|r]"); continue; } #if !defined(NO_SSL) if (so.is_ssl && phys_ctx->dd.ssl_ctx == NULL) { mg_cry_ctx_internal(phys_ctx, "Cannot add SSL socket (entry %i)", portsTotal); continue; } #endif /* Create socket. */ /* For a list of protocol numbers (e.g., TCP==6) see: * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml */ if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, (ip_version == 99) ? (/* LOCAL */ 0) : (/* TCP */ 6))) == INVALID_SOCKET) { mg_cry_ctx_internal(phys_ctx, "cannot create socket (entry %i)", portsTotal); continue; } #if defined(_WIN32) /* Windows SO_REUSEADDR lets many procs binds to a * socket, SO_EXCLUSIVEADDRUSE makes the bind fail * if someone already has the socket -- DTL */ /* NOTE: If SO_EXCLUSIVEADDRUSE is used, * Windows might need a few seconds before * the same port can be used again in the * same process, so a short Sleep may be * required between mg_stop and mg_start. */ if (setsockopt(so.sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (SOCK_OPT_TYPE)&on, sizeof(on)) != 0) { /* Set reuse option, but don't abort on errors. */ mg_cry_ctx_internal( phys_ctx, "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)", portsTotal); } #else if (setsockopt(so.sock, SOL_SOCKET, SO_REUSEADDR, (SOCK_OPT_TYPE)&on, sizeof(on)) != 0) { /* Set reuse option, but don't abort on errors. */ mg_cry_ctx_internal( phys_ctx, "cannot set socket option SO_REUSEADDR (entry %i)", portsTotal); } #endif #if defined(USE_X_DOM_SOCKET) if (ip_version == 99) { /* Unix domain socket */ } else #endif if (ip_version > 4) { /* Could be 6 for IPv6 onlyor 10 (4+6) for IPv4+IPv6 */ #if defined(USE_IPV6) if (ip_version > 6) { if (so.lsa.sa.sa_family == AF_INET6 && setsockopt(so.sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&off, sizeof(off)) != 0) { /* Set IPv6 only option, but don't abort on errors. */ mg_cry_ctx_internal(phys_ctx, "cannot set socket option " "IPV6_V6ONLY=off (entry %i)", portsTotal); } } else { if (so.lsa.sa.sa_family == AF_INET6 && setsockopt(so.sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on, sizeof(on)) != 0) { /* Set IPv6 only option, but don't abort on errors. */ mg_cry_ctx_internal(phys_ctx, "cannot set socket option " "IPV6_V6ONLY=on (entry %i)", portsTotal); } } #else mg_cry_ctx_internal(phys_ctx, "%s", "IPv6 not available"); closesocket(so.sock); so.sock = INVALID_SOCKET; continue; #endif } if (so.lsa.sa.sa_family == AF_INET) { len = sizeof(so.lsa.sin); if (bind(so.sock, &so.lsa.sa, len) != 0) { mg_cry_ctx_internal(phys_ctx, "cannot bind to %.*s: %d (%s)", (int)vec.len, vec.ptr, (int)ERRNO, strerror(errno)); closesocket(so.sock); so.sock = INVALID_SOCKET; continue; } } #if defined(USE_IPV6) else if (so.lsa.sa.sa_family == AF_INET6) { len = sizeof(so.lsa.sin6); if (bind(so.sock, &so.lsa.sa, len) != 0) { mg_cry_ctx_internal(phys_ctx, "cannot bind to IPv6 %.*s: %d (%s)", (int)vec.len, vec.ptr, (int)ERRNO, strerror(errno)); closesocket(so.sock); so.sock = INVALID_SOCKET; continue; } } #endif #if defined(USE_X_DOM_SOCKET) else if (so.lsa.sa.sa_family == AF_UNIX) { len = sizeof(so.lsa.sun); if (bind(so.sock, &so.lsa.sa, len) != 0) { mg_cry_ctx_internal(phys_ctx, "cannot bind to unix socket %s: %d (%s)", so.lsa.sun.sun_path, (int)ERRNO, strerror(errno)); closesocket(so.sock); so.sock = INVALID_SOCKET; continue; } } #endif else { mg_cry_ctx_internal( phys_ctx, "cannot bind: address family not supported (entry %i)", portsTotal); closesocket(so.sock); so.sock = INVALID_SOCKET; continue; } opt_txt = phys_ctx->dd.config[LISTEN_BACKLOG_SIZE]; opt_listen_backlog = strtol(opt_txt, NULL, 10); if ((opt_listen_backlog > INT_MAX) || (opt_listen_backlog < 1)) { mg_cry_ctx_internal(phys_ctx, "%s value \"%s\" is invalid", config_options[LISTEN_BACKLOG_SIZE].name, opt_txt); closesocket(so.sock); so.sock = INVALID_SOCKET; continue; } if (listen(so.sock, (int)opt_listen_backlog) != 0) { mg_cry_ctx_internal(phys_ctx, "cannot listen to %.*s: %d (%s)", (int)vec.len, vec.ptr, (int)ERRNO, strerror(errno)); closesocket(so.sock); so.sock = INVALID_SOCKET; continue; } if ((getsockname(so.sock, &(usa.sa), &len) != 0) || (usa.sa.sa_family != so.lsa.sa.sa_family)) { int err = (int)ERRNO; mg_cry_ctx_internal(phys_ctx, "call to getsockname failed %.*s: %d (%s)", (int)vec.len, vec.ptr, err, strerror(errno)); closesocket(so.sock); so.sock = INVALID_SOCKET; continue; } /* Update lsa port in case of random free ports */ #if defined(USE_IPV6) if (so.lsa.sa.sa_family == AF_INET6) { so.lsa.sin6.sin6_port = usa.sin6.sin6_port; } else #endif { so.lsa.sin.sin_port = usa.sin.sin_port; } if ((ptr = (struct socket *) mg_realloc_ctx(phys_ctx->listening_sockets, (phys_ctx->num_listening_sockets + 1) * sizeof(phys_ctx->listening_sockets[0]), phys_ctx)) == NULL) { mg_cry_ctx_internal(phys_ctx, "%s", "Out of memory"); closesocket(so.sock); so.sock = INVALID_SOCKET; continue; } if ((pfd = (struct mg_pollfd *) mg_realloc_ctx(phys_ctx->listening_socket_fds, (phys_ctx->num_listening_sockets + 1) * sizeof(phys_ctx->listening_socket_fds[0]), phys_ctx)) == NULL) { mg_cry_ctx_internal(phys_ctx, "%s", "Out of memory"); closesocket(so.sock); so.sock = INVALID_SOCKET; mg_free(ptr); continue; } set_close_on_exec(so.sock, NULL, phys_ctx); phys_ctx->listening_sockets = ptr; phys_ctx->listening_sockets[phys_ctx->num_listening_sockets] = so; phys_ctx->listening_socket_fds = pfd; phys_ctx->num_listening_sockets++; portsOk++; } if (portsOk != portsTotal) { close_all_listening_sockets(phys_ctx); portsOk = 0; } return portsOk; } static const char * header_val(const struct mg_connection *conn, const char *header) { const char *header_value; if ((header_value = mg_get_header(conn, header)) == NULL) { return "-"; } else { return header_value; } } #if defined(MG_EXTERNAL_FUNCTION_log_access) #include "external_log_access.h" #elif !defined(NO_FILESYSTEMS) static void log_access(const struct mg_connection *conn) { const struct mg_request_info *ri; struct mg_file fi; char date[64], src_addr[IP_ADDR_STR_LEN]; #if defined(REENTRANT_TIME) struct tm _tm; struct tm *tm = &_tm; #else struct tm *tm; #endif const char *referer; const char *user_agent; char log_buf[4096]; if (!conn || !conn->dom_ctx) { return; } /* Set log message to "empty" */ log_buf[0] = 0; #if defined(USE_LUA) if (conn->phys_ctx->lua_bg_log_available) { int ret; struct mg_context *ctx = conn->phys_ctx; lua_State *lstate = (lua_State *)ctx->lua_background_state; pthread_mutex_lock(&ctx->lua_bg_mutex); /* call "log()" in Lua */ lua_getglobal(lstate, "log"); prepare_lua_request_info_inner(conn, lstate); push_lua_response_log_data(conn, lstate); ret = lua_pcall(lstate, /* args */ 2, /* results */ 1, 0); if (ret == 0) { int t = lua_type(lstate, -1); if (t == LUA_TBOOLEAN) { if (lua_toboolean(lstate, -1) == 0) { /* log() returned false: do not log */ pthread_mutex_unlock(&ctx->lua_bg_mutex); return; } /* log returned true: continue logging */ } else if (t == LUA_TSTRING) { size_t len; const char *txt = lua_tolstring(lstate, -1, &len); if ((len == 0) || (*txt == 0)) { /* log() returned empty string: do not log */ pthread_mutex_unlock(&ctx->lua_bg_mutex); return; } /* Copy test from Lua into log_buf */ if (len >= sizeof(log_buf)) { len = sizeof(log_buf) - 1; } memcpy(log_buf, txt, len); log_buf[len] = 0; } } else { lua_cry(conn, ret, lstate, "lua_background_script", "log"); } pthread_mutex_unlock(&ctx->lua_bg_mutex); } #endif if (conn->dom_ctx->config[ACCESS_LOG_FILE] != NULL) { if (mg_fopen(conn, conn->dom_ctx->config[ACCESS_LOG_FILE], MG_FOPEN_MODE_APPEND, &fi) == 0) { fi.access.fp = NULL; } } else { fi.access.fp = NULL; } /* Log is written to a file and/or a callback. If both are not set, * executing the rest of the function is pointless. */ if ((fi.access.fp == NULL) && (conn->phys_ctx->callbacks.log_access == NULL)) { return; } /* If we did not get a log message from Lua, create it here. */ if (!log_buf[0]) { #if defined(REENTRANT_TIME) localtime_r(&conn->conn_birth_time, tm); #else tm = localtime(&conn->conn_birth_time); #endif if (tm != NULL) { strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm); } else { mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date)); } ri = &conn->request_info; sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa); referer = header_val(conn, "Referer"); user_agent = header_val(conn, "User-Agent"); mg_snprintf(conn, NULL, /* Ignore truncation in access log */ log_buf, sizeof(log_buf), "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s", src_addr, (ri->remote_user == NULL) ? "-" : ri->remote_user, date, ri->request_method ? ri->request_method : "-", ri->request_uri ? ri->request_uri : "-", ri->query_string ? "?" : "", ri->query_string ? ri->query_string : "", ri->http_version, conn->status_code, conn->num_bytes_sent, referer, user_agent); } /* Here we have a log message in log_buf. Call the callback */ if (conn->phys_ctx->callbacks.log_access) { if (conn->phys_ctx->callbacks.log_access(conn, log_buf)) { /* do not log if callback returns non-zero */ if (fi.access.fp) { mg_fclose(&fi.access); } return; } } /* Store in file */ if (fi.access.fp) { int ok = 1; flockfile(fi.access.fp); if (fprintf(fi.access.fp, "%s\n", log_buf) < 1) { ok = 0; } if (fflush(fi.access.fp) != 0) { ok = 0; } funlockfile(fi.access.fp); if (mg_fclose(&fi.access) != 0) { ok = 0; } if (!ok) { mg_cry_internal(conn, "Error writing log file %s", conn->dom_ctx->config[ACCESS_LOG_FILE]); } } } #else #error "Either enable filesystems or provide a custom log_access implementation" #endif /* Externally provided function */ /* Verify given socket address against the ACL. * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed. */ static int check_acl(struct mg_context *phys_ctx, const union usa *sa) { int allowed, flag, matched; struct vec vec; if (phys_ctx) { const char *list = phys_ctx->dd.config[ACCESS_CONTROL_LIST]; /* If any ACL is set, deny by default */ allowed = (list == NULL) ? '+' : '-'; while ((list = next_option(list, &vec, NULL)) != NULL) { flag = vec.ptr[0]; matched = -1; if ((vec.len > 0) && ((flag == '+') || (flag == '-'))) { vec.ptr++; vec.len--; matched = parse_match_net(&vec, sa, 1); } if (matched < 0) { mg_cry_ctx_internal(phys_ctx, "%s: subnet must be [+|-]IP-addr[/x]", __func__); return -1; } if (matched) { allowed = flag; } } return allowed == '+'; } return -1; } #if !defined(_WIN32) && !defined(__ZEPHYR__) static int set_uid_option(struct mg_context *phys_ctx) { int success = 0; if (phys_ctx) { /* We are currently running as curr_uid. */ const uid_t curr_uid = getuid(); /* If set, we want to run as run_as_user. */ const char *run_as_user = phys_ctx->dd.config[RUN_AS_USER]; const struct passwd *to_pw = NULL; if ((run_as_user != NULL) && (to_pw = getpwnam(run_as_user)) == NULL) { /* run_as_user does not exist on the system. We can't proceed * further. */ mg_cry_ctx_internal(phys_ctx, "%s: unknown user [%s]", __func__, run_as_user); } else if ((run_as_user == NULL) || (curr_uid == to_pw->pw_uid)) { /* There was either no request to change user, or we're already * running as run_as_user. Nothing else to do. */ success = 1; } else { /* Valid change request. */ if (setgid(to_pw->pw_gid) == -1) { mg_cry_ctx_internal(phys_ctx, "%s: setgid(%s): %s", __func__, run_as_user, strerror(errno)); } else if (setgroups(0, NULL) == -1) { mg_cry_ctx_internal(phys_ctx, "%s: setgroups(): %s", __func__, strerror(errno)); } else if (setuid(to_pw->pw_uid) == -1) { mg_cry_ctx_internal(phys_ctx, "%s: setuid(%s): %s", __func__, run_as_user, strerror(errno)); } else { success = 1; } } } return success; } #endif /* !_WIN32 */ static void tls_dtor(void *key) { struct mg_workerTLS *tls = (struct mg_workerTLS *)key; /* key == pthread_getspecific(sTlsKey); */ if (tls) { if (tls->is_master == 2) { tls->is_master = -3; /* Mark memory as dead */ mg_free(tls); } } pthread_setspecific(sTlsKey, NULL); } #if defined(USE_MBEDTLS) /* Check if SSL is required. * If so, set up ctx->ssl_ctx pointer. */ static int mg_sslctx_init(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx) { if (!phys_ctx) { return 0; } if (!dom_ctx) { dom_ctx = &(phys_ctx->dd); } if (!is_ssl_port_used(dom_ctx->config[LISTENING_PORTS])) { /* No SSL port is set. No need to setup SSL. */ return 1; } dom_ctx->ssl_ctx = (SSL_CTX *)mg_calloc(1, sizeof(*dom_ctx->ssl_ctx)); if (dom_ctx->ssl_ctx == NULL) { DEBUG_TRACE("ssl_ctx malloc failed"); return 0; } return mbed_sslctx_init(dom_ctx->ssl_ctx, dom_ctx->config[SSL_CERTIFICATE]) == 0 ? 1 : 0; } #elif !defined(NO_SSL) static int ssl_use_pem_file(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx, const char *pem, const char *chain); static const char *ssl_error(void); static int refresh_trust(struct mg_connection *conn) { struct stat cert_buf; int64_t t = 0; const char *pem; const char *chain; int should_verify_peer; if ((pem = conn->dom_ctx->config[SSL_CERTIFICATE]) == NULL) { /* If pem is NULL and conn->phys_ctx->callbacks.init_ssl is not, * refresh_trust still can not work. */ return 0; } chain = conn->dom_ctx->config[SSL_CERTIFICATE_CHAIN]; if (chain == NULL) { /* pem is not NULL here */ chain = pem; } if (*chain == 0) { chain = NULL; } if (stat(pem, &cert_buf) != -1) { t = (int64_t)cert_buf.st_mtime; } mg_lock_context(conn->phys_ctx); if ((t != 0) && (conn->dom_ctx->ssl_cert_last_mtime != t)) { conn->dom_ctx->ssl_cert_last_mtime = t; should_verify_peer = 0; if (conn->dom_ctx->config[SSL_DO_VERIFY_PEER] != NULL) { if (mg_strcasecmp(conn->dom_ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0) { should_verify_peer = 1; } else if (mg_strcasecmp(conn->dom_ctx->config[SSL_DO_VERIFY_PEER], "optional") == 0) { should_verify_peer = 1; } } if (should_verify_peer) { char *ca_path = conn->dom_ctx->config[SSL_CA_PATH]; char *ca_file = conn->dom_ctx->config[SSL_CA_FILE]; if (SSL_CTX_load_verify_locations(conn->dom_ctx->ssl_ctx, ca_file, ca_path) != 1) { mg_unlock_context(conn->phys_ctx); mg_cry_ctx_internal( conn->phys_ctx, "SSL_CTX_load_verify_locations error: %s " "ssl_verify_peer requires setting " "either ssl_ca_path or ssl_ca_file. Is any of them " "present in " "the .conf file?", ssl_error()); return 0; } } if (ssl_use_pem_file(conn->phys_ctx, conn->dom_ctx, pem, chain) == 0) { mg_unlock_context(conn->phys_ctx); return 0; } } mg_unlock_context(conn->phys_ctx); return 1; } #if defined(OPENSSL_API_1_1) #else static pthread_mutex_t *ssl_mutexes; #endif /* OPENSSL_API_1_1 */ static int sslize(struct mg_connection *conn, int (*func)(SSL *), const struct mg_client_options *client_options) { int ret, err; int short_trust; unsigned timeout = 1024; unsigned i; if (!conn) { return 0; } short_trust = (conn->dom_ctx->config[SSL_SHORT_TRUST] != NULL) && (mg_strcasecmp(conn->dom_ctx->config[SSL_SHORT_TRUST], "yes") == 0); if (short_trust) { int trust_ret = refresh_trust(conn); if (!trust_ret) { return trust_ret; } } mg_lock_context(conn->phys_ctx); conn->ssl = SSL_new(conn->dom_ctx->ssl_ctx); mg_unlock_context(conn->phys_ctx); if (conn->ssl == NULL) { mg_cry_internal(conn, "sslize error: %s", ssl_error()); OPENSSL_REMOVE_THREAD_STATE(); return 0; } SSL_set_app_data(conn->ssl, (char *)conn); ret = SSL_set_fd(conn->ssl, conn->client.sock); if (ret != 1) { mg_cry_internal(conn, "sslize error: %s", ssl_error()); SSL_free(conn->ssl); conn->ssl = NULL; OPENSSL_REMOVE_THREAD_STATE(); return 0; } if (client_options) { if (client_options->host_name) { SSL_set_tlsext_host_name(conn->ssl, client_options->host_name); } } /* Reuse the request timeout for the SSL_Accept/SSL_connect timeout */ if (conn->dom_ctx->config[REQUEST_TIMEOUT]) { /* NOTE: The loop below acts as a back-off, so we can end * up sleeping for more (or less) than the REQUEST_TIMEOUT. */ int to = atoi(conn->dom_ctx->config[REQUEST_TIMEOUT]); if (to >= 0) { timeout = (unsigned)to; } } /* SSL functions may fail and require to be called again: * see https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html * Here "func" could be SSL_connect or SSL_accept. */ for (i = 0; i <= timeout; i += 50) { ERR_clear_error(); /* conn->dom_ctx may be changed here (see ssl_servername_callback) */ ret = func(conn->ssl); if (ret != 1) { err = SSL_get_error(conn->ssl, ret); if ((err == SSL_ERROR_WANT_CONNECT) || (err == SSL_ERROR_WANT_ACCEPT) || (err == SSL_ERROR_WANT_READ) || (err == SSL_ERROR_WANT_WRITE) || (err == SSL_ERROR_WANT_X509_LOOKUP)) { if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) { /* Don't wait if the server is going to be stopped. */ break; } if (err == SSL_ERROR_WANT_X509_LOOKUP) { /* Simply retry the function call. */ mg_sleep(50); } else { /* Need to retry the function call "later". * See https://linux.die.net/man/3/ssl_get_error * This is typical for non-blocking sockets. */ struct mg_pollfd pfd; int pollres; pfd.fd = conn->client.sock; pfd.events = ((err == SSL_ERROR_WANT_CONNECT) || (err == SSL_ERROR_WANT_WRITE)) ? POLLOUT : POLLIN; pollres = mg_poll(&pfd, 1, 50, &(conn->phys_ctx->stop_flag)); if (pollres < 0) { /* Break if error occurred (-1) * or server shutdown (-2) */ break; } } } else if (err == SSL_ERROR_SYSCALL) { /* This is an IO error. Look at errno. */ mg_cry_internal(conn, "SSL syscall error %i", ERRNO); break; } else { /* This is an SSL specific error, e.g. SSL_ERROR_SSL */ mg_cry_internal(conn, "sslize error: %s", ssl_error()); break; } } else { /* success */ break; } } ERR_clear_error(); if (ret != 1) { SSL_free(conn->ssl); conn->ssl = NULL; OPENSSL_REMOVE_THREAD_STATE(); return 0; } return 1; } /* Return OpenSSL error message (from CRYPTO lib) */ static const char * ssl_error(void) { unsigned long err; err = ERR_get_error(); return ((err == 0) ? "" : ERR_error_string(err, NULL)); } static int hexdump2string(void *mem, int memlen, char *buf, int buflen) { int i; const char hexdigit[] = "0123456789abcdef"; if ((memlen <= 0) || (buflen <= 0)) { return 0; } if (buflen < (3 * memlen)) { return 0; } for (i = 0; i < memlen; i++) { if (i > 0) { buf[3 * i - 1] = ' '; } buf[3 * i] = hexdigit[(((uint8_t *)mem)[i] >> 4) & 0xF]; buf[3 * i + 1] = hexdigit[((uint8_t *)mem)[i] & 0xF]; } buf[3 * memlen - 1] = 0; return 1; } static int ssl_get_client_cert_info(const struct mg_connection *conn, struct mg_client_cert *client_cert) { X509 *cert = SSL_get_peer_certificate(conn->ssl); if (cert) { char str_buf[1024]; unsigned char buf[256]; char *str_serial = NULL; unsigned int ulen; int ilen; unsigned char *tmp_buf; unsigned char *tmp_p; /* Handle to algorithm used for fingerprint */ const EVP_MD *digest = EVP_get_digestbyname("sha1"); /* Get Subject and issuer */ X509_NAME *subj = X509_get_subject_name(cert); X509_NAME *iss = X509_get_issuer_name(cert); /* Get serial number */ ASN1_INTEGER *serial = X509_get_serialNumber(cert); /* Translate serial number to a hex string */ BIGNUM *serial_bn = ASN1_INTEGER_to_BN(serial, NULL); if (serial_bn) { str_serial = BN_bn2hex(serial_bn); BN_free(serial_bn); } client_cert->serial = str_serial ? mg_strdup_ctx(str_serial, conn->phys_ctx) : NULL; /* Translate subject and issuer to a string */ (void)X509_NAME_oneline(subj, str_buf, (int)sizeof(str_buf)); client_cert->subject = mg_strdup_ctx(str_buf, conn->phys_ctx); (void)X509_NAME_oneline(iss, str_buf, (int)sizeof(str_buf)); client_cert->issuer = mg_strdup_ctx(str_buf, conn->phys_ctx); /* Calculate SHA1 fingerprint and store as a hex string */ ulen = 0; /* ASN1_digest is deprecated. Do the calculation manually, * using EVP_Digest. */ ilen = i2d_X509(cert, NULL); tmp_buf = (ilen > 0) ? (unsigned char *)mg_malloc_ctx((unsigned)ilen + 1, conn->phys_ctx) : NULL; if (tmp_buf) { tmp_p = tmp_buf; (void)i2d_X509(cert, &tmp_p); if (!EVP_Digest( tmp_buf, (unsigned)ilen, buf, &ulen, digest, NULL)) { ulen = 0; } mg_free(tmp_buf); } if (!hexdump2string(buf, (int)ulen, str_buf, (int)sizeof(str_buf))) { *str_buf = 0; } client_cert->finger = mg_strdup_ctx(str_buf, conn->phys_ctx); client_cert->peer_cert = (void *)cert; /* Strings returned from bn_bn2hex must be freed using OPENSSL_free, * see https://linux.die.net/man/3/bn_bn2hex */ OPENSSL_free(str_serial); return 1; } return 0; } #if defined(OPENSSL_API_1_1) #else static void ssl_locking_callback(int mode, int mutex_num, const char *file, int line) { (void)line; (void)file; if (mode & 1) { /* 1 is CRYPTO_LOCK */ (void)pthread_mutex_lock(&ssl_mutexes[mutex_num]); } else { (void)pthread_mutex_unlock(&ssl_mutexes[mutex_num]); } } #endif /* OPENSSL_API_1_1 */ #if !defined(NO_SSL_DL) /* Load a DLL/Shared Object with a TLS/SSL implementation. */ static void * load_tls_dll(char *ebuf, size_t ebuf_len, const char *dll_name, struct ssl_func *sw, int *feature_missing) { union { void *p; void (*fp)(void); } u; void *dll_handle; struct ssl_func *fp; int ok; int truncated = 0; if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) { mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s: cannot load %s", __func__, dll_name); return NULL; } ok = 1; for (fp = sw; fp->name != NULL; fp++) { #if defined(_WIN32) /* GetProcAddress() returns pointer to function */ u.fp = (void (*)(void))dlsym(dll_handle, fp->name); #else /* dlsym() on UNIX returns void *. ISO C forbids casts of data * pointers to function pointers. We need to use a union to make a * cast. */ u.p = dlsym(dll_handle, fp->name); #endif /* _WIN32 */ /* Set pointer (might be NULL) */ fp->ptr = u.fp; if (u.fp == NULL) { DEBUG_TRACE("Missing function: %s\n", fp->name); if (feature_missing) { feature_missing[fp->required]++; } if (fp->required == TLS_Mandatory) { /* Mandatory function is missing */ if (ok) { /* This is the first missing function. * Create a new error message. */ mg_snprintf(NULL, &truncated, ebuf, ebuf_len, "%s: %s: cannot find %s", __func__, dll_name, fp->name); ok = 0; } else { /* This is yet anothermissing function. * Append existing error message. */ size_t cur_len = strlen(ebuf); if (!truncated && ((ebuf_len - cur_len) > 3)) { mg_snprintf(NULL, &truncated, ebuf + cur_len, ebuf_len - cur_len - 3, ", %s", fp->name); if (truncated) { /* If truncated, add "..." */ strcat(ebuf, "..."); } } } } } } if (!ok) { (void)dlclose(dll_handle); return NULL; } return dll_handle; } static void *ssllib_dll_handle; /* Store the ssl library handle. */ static void *cryptolib_dll_handle; /* Store the crypto library handle. */ #endif /* NO_SSL_DL */ #if defined(SSL_ALREADY_INITIALIZED) static volatile ptrdiff_t cryptolib_users = 1; /* Reference counter for crypto library. */ #else static volatile ptrdiff_t cryptolib_users = 0; /* Reference counter for crypto library. */ #endif static int initialize_openssl(char *ebuf, size_t ebuf_len) { #if !defined(OPENSSL_API_1_1) && !defined(OPENSSL_API_3_0) int i, num_locks; size_t size; #endif if (ebuf_len > 0) { ebuf[0] = 0; } #if !defined(NO_SSL_DL) if (!cryptolib_dll_handle) { memset(tls_feature_missing, 0, sizeof(tls_feature_missing)); cryptolib_dll_handle = load_tls_dll( ebuf, ebuf_len, CRYPTO_LIB, crypto_sw, tls_feature_missing); if (!cryptolib_dll_handle) { mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s: error loading library %s", __func__, CRYPTO_LIB); DEBUG_TRACE("%s", ebuf); return 0; } } #endif /* NO_SSL_DL */ if (mg_atomic_inc(&cryptolib_users) > 1) { return 1; } #if !defined(OPENSSL_API_1_1) && !defined(OPENSSL_API_3_0) /* Initialize locking callbacks, needed for thread safety. * http://www.openssl.org/support/faq.html#PROG1 */ num_locks = CRYPTO_num_locks(); if (num_locks < 0) { num_locks = 0; } size = sizeof(pthread_mutex_t) * ((size_t)(num_locks)); /* allocate mutex array, if required */ if (num_locks == 0) { /* No mutex array required */ ssl_mutexes = NULL; } else { /* Mutex array required - allocate it */ ssl_mutexes = (pthread_mutex_t *)mg_malloc(size); /* Check OOM */ if (ssl_mutexes == NULL) { mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s: cannot allocate mutexes: %s", __func__, ssl_error()); DEBUG_TRACE("%s", ebuf); return 0; } /* initialize mutex array */ for (i = 0; i < num_locks; i++) { if (0 != pthread_mutex_init(&ssl_mutexes[i], &pthread_mutex_attr)) { mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s: error initializing mutex %i of %i", __func__, i, num_locks); DEBUG_TRACE("%s", ebuf); mg_free(ssl_mutexes); return 0; } } } CRYPTO_set_locking_callback(&ssl_locking_callback); CRYPTO_set_id_callback(&mg_current_thread_id); #endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */ #if !defined(NO_SSL_DL) if (!ssllib_dll_handle) { ssllib_dll_handle = load_tls_dll(ebuf, ebuf_len, SSL_LIB, ssl_sw, tls_feature_missing); if (!ssllib_dll_handle) { #if !defined(OPENSSL_API_1_1) mg_free(ssl_mutexes); #endif DEBUG_TRACE("%s", ebuf); return 0; } } #endif /* NO_SSL_DL */ #if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)) \ && !defined(NO_SSL_DL) /* Initialize SSL library */ OPENSSL_init_ssl(0, NULL); OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); #else /* Initialize SSL library */ SSL_library_init(); SSL_load_error_strings(); #endif return 1; } static int ssl_use_pem_file(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx, const char *pem, const char *chain) { if (SSL_CTX_use_certificate_file(dom_ctx->ssl_ctx, pem, 1) == 0) { mg_cry_ctx_internal(phys_ctx, "%s: cannot open certificate file %s: %s", __func__, pem, ssl_error()); return 0; } /* could use SSL_CTX_set_default_passwd_cb_userdata */ if (SSL_CTX_use_PrivateKey_file(dom_ctx->ssl_ctx, pem, 1) == 0) { mg_cry_ctx_internal(phys_ctx, "%s: cannot open private key file %s: %s", __func__, pem, ssl_error()); return 0; } if (SSL_CTX_check_private_key(dom_ctx->ssl_ctx) == 0) { mg_cry_ctx_internal(phys_ctx, "%s: certificate and private key do not match: %s", __func__, pem); return 0; } /* In contrast to OpenSSL, wolfSSL does not support certificate * chain files that contain private keys and certificates in * SSL_CTX_use_certificate_chain_file. * The CivetWeb-Server used pem-Files that contained both information. * In order to make wolfSSL work, it is split in two files. * One file that contains key and certificate used by the server and * an optional chain file for the ssl stack. */ if (chain) { if (SSL_CTX_use_certificate_chain_file(dom_ctx->ssl_ctx, chain) == 0) { mg_cry_ctx_internal(phys_ctx, "%s: cannot use certificate chain file %s: %s", __func__, chain, ssl_error()); return 0; } } return 1; } #if defined(OPENSSL_API_1_1) static unsigned long ssl_get_protocol(int version_id) { long unsigned ret = (long unsigned)SSL_OP_ALL; if (version_id > 0) ret |= SSL_OP_NO_SSLv2; if (version_id > 1) ret |= SSL_OP_NO_SSLv3; if (version_id > 2) ret |= SSL_OP_NO_TLSv1; if (version_id > 3) ret |= SSL_OP_NO_TLSv1_1; if (version_id > 4) ret |= SSL_OP_NO_TLSv1_2; #if defined(SSL_OP_NO_TLSv1_3) if (version_id > 5) ret |= SSL_OP_NO_TLSv1_3; #endif return ret; } #else static long ssl_get_protocol(int version_id) { unsigned long ret = (unsigned long)SSL_OP_ALL; if (version_id > 0) ret |= SSL_OP_NO_SSLv2; if (version_id > 1) ret |= SSL_OP_NO_SSLv3; if (version_id > 2) ret |= SSL_OP_NO_TLSv1; if (version_id > 3) ret |= SSL_OP_NO_TLSv1_1; if (version_id > 4) ret |= SSL_OP_NO_TLSv1_2; #if defined(SSL_OP_NO_TLSv1_3) if (version_id > 5) ret |= SSL_OP_NO_TLSv1_3; #endif return (long)ret; } #endif /* OPENSSL_API_1_1 */ /* SSL callback documentation: * https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_info_callback.html * https://wiki.openssl.org/index.php/Manual:SSL_CTX_set_info_callback(3) * https://linux.die.net/man/3/ssl_set_info_callback */ /* Note: There is no "const" for the first argument in the documentation * examples, however some (maybe most, but not all) headers of OpenSSL * versions / OpenSSL compatibility layers have it. Having a different * definition will cause a warning in C and an error in C++. Use "const SSL * *", while automatic conversion from "SSL *" works for all compilers, * but not other way around */ static void ssl_info_callback(const SSL *ssl, int what, int ret) { (void)ret; if (what & SSL_CB_HANDSHAKE_START) { SSL_get_app_data(ssl); } if (what & SSL_CB_HANDSHAKE_DONE) { /* TODO: check for openSSL 1.1 */ //#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001 // ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; } } static int ssl_servername_callback(SSL *ssl, int *ad, void *arg) { #if defined(GCC_DIAGNOSTIC) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcast-align" #endif /* defined(GCC_DIAGNOSTIC) */ /* We used an aligned pointer in SSL_set_app_data */ struct mg_connection *conn = (struct mg_connection *)SSL_get_app_data(ssl); #if defined(GCC_DIAGNOSTIC) # pragma GCC diagnostic pop #endif /* defined(GCC_DIAGNOSTIC) */ const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); (void)ad; (void)arg; if ((conn == NULL) || (conn->phys_ctx == NULL)) { DEBUG_ASSERT(0); return SSL_TLSEXT_ERR_NOACK; } conn->dom_ctx = &(conn->phys_ctx->dd); /* Old clients (Win XP) will not support SNI. Then, there * is no server name available in the request - we can * only work with the default certificate. * Multiple HTTPS hosts on one IP+port are only possible * with a certificate containing all alternative names. */ if ((servername == NULL) || (*servername == 0)) { DEBUG_TRACE("%s", "SSL connection not supporting SNI"); mg_lock_context(conn->phys_ctx); SSL_set_SSL_CTX(ssl, conn->dom_ctx->ssl_ctx); mg_unlock_context(conn->phys_ctx); return SSL_TLSEXT_ERR_NOACK; } DEBUG_TRACE("TLS connection to host %s", servername); while (conn->dom_ctx) { if (!mg_strcasecmp(servername, conn->dom_ctx->config[AUTHENTICATION_DOMAIN])) { /* Found matching domain */ DEBUG_TRACE("TLS domain %s found", conn->dom_ctx->config[AUTHENTICATION_DOMAIN]); break; } mg_lock_context(conn->phys_ctx); conn->dom_ctx = conn->dom_ctx->next; mg_unlock_context(conn->phys_ctx); } if (conn->dom_ctx == NULL) { /* Default domain */ DEBUG_TRACE("TLS default domain %s used", conn->phys_ctx->dd.config[AUTHENTICATION_DOMAIN]); conn->dom_ctx = &(conn->phys_ctx->dd); } mg_lock_context(conn->phys_ctx); SSL_set_SSL_CTX(ssl, conn->dom_ctx->ssl_ctx); mg_unlock_context(conn->phys_ctx); return SSL_TLSEXT_ERR_OK; } #if defined(USE_ALPN) static const char alpn_proto_list[] = "\x02h2\x08http/1.1\x08http/1.0"; static const char *alpn_proto_order_http1[] = {alpn_proto_list + 3, alpn_proto_list + 3 + 8, NULL}; #if defined(USE_HTTP2) static const char *alpn_proto_order_http2[] = {alpn_proto_list, alpn_proto_list + 3, alpn_proto_list + 3 + 8, NULL}; #endif static int alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { struct mg_domain_context *dom_ctx = (struct mg_domain_context *)arg; unsigned int i, j, enable_http2 = 0; const char **alpn_proto_order = alpn_proto_order_http1; struct mg_workerTLS *tls = (struct mg_workerTLS *)pthread_getspecific(sTlsKey); (void)ssl; if (tls == NULL) { /* Need to store protocol in Thread Local Storage */ /* If there is no Thread Local Storage, don't use ALPN */ return SSL_TLSEXT_ERR_NOACK; } #if defined(USE_HTTP2) enable_http2 = (0 == strcmp(dom_ctx->config[ENABLE_HTTP2], "yes")); if (enable_http2) { alpn_proto_order = alpn_proto_order_http2; } #endif for (j = 0; alpn_proto_order[j] != NULL; j++) { /* check all accepted protocols in this order */ const char *alpn_proto = alpn_proto_order[j]; /* search input for matching protocol */ for (i = 0; i < inlen; i++) { if (!memcmp(in + i, alpn_proto, (unsigned char)alpn_proto[0])) { *out = in + i + 1; *outlen = in[i]; tls->alpn_proto = alpn_proto; return SSL_TLSEXT_ERR_OK; } } } /* Nothing found */ return SSL_TLSEXT_ERR_NOACK; } static int next_protos_advertised_cb(SSL *ssl, const unsigned char **data, unsigned int *len, void *arg) { struct mg_domain_context *dom_ctx = (struct mg_domain_context *)arg; *data = (const unsigned char *)alpn_proto_list; *len = (unsigned int)strlen((const char *)data); (void)ssl; (void)dom_ctx; return SSL_TLSEXT_ERR_OK; } static int init_alpn(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx) { unsigned int alpn_len = (unsigned int)strlen((char *)alpn_proto_list); int ret = SSL_CTX_set_alpn_protos(dom_ctx->ssl_ctx, (const unsigned char *)alpn_proto_list, alpn_len); if (ret != 0) { mg_cry_ctx_internal(phys_ctx, "SSL_CTX_set_alpn_protos error: %s", ssl_error()); } SSL_CTX_set_alpn_select_cb(dom_ctx->ssl_ctx, alpn_select_cb, (void *)dom_ctx); SSL_CTX_set_next_protos_advertised_cb(dom_ctx->ssl_ctx, next_protos_advertised_cb, (void *)dom_ctx); return ret; } #endif /* Setup SSL CTX as required by CivetWeb */ static int init_ssl_ctx_impl(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx, const char *pem, const char *chain) { int callback_ret; int should_verify_peer; int peer_certificate_optional; const char *ca_path; const char *ca_file; int use_default_verify_paths; int verify_depth; struct timespec now_mt; md5_byte_t ssl_context_id[16]; md5_state_t md5state; int protocol_ver; int ssl_cache_timeout; #if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)) \ && !defined(NO_SSL_DL) if ((dom_ctx->ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) { mg_cry_ctx_internal(phys_ctx, "SSL_CTX_new (server) error: %s", ssl_error()); return 0; } #else if ((dom_ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { mg_cry_ctx_internal(phys_ctx, "SSL_CTX_new (server) error: %s", ssl_error()); return 0; } #endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */ #if defined(SSL_OP_NO_TLSv1_3) SSL_CTX_clear_options(dom_ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3); #else SSL_CTX_clear_options(dom_ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2); #endif protocol_ver = atoi(dom_ctx->config[SSL_PROTOCOL_VERSION]); SSL_CTX_set_options(dom_ctx->ssl_ctx, ssl_get_protocol(protocol_ver)); SSL_CTX_set_options(dom_ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE); SSL_CTX_set_options(dom_ctx->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); SSL_CTX_set_options(dom_ctx->ssl_ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); SSL_CTX_set_options(dom_ctx->ssl_ctx, SSL_OP_NO_COMPRESSION); #if defined(SSL_OP_NO_RENEGOTIATION) SSL_CTX_set_options(dom_ctx->ssl_ctx, SSL_OP_NO_RENEGOTIATION); #endif #if !defined(NO_SSL_DL) SSL_CTX_set_ecdh_auto(dom_ctx->ssl_ctx, 1); #endif /* NO_SSL_DL */ /* In SSL documentation examples callback defined without const * specifier 'void (*)(SSL *, int, int)' See: * https://www.openssl.org/docs/man1.0.2/ssl/ssl.html * https://www.openssl.org/docs/man1.1.0/ssl/ssl.html * But in the source code const SSL is used: * 'void (*)(const SSL *, int, int)' See: * https://github.com/openssl/openssl/blob/1d97c8435171a7af575f73c526d79e1ef0ee5960/ssl/ssl.h#L1173 * Problem about wrong documentation described, but not resolved: * https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/1147526 * Wrong const cast ignored on C or can be suppressed by compiler flags. * But when compiled with modern C++ compiler, correct const should be * provided */ SSL_CTX_set_info_callback(dom_ctx->ssl_ctx, ssl_info_callback); SSL_CTX_set_tlsext_servername_callback(dom_ctx->ssl_ctx, ssl_servername_callback); /* If a callback has been specified, call it. */ callback_ret = (phys_ctx->callbacks.init_ssl == NULL) ? 0 : (phys_ctx->callbacks.init_ssl(dom_ctx->ssl_ctx, phys_ctx->user_data)); /* If callback returns 0, civetweb sets up the SSL certificate. * If it returns 1, civetweb assumes the callback already did this. * If it returns -1, initializing ssl fails. */ if (callback_ret < 0) { mg_cry_ctx_internal(phys_ctx, "SSL callback returned error: %i", callback_ret); return 0; } if (callback_ret > 0) { /* Callback did everything. */ return 1; } /* If a domain callback has been specified, call it. */ callback_ret = (phys_ctx->callbacks.init_ssl_domain == NULL) ? 0 : (phys_ctx->callbacks.init_ssl_domain( dom_ctx->config[AUTHENTICATION_DOMAIN], dom_ctx->ssl_ctx, phys_ctx->user_data)); /* If domain callback returns 0, civetweb sets up the SSL certificate. * If it returns 1, civetweb assumes the callback already did this. * If it returns -1, initializing ssl fails. */ if (callback_ret < 0) { mg_cry_ctx_internal(phys_ctx, "Domain SSL callback returned error: %i", callback_ret); return 0; } if (callback_ret > 0) { /* Domain callback did everything. */ return 1; } /* Use some combination of start time, domain and port as a SSL * context ID. This should be unique on the current machine. */ md5_init(&md5state); clock_gettime(CLOCK_MONOTONIC, &now_mt); md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt)); md5_append(&md5state, (const md5_byte_t *)phys_ctx->dd.config[LISTENING_PORTS], strlen(phys_ctx->dd.config[LISTENING_PORTS])); md5_append(&md5state, (const md5_byte_t *)dom_ctx->config[AUTHENTICATION_DOMAIN], strlen(dom_ctx->config[AUTHENTICATION_DOMAIN])); md5_append(&md5state, (const md5_byte_t *)phys_ctx, sizeof(*phys_ctx)); md5_append(&md5state, (const md5_byte_t *)dom_ctx, sizeof(*dom_ctx)); md5_finish(&md5state, ssl_context_id); SSL_CTX_set_session_id_context(dom_ctx->ssl_ctx, (unsigned char *)ssl_context_id, sizeof(ssl_context_id)); if (pem != NULL) { if (!ssl_use_pem_file(phys_ctx, dom_ctx, pem, chain)) { return 0; } } /* Should we support client certificates? */ /* Default is "no". */ should_verify_peer = 0; peer_certificate_optional = 0; if (dom_ctx->config[SSL_DO_VERIFY_PEER] != NULL) { if (mg_strcasecmp(dom_ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0) { /* Yes, they are mandatory */ should_verify_peer = 1; } else if (mg_strcasecmp(dom_ctx->config[SSL_DO_VERIFY_PEER], "optional") == 0) { /* Yes, they are optional */ should_verify_peer = 1; peer_certificate_optional = 1; } } use_default_verify_paths = (dom_ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL) && (mg_strcasecmp(dom_ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0); if (should_verify_peer) { ca_path = dom_ctx->config[SSL_CA_PATH]; ca_file = dom_ctx->config[SSL_CA_FILE]; if (SSL_CTX_load_verify_locations(dom_ctx->ssl_ctx, ca_file, ca_path) != 1) { mg_cry_ctx_internal(phys_ctx, "SSL_CTX_load_verify_locations error: %s " "ssl_verify_peer requires setting " "either ssl_ca_path or ssl_ca_file. " "Is any of them present in the " ".conf file?", ssl_error()); return 0; } if (peer_certificate_optional) { SSL_CTX_set_verify(dom_ctx->ssl_ctx, SSL_VERIFY_PEER, NULL); } else { SSL_CTX_set_verify(dom_ctx->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); } if (use_default_verify_paths && (SSL_CTX_set_default_verify_paths(dom_ctx->ssl_ctx) != 1)) { mg_cry_ctx_internal(phys_ctx, "SSL_CTX_set_default_verify_paths error: %s", ssl_error()); return 0; } if (dom_ctx->config[SSL_VERIFY_DEPTH]) { verify_depth = atoi(dom_ctx->config[SSL_VERIFY_DEPTH]); SSL_CTX_set_verify_depth(dom_ctx->ssl_ctx, verify_depth); } } if (dom_ctx->config[SSL_CIPHER_LIST] != NULL) { if (SSL_CTX_set_cipher_list(dom_ctx->ssl_ctx, dom_ctx->config[SSL_CIPHER_LIST]) != 1) { mg_cry_ctx_internal(phys_ctx, "SSL_CTX_set_cipher_list error: %s", ssl_error()); } } /* SSL session caching */ ssl_cache_timeout = ((dom_ctx->config[SSL_CACHE_TIMEOUT] != NULL) ? atoi(dom_ctx->config[SSL_CACHE_TIMEOUT]) : 0); if (ssl_cache_timeout > 0) { SSL_CTX_set_session_cache_mode(dom_ctx->ssl_ctx, SSL_SESS_CACHE_BOTH); /* SSL_CTX_sess_set_cache_size(dom_ctx->ssl_ctx, 10000); ... use * default */ SSL_CTX_set_timeout(dom_ctx->ssl_ctx, (long)ssl_cache_timeout); } #if defined(USE_ALPN) /* Initialize ALPN only of TLS library (OpenSSL version) supports ALPN */ #if !defined(NO_SSL_DL) if (!tls_feature_missing[TLS_ALPN]) #endif { init_alpn(phys_ctx, dom_ctx); } #endif return 1; } /* Check if SSL is required. * If so, dynamically load SSL library * and set up ctx->ssl_ctx pointer. */ static int init_ssl_ctx(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx) { void *ssl_ctx = 0; int callback_ret; const char *pem; const char *chain; char ebuf[128]; if (!phys_ctx) { return 0; } if (!dom_ctx) { dom_ctx = &(phys_ctx->dd); } if (!is_ssl_port_used(dom_ctx->config[LISTENING_PORTS])) { /* No SSL port is set. No need to setup SSL. */ return 1; } /* Check for external SSL_CTX */ callback_ret = (phys_ctx->callbacks.external_ssl_ctx == NULL) ? 0 : (phys_ctx->callbacks.external_ssl_ctx(&ssl_ctx, phys_ctx->user_data)); if (callback_ret < 0) { /* Callback exists and returns <0: Initializing failed. */ mg_cry_ctx_internal(phys_ctx, "external_ssl_ctx callback returned error: %i", callback_ret); return 0; } else if (callback_ret > 0) { /* Callback exists and returns >0: Initializing complete, * civetweb should not modify the SSL context. */ dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx; if (!initialize_openssl(ebuf, sizeof(ebuf))) { mg_cry_ctx_internal(phys_ctx, "%s", ebuf); return 0; } return 1; } /* If the callback does not exist or return 0, civetweb must initialize * the SSL context. Handle "domain" callback next. */ /* Check for external domain SSL_CTX callback. */ callback_ret = (phys_ctx->callbacks.external_ssl_ctx_domain == NULL) ? 0 : (phys_ctx->callbacks.external_ssl_ctx_domain( dom_ctx->config[AUTHENTICATION_DOMAIN], &ssl_ctx, phys_ctx->user_data)); if (callback_ret < 0) { /* Callback < 0: Error. Abort init. */ mg_cry_ctx_internal( phys_ctx, "external_ssl_ctx_domain callback returned error: %i", callback_ret); return 0; } else if (callback_ret > 0) { /* Callback > 0: Consider init done. */ dom_ctx->ssl_ctx = (SSL_CTX *)ssl_ctx; if (!initialize_openssl(ebuf, sizeof(ebuf))) { mg_cry_ctx_internal(phys_ctx, "%s", ebuf); return 0; } return 1; } /* else: external_ssl_ctx/external_ssl_ctx_domain do not exist or return * 0, CivetWeb should continue initializing SSL */ /* If PEM file is not specified and the init_ssl callbacks * are not specified, setup will fail. */ if (((pem = dom_ctx->config[SSL_CERTIFICATE]) == NULL) && (phys_ctx->callbacks.init_ssl == NULL) && (phys_ctx->callbacks.init_ssl_domain == NULL)) { /* No certificate and no init_ssl callbacks: * Essential data to set up TLS is missing. */ mg_cry_ctx_internal(phys_ctx, "Initializing SSL failed: -%s is not set", config_options[SSL_CERTIFICATE].name); return 0; } /* If a certificate chain is configured, use it. */ chain = dom_ctx->config[SSL_CERTIFICATE_CHAIN]; if (chain == NULL) { /* Default: certificate chain in PEM file */ chain = pem; } if ((chain != NULL) && (*chain == 0)) { /* If the chain is an empty string, don't use it. */ chain = NULL; } if (!initialize_openssl(ebuf, sizeof(ebuf))) { mg_cry_ctx_internal(phys_ctx, "%s", ebuf); return 0; } return init_ssl_ctx_impl(phys_ctx, dom_ctx, pem, chain); } static void uninitialize_openssl(void) { #if defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0) if (mg_atomic_dec(&cryptolib_users) == 0) { /* Shutdown according to * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl */ CONF_modules_unload(1); #else int i; if (mg_atomic_dec(&cryptolib_users) == 0) { /* Shutdown according to * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl */ CRYPTO_set_locking_callback(NULL); CRYPTO_set_id_callback(NULL); ENGINE_cleanup(); CONF_modules_unload(1); ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); OPENSSL_REMOVE_THREAD_STATE(); for (i = 0; i < CRYPTO_num_locks(); i++) { pthread_mutex_destroy(&ssl_mutexes[i]); } mg_free(ssl_mutexes); ssl_mutexes = NULL; #endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */ } } #endif /* !defined(NO_SSL) && !defined(USE_MBEDTLS) */ #if !defined(NO_FILESYSTEMS) static int set_gpass_option(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx) { if (phys_ctx) { struct mg_file file = STRUCT_FILE_INITIALIZER; const char *path; struct mg_connection fc; if (!dom_ctx) { dom_ctx = &(phys_ctx->dd); } path = dom_ctx->config[GLOBAL_PASSWORDS_FILE]; if ((path != NULL) && !mg_stat(fake_connection(&fc, phys_ctx), path, &file.stat)) { mg_cry_ctx_internal(phys_ctx, "Cannot open %s: %s", path, strerror(ERRNO)); return 0; } return 1; } return 0; } #endif /* NO_FILESYSTEMS */ static int set_acl_option(struct mg_context *phys_ctx) { union usa sa; memset(&sa, 0, sizeof(sa)); #if defined(USE_IPV6) sa.sin6.sin6_family = AF_INET6; #else sa.sin.sin_family = AF_INET; #endif return check_acl(phys_ctx, &sa) != -1; } static void reset_per_request_attributes(struct mg_connection *conn) { if (!conn) { return; } conn->num_bytes_sent = conn->consumed_content = 0; conn->path_info = NULL; conn->status_code = -1; conn->content_len = -1; conn->is_chunked = 0; conn->must_close = 0; conn->request_len = 0; conn->request_state = 0; conn->throttle = 0; conn->accept_gzip = 0; conn->response_info.content_length = conn->request_info.content_length = -1; conn->response_info.http_version = conn->request_info.http_version = NULL; conn->response_info.num_headers = conn->request_info.num_headers = 0; conn->response_info.status_text = NULL; conn->response_info.status_code = 0; conn->request_info.remote_user = NULL; conn->request_info.request_method = NULL; conn->request_info.request_uri = NULL; /* Free cleaned local URI (if any) */ if (conn->request_info.local_uri != conn->request_info.local_uri_raw) { mg_free((void *)conn->request_info.local_uri); conn->request_info.local_uri = NULL; } conn->request_info.local_uri = NULL; #if defined(USE_SERVER_STATS) conn->processing_time = 0; #endif } static int set_tcp_nodelay(const struct socket *so, int nodelay_on) { if ((so->lsa.sa.sa_family == AF_INET) || (so->lsa.sa.sa_family == AF_INET6)) { /* Only for TCP sockets */ if (setsockopt(so->sock, IPPROTO_TCP, TCP_NODELAY, (SOCK_OPT_TYPE)&nodelay_on, sizeof(nodelay_on)) != 0) { /* Error */ return 1; } } /* OK */ return 0; } #if !defined(__ZEPHYR__) static void close_socket_gracefully(struct mg_connection *conn) { #if defined(_WIN32) char buf[MG_BUF_LEN]; int n; #endif struct linger linger; int error_code = 0; int linger_timeout = -2; socklen_t opt_len = sizeof(error_code); if (!conn) { return; } /* http://msdn.microsoft.com/en-us/library/ms739165(v=vs.85).aspx: * "Note that enabling a nonzero timeout on a nonblocking socket * is not recommended.", so set it to blocking now */ set_blocking_mode(conn->client.sock); /* Send FIN to the client */ shutdown(conn->client.sock, SHUTDOWN_WR); #if defined(_WIN32) /* Read and discard pending incoming data. If we do not do that and * close * the socket, the data in the send buffer may be discarded. This * behaviour is seen on Windows, when client keeps sending data * when server decides to close the connection; then when client * does recv() it gets no data back. */ do { n = pull_inner(NULL, conn, buf, sizeof(buf), /* Timeout in s: */ 1.0); } while (n > 0); #endif if (conn->dom_ctx->config[LINGER_TIMEOUT]) { linger_timeout = atoi(conn->dom_ctx->config[LINGER_TIMEOUT]); } /* Set linger option according to configuration */ if (linger_timeout >= 0) { /* Set linger option to avoid socket hanging out after close. This * prevent ephemeral port exhaust problem under high QPS. */ linger.l_onoff = 1; #if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4244) #endif #if defined(GCC_DIAGNOSTIC) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" #endif /* Data type of linger structure elements may differ, * so we don't know what cast we need here. * Disable type conversion warnings. */ linger.l_linger = (linger_timeout + 999) / 1000; #if defined(GCC_DIAGNOSTIC) # pragma GCC diagnostic pop #endif #if defined(_MSC_VER) # pragma warning(pop) #endif } else { linger.l_onoff = 0; linger.l_linger = 0; } if (linger_timeout < -1) { /* Default: don't configure any linger */ } else if (getsockopt(conn->client.sock, SOL_SOCKET, SO_ERROR, #if defined(_WIN32) /* WinSock uses different data type here */ (char *)&error_code, #else &error_code, #endif &opt_len) != 0) { /* Cannot determine if socket is already closed. This should * not occur and never did in a test. Log an error message * and continue. */ mg_cry_internal(conn, "%s: getsockopt(SOL_SOCKET SO_ERROR) failed: %s", __func__, strerror(ERRNO)); #if defined(_WIN32) } else if (error_code == WSAECONNRESET) { #else } else if (error_code == ECONNRESET) { #endif /* Socket already closed by client/peer, close socket without linger */ } else { /* Set linger timeout */ if (setsockopt(conn->client.sock, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger)) != 0) { mg_cry_internal( conn, "%s: setsockopt(SOL_SOCKET SO_LINGER(%i,%i)) failed: %s", __func__, linger.l_onoff, linger.l_linger, strerror(ERRNO)); } } /* Now we know that our FIN is ACK-ed, safe to close */ closesocket(conn->client.sock); conn->client.sock = INVALID_SOCKET; } #endif static void close_connection(struct mg_connection *conn) { #if defined(USE_SERVER_STATS) conn->conn_state = 6; /* to close */ #endif #if defined(USE_LUA) && defined(USE_WEBSOCKET) if (conn->lua_websocket_state) { lua_websocket_close(conn, conn->lua_websocket_state); conn->lua_websocket_state = NULL; } #endif mg_lock_connection(conn); /* Set close flag, so keep-alive loops will stop */ conn->must_close = 1; /* call the connection_close callback if assigned */ if (conn->phys_ctx->callbacks.connection_close != NULL) { if (conn->phys_ctx->context_type == CONTEXT_SERVER) { conn->phys_ctx->callbacks.connection_close(conn); } } /* Reset user data, after close callback is called. * Do not reuse it. If the user needs a destructor, * it must be done in the connection_close callback. */ mg_set_user_connection_data(conn, NULL); #if defined(USE_SERVER_STATS) conn->conn_state = 7; /* closing */ #endif #if defined(USE_MBEDTLS) if (conn->ssl != NULL) { mbed_ssl_close(conn->ssl); conn->ssl = NULL; } #elif !defined(NO_SSL) if (conn->ssl != NULL) { /* Run SSL_shutdown twice to ensure completely close SSL connection */ SSL_shutdown(conn->ssl); SSL_free(conn->ssl); OPENSSL_REMOVE_THREAD_STATE(); conn->ssl = NULL; } #endif if (conn->client.sock != INVALID_SOCKET) { #if defined(__ZEPHYR__) closesocket(conn->client.sock); #else close_socket_gracefully(conn); #endif conn->client.sock = INVALID_SOCKET; } /* call the connection_closed callback if assigned */ if (conn->phys_ctx->callbacks.connection_closed != NULL) { if (conn->phys_ctx->context_type == CONTEXT_SERVER) { conn->phys_ctx->callbacks.connection_closed(conn); } } mg_unlock_connection(conn); #if defined(USE_SERVER_STATS) conn->conn_state = 8; /* closed */ #endif } CIVETWEB_API void mg_close_connection(struct mg_connection *conn) { if ((conn == NULL) || (conn->phys_ctx == NULL)) { return; } #if defined(USE_WEBSOCKET) if (conn->phys_ctx->context_type == CONTEXT_SERVER) { if (conn->in_websocket_handling) { /* Set close flag, so the server thread can exit. */ conn->must_close = 1; return; } } if (conn->phys_ctx->context_type == CONTEXT_WS_CLIENT) { unsigned int i; /* client context: loops must end */ STOP_FLAG_ASSIGN(&conn->phys_ctx->stop_flag, 1); conn->must_close = 1; /* We need to get the client thread out of the select/recv call * here. */ /* Since we use a sleep quantum of some seconds to check for recv * timeouts, we will just wait a few seconds in mg_join_thread. */ /* join worker thread */ for (i = 0; i < conn->phys_ctx->cfg_worker_threads; i++) { mg_join_thread(conn->phys_ctx->worker_threadids[i]); } } #endif /* defined(USE_WEBSOCKET) */ close_connection(conn); #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client if (((conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) || (conn->phys_ctx->context_type == CONTEXT_WS_CLIENT)) && (conn->phys_ctx->dd.ssl_ctx != NULL)) { SSL_CTX_free(conn->phys_ctx->dd.ssl_ctx); } #endif #if defined(USE_WEBSOCKET) if (conn->phys_ctx->context_type == CONTEXT_WS_CLIENT) { mg_free(conn->phys_ctx->worker_threadids); (void)pthread_mutex_destroy(&conn->mutex); mg_free(conn); } else if (conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) { (void)pthread_mutex_destroy(&conn->mutex); mg_free(conn); } #else if (conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) { /* Client */ (void)pthread_mutex_destroy(&conn->mutex); mg_free(conn); } #endif /* defined(USE_WEBSOCKET) */ } static struct mg_connection * mg_connect_client_impl(const struct mg_client_options *client_options, int use_ssl, struct mg_init_data *init, struct mg_error_data *error) { struct mg_connection *conn = NULL; SOCKET sock; union usa sa; struct sockaddr *psa; socklen_t len; unsigned max_req_size = (unsigned)atoi(config_options[MAX_REQUEST_SIZE].default_value); /* Size of structures, aligned to 8 bytes */ size_t conn_size = ((sizeof(struct mg_connection) + 7) >> 3) << 3; size_t ctx_size = ((sizeof(struct mg_context) + 7) >> 3) << 3; size_t alloc_size = conn_size + ctx_size + max_req_size; (void)init; /* TODO: Implement required options */ conn = (struct mg_connection *)mg_calloc(1, alloc_size); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OK; error->code_sub = 0; if (error->text_buffer_size > 0) { error->text[0] = 0; } } if (conn == NULL) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY; error->code_sub = (unsigned)alloc_size; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "calloc(): %s", strerror(ERRNO)); } return NULL; } #if defined(GCC_DIAGNOSTIC) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wcast-align" #endif /* defined(GCC_DIAGNOSTIC) */ /* conn_size is aligned to 8 bytes */ conn->phys_ctx = (struct mg_context *)(((char *)conn) + conn_size); #if defined(GCC_DIAGNOSTIC) # pragma GCC diagnostic pop #endif /* defined(GCC_DIAGNOSTIC) */ conn->buf = (((char *)conn) + conn_size + ctx_size); conn->buf_size = (int)max_req_size; conn->phys_ctx->context_type = CONTEXT_HTTP_CLIENT; conn->dom_ctx = &(conn->phys_ctx->dd); if (!connect_socket(conn->phys_ctx, client_options->host, client_options->port, use_ssl, error, &sock, &sa)) { /* "error" will be set by connect_socket. */ /* free all memory and return NULL; */ mg_free(conn); return NULL; } #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client #if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0)) \ && !defined(NO_SSL_DL) if (use_ssl && (conn->dom_ctx->ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "SSL_CTX_new error: %s", ssl_error()); } closesocket(sock); mg_free(conn); return NULL; } #else if (use_ssl && (conn->dom_ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "SSL_CTX_new error: %s", ssl_error()); } closesocket(sock); mg_free(conn); return NULL; } #endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */ #endif /* NO_SSL */ #if defined(USE_IPV6) len = (sa.sa.sa_family == AF_INET) ? sizeof(conn->client.rsa.sin) : sizeof(conn->client.rsa.sin6); psa = (sa.sa.sa_family == AF_INET) ? (struct sockaddr *)&(conn->client.rsa.sin) : (struct sockaddr *)&(conn->client.rsa.sin6); #else len = sizeof(conn->client.rsa.sin); psa = (struct sockaddr *)&(conn->client.rsa.sin); #endif conn->client.sock = sock; conn->client.lsa = sa; if (getsockname(sock, psa, &len) != 0) { mg_cry_internal(conn, "%s: getsockname() failed: %s", __func__, strerror(ERRNO)); } conn->client.is_ssl = use_ssl ? 1 : 0; if (0 != pthread_mutex_init(&conn->mutex, &pthread_mutex_attr)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OS_ERROR; error->code_sub = (unsigned)ERRNO; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "Can not create mutex"); } #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client SSL_CTX_free(conn->dom_ctx->ssl_ctx); #endif closesocket(sock); mg_free(conn); return NULL; } #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client if (use_ssl) { /* TODO: Check ssl_verify_peer and ssl_ca_path here. * SSL_CTX_set_verify call is needed to switch off server * certificate checking, which is off by default in OpenSSL and * on in yaSSL. */ /* TODO: SSL_CTX_set_verify(conn->dom_ctx, * SSL_VERIFY_PEER, verify_ssl_server); */ if (client_options->client_cert) { if (!ssl_use_pem_file(conn->phys_ctx, conn->dom_ctx, client_options->client_cert, NULL)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_TLS_CLIENT_CERT_ERROR; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "Can not use SSL client certificate"); } SSL_CTX_free(conn->dom_ctx->ssl_ctx); closesocket(sock); mg_free(conn); return NULL; } } if (client_options->server_cert) { if (SSL_CTX_load_verify_locations(conn->dom_ctx->ssl_ctx, client_options->server_cert, NULL) != 1) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_TLS_SERVER_CERT_ERROR; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "SSL_CTX_load_verify_locations error: %s", ssl_error()); } SSL_CTX_free(conn->dom_ctx->ssl_ctx); closesocket(sock); mg_free(conn); return NULL; } SSL_CTX_set_verify(conn->dom_ctx->ssl_ctx, SSL_VERIFY_PEER, NULL); } else { SSL_CTX_set_verify(conn->dom_ctx->ssl_ctx, SSL_VERIFY_NONE, NULL); } if (!sslize(conn, SSL_connect, client_options)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_TLS_CONNECT_ERROR; mg_snprintf(NULL, NULL, /* No truncation check for ebuf */ error->text, error->text_buffer_size, "SSL connection error"); } SSL_CTX_free(conn->dom_ctx->ssl_ctx); closesocket(sock); mg_free(conn); return NULL; } } #endif return conn; } CIVETWEB_API struct mg_connection * mg_connect_client_secure(const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size) { struct mg_init_data init; struct mg_error_data error; memset(&init, 0, sizeof(init)); memset(&error, 0, sizeof(error)); error.text_buffer_size = error_buffer_size; error.text = error_buffer; return mg_connect_client_impl(client_options, 1, &init, &error); } CIVETWEB_API struct mg_connection * mg_connect_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size) { struct mg_client_options opts; struct mg_init_data init; struct mg_error_data error; memset(&init, 0, sizeof(init)); memset(&error, 0, sizeof(error)); error.text_buffer_size = error_buffer_size; error.text = error_buffer; memset(&opts, 0, sizeof(opts)); opts.host = host; opts.port = port; if (use_ssl) { opts.host_name = host; } return mg_connect_client_impl(&opts, use_ssl, &init, &error); } #if defined(MG_EXPERIMENTAL_INTERFACES) CIVETWEB_API struct mg_connection * mg_connect_client2(const char *host, const char *protocol, int port, const char *path, struct mg_init_data *init, struct mg_error_data *error) { (void)path; int is_ssl, is_ws; /* void *user_data = (init != NULL) ? init->user_data : NULL; -- TODO */ if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OK; error->code_sub = 0; if (error->text_buffer_size > 0) { *error->text = 0; } } if ((host == NULL) || (protocol == NULL)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_PARAM; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", "Invalid parameters"); } return NULL; } /* check all known protocols */ if (!mg_strcasecmp(protocol, "http")) { is_ssl = 0; is_ws = 0; } else if (!mg_strcasecmp(protocol, "https")) { is_ssl = 1; is_ws = 0; #if defined(USE_WEBSOCKET) } else if (!mg_strcasecmp(protocol, "ws")) { is_ssl = 0; is_ws = 1; } else if (!mg_strcasecmp(protocol, "wss")) { is_ssl = 1; is_ws = 1; #endif } else { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_PARAM; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Protocol %s not supported", protocol); } return NULL; } /* TODO: The current implementation here just calls the old * implementations, without using any new options. This is just a first * step to test the new interfaces. */ #if defined(USE_WEBSOCKET) if (is_ws) { /* TODO: implement all options */ return mg_connect_websocket_client( host, port, is_ssl, ((error != NULL) ? error->text : NULL), ((error != NULL) ? error->text_buffer_size : 0), (path ? path : ""), NULL /* TODO: origin */, experimental_websocket_client_data_wrapper, experimental_websocket_client_close_wrapper, (void *)init->callbacks); } #else (void)is_ws; #endif /* TODO: all additional options */ struct mg_client_options opts; memset(&opts, 0, sizeof(opts)); opts.host = host; opts.port = port; return mg_connect_client_impl(&opts, is_ssl, init, error); } #endif static const struct { const char *proto; size_t proto_len; unsigned default_port; } abs_uri_protocols[] = {{"http://", 7, 80}, {"https://", 8, 443}, {"ws://", 5, 80}, {"wss://", 6, 443}, {NULL, 0, 0}}; /* Check if the uri is valid. * return 0 for invalid uri, * return 1 for *, * return 2 for relative uri, * return 3 for absolute uri without port, * return 4 for absolute uri with port */ static int get_uri_type(const char *uri) { int i; const char *hostend, *portbegin; char *portend; unsigned long port; /* According to the HTTP standard * http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 * URI can be an asterisk (*) or should start with slash (relative uri), * or it should start with the protocol (absolute uri). */ if ((uri[0] == '*') && (uri[1] == '\0')) { /* asterisk */ return 1; } /* Valid URIs according to RFC 3986 * (https://www.ietf.org/rfc/rfc3986.txt) * must only contain reserved characters :/?#[]@!$&'()*+,;= * and unreserved characters A-Z a-z 0-9 and -._~ * and % encoded symbols. */ for (i = 0; uri[i] != 0; i++) { if (uri[i] < 33) { /* control characters and spaces are invalid */ return 0; } /* Allow everything else here (See #894) */ } /* A relative uri starts with a / character */ if (uri[0] == '/') { /* relative uri */ return 2; } /* It could be an absolute uri: */ /* This function only checks if the uri is valid, not if it is * addressing the current server. So civetweb can also be used * as a proxy server. */ for (i = 0; abs_uri_protocols[i].proto != NULL; i++) { if (mg_strncasecmp(uri, abs_uri_protocols[i].proto, abs_uri_protocols[i].proto_len) == 0) { hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/'); if (!hostend) { return 0; } portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':'); if (!portbegin) { return 3; } port = strtoul(portbegin + 1, &portend, 10); if ((portend != hostend) || (port <= 0) || !is_valid_port(port)) { return 0; } return 4; } } return 0; } /* Return NULL or the relative uri at the current server */ static const char * get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn) { const char *server_domain; size_t server_domain_len; size_t request_domain_len = 0; unsigned long port = 0; int i, auth_domain_check_enabled; const char *hostbegin = NULL; const char *hostend = NULL; const char *portbegin; char *portend; auth_domain_check_enabled = !mg_strcasecmp(conn->dom_ctx->config[ENABLE_AUTH_DOMAIN_CHECK], "yes"); /* DNS is case insensitive, so use case insensitive string compare here */ for (i = 0; abs_uri_protocols[i].proto != NULL; i++) { if (mg_strncasecmp(uri, abs_uri_protocols[i].proto, abs_uri_protocols[i].proto_len) == 0) { hostbegin = uri + abs_uri_protocols[i].proto_len; hostend = strchr(hostbegin, '/'); if (!hostend) { return 0; } portbegin = strchr(hostbegin, ':'); if ((!portbegin) || (portbegin > hostend)) { port = abs_uri_protocols[i].default_port; request_domain_len = (size_t)(hostend - hostbegin); } else { port = strtoul(portbegin + 1, &portend, 10); if ((portend != hostend) || (port <= 0) || !is_valid_port(port)) { return 0; } request_domain_len = (size_t)(portbegin - hostbegin); } /* protocol found, port set */ break; } } if (!port) { /* port remains 0 if the protocol is not found */ return 0; } /* Check if the request is directed to a different server. */ /* First check if the port is the same. */ if (ntohs(USA_IN_PORT_UNSAFE(&conn->client.lsa)) != port) { /* Request is directed to a different port */ return 0; } /* Finally check if the server corresponds to the authentication * domain of the server (the server domain). * Allow full matches (like http://mydomain.com/path/file.ext), and * allow subdomain matches (like http://www.mydomain.com/path/file.ext), * but do not allow substrings (like * http://notmydomain.com/path/file.ext * or http://mydomain.com.fake/path/file.ext). */ if (auth_domain_check_enabled) { server_domain = conn->dom_ctx->config[AUTHENTICATION_DOMAIN]; server_domain_len = strlen(server_domain); if ((server_domain_len == 0) || (hostbegin == NULL)) { return 0; } if ((request_domain_len == server_domain_len) && (!memcmp(server_domain, hostbegin, server_domain_len))) { /* Request is directed to this server - full name match. */ } else { if (request_domain_len < (server_domain_len + 2)) { /* Request is directed to another server: The server name * is longer than the request name. * Drop this case here to avoid overflows in the * following checks. */ return 0; } if (hostbegin[request_domain_len - server_domain_len - 1] != '.') { /* Request is directed to another server: It could be a * substring * like notmyserver.com */ return 0; } if (0 != memcmp(server_domain, hostbegin + request_domain_len - server_domain_len, server_domain_len)) { /* Request is directed to another server: * The server name is different. */ return 0; } } } return hostend; } static int get_message(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err) { if (ebuf_len > 0) { ebuf[0] = '\0'; } *err = 0; reset_per_request_attributes(conn); if (!conn) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Internal error"); *err = 500; return 0; } /* Set the time the request was received. This value should be used for * timeouts. */ clock_gettime(CLOCK_MONOTONIC, &(conn->req_time)); conn->request_len = read_message(NULL, conn, conn->buf, conn->buf_size, &conn->data_len); DEBUG_ASSERT(conn->request_len < 0 || conn->data_len >= conn->request_len); if ((conn->request_len >= 0) && (conn->data_len < conn->request_len)) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Invalid message size"); *err = 500; return 0; } if ((conn->request_len == 0) && (conn->data_len == conn->buf_size)) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Message too large"); *err = 413; return 0; } if (conn->request_len <= 0) { if (conn->data_len > 0) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Malformed message"); *err = 400; } else { /* Server did not recv anything -> just close the connection */ conn->must_close = 1; mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "No data received"); *err = 0; } return 0; } return 1; } static int get_request(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err) { const char *cl; conn->connection_type = CONNECTION_TYPE_REQUEST; /* request (valid of not) */ if (!get_message(conn, ebuf, ebuf_len, err)) { return 0; } if (parse_http_request(conn->buf, conn->buf_size, &conn->request_info) <= 0) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Bad request"); *err = 400; return 0; } /* Message is a valid request */ if (!switch_domain_context(conn)) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Bad request: Host mismatch"); *err = 400; return 0; } #if USE_ZLIB if (((cl = get_header(conn->request_info.http_headers, conn->request_info.num_headers, "Accept-Encoding")) != NULL) && strstr(cl, "gzip")) { conn->accept_gzip = 1; } #endif if (((cl = get_header(conn->request_info.http_headers, conn->request_info.num_headers, "Transfer-Encoding")) != NULL) && mg_strcasecmp(cl, "identity")) { if (mg_strcasecmp(cl, "chunked")) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Bad request"); *err = 400; return 0; } conn->is_chunked = 1; conn->content_len = 0; /* not yet read */ } else if ((cl = get_header(conn->request_info.http_headers, conn->request_info.num_headers, "Content-Length")) != NULL) { /* Request has content length set */ char *endptr = NULL; conn->content_len = strtoll(cl, &endptr, 10); if ((endptr == cl) || (conn->content_len < 0)) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Bad request"); *err = 411; return 0; } /* Publish the content length back to the request info. */ conn->request_info.content_length = conn->content_len; } else { /* There is no exception, see RFC7230. */ conn->content_len = 0; } return 1; } /* conn is assumed to be valid in this internal function */ static int get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err) { const char *cl; conn->connection_type = CONNECTION_TYPE_RESPONSE; /* response (valid or not) */ if (!get_message(conn, ebuf, ebuf_len, err)) { return 0; } if (parse_http_response(conn->buf, conn->buf_size, &conn->response_info) <= 0) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Bad response"); *err = 400; return 0; } /* Message is a valid response */ if (((cl = get_header(conn->response_info.http_headers, conn->response_info.num_headers, "Transfer-Encoding")) != NULL) && mg_strcasecmp(cl, "identity")) { if (mg_strcasecmp(cl, "chunked")) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Bad request"); *err = 400; return 0; } conn->is_chunked = 1; conn->content_len = 0; /* not yet read */ } else if ((cl = get_header(conn->response_info.http_headers, conn->response_info.num_headers, "Content-Length")) != NULL) { char *endptr = NULL; conn->content_len = strtoll(cl, &endptr, 10); if ((endptr == cl) || (conn->content_len < 0)) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Bad request"); *err = 411; return 0; } /* Publish the content length back to the response info. */ conn->response_info.content_length = conn->content_len; /* TODO: check if it is still used in response_info */ conn->request_info.content_length = conn->content_len; /* TODO: we should also consider HEAD method */ if (conn->response_info.status_code == 304) { conn->content_len = 0; } } else { /* TODO: we should also consider HEAD method */ if (((conn->response_info.status_code >= 100) && (conn->response_info.status_code <= 199)) || (conn->response_info.status_code == 204) || (conn->response_info.status_code == 304)) { conn->content_len = 0; } else { conn->content_len = -1; /* unknown content length */ } } return 1; } CIVETWEB_API int mg_get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int timeout) { int err, ret; char txt[32]; /* will not overflow */ char *save_timeout; char *new_timeout; if (ebuf_len > 0) { ebuf[0] = '\0'; } if (!conn) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Parameter error"); return -1; } /* Reset the previous responses */ conn->data_len = 0; /* Implementation of API function for HTTP clients */ save_timeout = conn->dom_ctx->config[REQUEST_TIMEOUT]; if (timeout >= 0) { mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout); new_timeout = txt; } else { new_timeout = NULL; } conn->dom_ctx->config[REQUEST_TIMEOUT] = new_timeout; ret = get_response(conn, ebuf, ebuf_len, &err); conn->dom_ctx->config[REQUEST_TIMEOUT] = save_timeout; /* TODO: here, the URI is the http response code */ conn->request_info.local_uri_raw = conn->request_info.request_uri; conn->request_info.local_uri = conn->request_info.local_uri_raw; /* TODO (mid): Define proper return values - maybe return length? * For the first test use <0 for error and >0 for OK */ return (ret == 0) ? -1 : +1; } CIVETWEB_API struct mg_connection * mg_download(const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, const char *fmt, ...) { struct mg_connection *conn; va_list ap; int i; int reqerr; if (ebuf_len > 0) { ebuf[0] = '\0'; } va_start(ap, fmt); /* open a connection */ conn = mg_connect_client(host, port, use_ssl, ebuf, ebuf_len); if (conn != NULL) { i = mg_vprintf(conn, fmt, ap); if (i <= 0) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, ebuf_len, "%s", "Error sending request"); } else { /* make sure the buffer is clear */ conn->data_len = 0; get_response(conn, ebuf, ebuf_len, &reqerr); /* TODO: here, the URI is the http response code */ conn->request_info.local_uri = conn->request_info.request_uri; } } /* if an error occurred, close the connection */ if ((ebuf[0] != '\0') && (conn != NULL)) { mg_close_connection(conn); conn = NULL; } va_end(ap); return conn; } struct websocket_client_thread_data { struct mg_connection *conn; mg_websocket_data_handler data_handler; mg_websocket_close_handler close_handler; void *callback_data; }; #if defined(USE_WEBSOCKET) #if defined(_WIN32) static unsigned __stdcall websocket_client_thread(void *data) #else static void * websocket_client_thread(void *data) #endif { struct websocket_client_thread_data *cdata = (struct websocket_client_thread_data *)data; void *user_thread_ptr = NULL; #if !defined(_WIN32) && !defined(__ZEPHYR__) struct sigaction sa; /* Ignore SIGPIPE */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); #endif mg_set_thread_name("ws-clnt"); if (cdata->conn->phys_ctx) { if (cdata->conn->phys_ctx->callbacks.init_thread) { /* 3 indicates a websocket client thread */ /* TODO: check if conn->phys_ctx can be set */ user_thread_ptr = cdata->conn->phys_ctx->callbacks.init_thread( cdata->conn->phys_ctx, 3); } } read_websocket(cdata->conn, cdata->data_handler, cdata->callback_data); DEBUG_TRACE("%s", "Websocket client thread exited\n"); if (cdata->close_handler != NULL) { cdata->close_handler(cdata->conn, cdata->callback_data); } /* The websocket_client context has only this thread. If it runs out, set the stop_flag to 2 (= "stopped"). */ STOP_FLAG_ASSIGN(&cdata->conn->phys_ctx->stop_flag, 2); if (cdata->conn->phys_ctx->callbacks.exit_thread) { cdata->conn->phys_ctx->callbacks.exit_thread(cdata->conn->phys_ctx, 3, user_thread_ptr); } mg_free((void *)cdata); #if defined(_WIN32) return 0; #else return NULL; #endif } #endif static struct mg_connection * mg_connect_websocket_client_impl(const struct mg_client_options *client_options, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, const char *extensions, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data) { struct mg_connection *conn = NULL; #if defined(USE_WEBSOCKET) struct websocket_client_thread_data *thread_data; static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw=="; const char *host = client_options->host; int i; struct mg_init_data init; struct mg_error_data error; memset(&init, 0, sizeof(init)); memset(&error, 0, sizeof(error)); error.text_buffer_size = error_buffer_size; error.text = error_buffer; #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wformat-nonliteral" #endif /* Establish the client connection and request upgrade */ conn = mg_connect_client_impl(client_options, use_ssl, &init, &error); /* Connection object will be null if something goes wrong */ if (conn == NULL) { /* error_buffer should be already filled ... */ if (!error_buffer[0]) { /* ... if not add an error message */ mg_snprintf(conn, NULL, /* No truncation check for ebuf */ error_buffer, error_buffer_size, "Unexpected error"); } return NULL; } if (origin != NULL) { if (extensions != NULL) { i = mg_printf(conn, "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Key: %s\r\n" "Sec-WebSocket-Version: 13\r\n" "Sec-WebSocket-Extensions: %s\r\n" "Origin: %s\r\n" "\r\n", path, host, magic, extensions, origin); } else { i = mg_printf(conn, "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Key: %s\r\n" "Sec-WebSocket-Version: 13\r\n" "Origin: %s\r\n" "\r\n", path, host, magic, origin); } } else { if (extensions != NULL) { i = mg_printf(conn, "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Key: %s\r\n" "Sec-WebSocket-Version: 13\r\n" "Sec-WebSocket-Extensions: %s\r\n" "\r\n", path, host, magic, extensions); } else { i = mg_printf(conn, "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Key: %s\r\n" "Sec-WebSocket-Version: 13\r\n" "\r\n", path, host, magic); } } if (i <= 0) { mg_snprintf(conn, NULL, /* No truncation check for ebuf */ error_buffer, error_buffer_size, "%s", "Error sending request"); mg_close_connection(conn); return NULL; } conn->data_len = 0; if (!get_response(conn, error_buffer, error_buffer_size, &i)) { mg_close_connection(conn); return NULL; } conn->request_info.local_uri_raw = conn->request_info.request_uri; conn->request_info.local_uri = conn->request_info.local_uri_raw; #if defined(__clang__) # pragma clang diagnostic pop #endif if (conn->response_info.status_code != 101) { /* We sent an "upgrade" request. For a correct websocket * protocol handshake, we expect a "101 Continue" response. * Otherwise it is a protocol violation. Maybe the HTTP * Server does not know websockets. */ if (!*error_buffer) { /* set an error, if not yet set */ mg_snprintf(conn, NULL, /* No truncation check for ebuf */ error_buffer, error_buffer_size, "Unexpected server reply"); } DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer); mg_close_connection(conn); return NULL; } thread_data = (struct websocket_client_thread_data *)mg_calloc_ctx( 1, sizeof(struct websocket_client_thread_data), conn->phys_ctx); if (!thread_data) { DEBUG_TRACE("%s\r\n", "Out of memory"); mg_close_connection(conn); return NULL; } thread_data->conn = conn; thread_data->data_handler = data_func; thread_data->close_handler = close_func; thread_data->callback_data = user_data; conn->phys_ctx->worker_threadids = (pthread_t *)mg_calloc_ctx(1, sizeof(pthread_t), conn->phys_ctx); if (!conn->phys_ctx->worker_threadids) { DEBUG_TRACE("%s\r\n", "Out of memory"); mg_free(thread_data); mg_close_connection(conn); return NULL; } /* Now upgrade to ws/wss client context */ conn->phys_ctx->user_data = user_data; conn->phys_ctx->context_type = CONTEXT_WS_CLIENT; conn->phys_ctx->cfg_worker_threads = 1; /* one worker thread */ /* Start a thread to read the websocket client connection * This thread will automatically stop when mg_disconnect is * called on the client connection */ if (mg_start_thread_with_id(websocket_client_thread, thread_data, conn->phys_ctx->worker_threadids) != 0) { conn->phys_ctx->cfg_worker_threads = 0; mg_free(thread_data); mg_close_connection(conn); conn = NULL; DEBUG_TRACE("%s", "Websocket client connect thread could not be started\r\n"); } #else /* Appease "unused parameter" warnings */ (void)client_options; (void)use_ssl; (void)error_buffer; (void)error_buffer_size; (void)path; (void)origin; (void)extensions; (void)user_data; (void)data_func; (void)close_func; #endif return conn; } CIVETWEB_API struct mg_connection * mg_connect_websocket_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data) { struct mg_client_options client_options; memset(&client_options, 0, sizeof(client_options)); client_options.host = host; client_options.port = port; return mg_connect_websocket_client_impl(&client_options, use_ssl, error_buffer, error_buffer_size, path, origin, NULL, data_func, close_func, user_data); } CIVETWEB_API struct mg_connection * mg_connect_websocket_client_secure( const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data) { if (!client_options) { return NULL; } return mg_connect_websocket_client_impl(client_options, 1, error_buffer, error_buffer_size, path, origin, NULL, data_func, close_func, user_data); } CIVETWEB_API struct mg_connection * mg_connect_websocket_client_extensions(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, const char *extensions, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data) { struct mg_client_options client_options; memset(&client_options, 0, sizeof(client_options)); client_options.host = host; client_options.port = port; return mg_connect_websocket_client_impl(&client_options, use_ssl, error_buffer, error_buffer_size, path, origin, extensions, data_func, close_func, user_data); } CIVETWEB_API struct mg_connection * mg_connect_websocket_client_secure_extensions( const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, const char *extensions, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data) { if (!client_options) { return NULL; } return mg_connect_websocket_client_impl(client_options, 1, error_buffer, error_buffer_size, path, origin, extensions, data_func, close_func, user_data); } /* Prepare connection data structure */ static void init_connection(struct mg_connection *conn) { /* Is keep alive allowed by the server */ int keep_alive_enabled = !mg_strcasecmp(conn->dom_ctx->config[ENABLE_KEEP_ALIVE], "yes"); if (!keep_alive_enabled) { conn->must_close = 1; } /* Important: on new connection, reset the receiving buffer. Credit * goes to crule42. */ conn->data_len = 0; conn->handled_requests = 0; conn->connection_type = CONNECTION_TYPE_INVALID; conn->request_info.acceptedWebSocketSubprotocol = NULL; mg_set_user_connection_data(conn, NULL); #if defined(USE_SERVER_STATS) conn->conn_state = 2; /* init */ #endif /* call the init_connection callback if assigned */ if (conn->phys_ctx->callbacks.init_connection != NULL) { if (conn->phys_ctx->context_type == CONTEXT_SERVER) { void *conn_data = NULL; conn->phys_ctx->callbacks.init_connection(conn, &conn_data); mg_set_user_connection_data(conn, conn_data); } } } /* Process a connection - may handle multiple requests * using the same connection. * Must be called with a valid connection (conn and * conn->phys_ctx must be valid). */ static void process_new_connection(struct mg_connection *conn) { struct mg_request_info *ri = &conn->request_info; int keep_alive, discard_len; char ebuf[100]; const char *hostend; int reqerr, uri_type; #if defined(USE_SERVER_STATS) ptrdiff_t mcon = mg_atomic_inc(&(conn->phys_ctx->active_connections)); mg_atomic_add(&(conn->phys_ctx->total_connections), 1); mg_atomic_max(&(conn->phys_ctx->max_active_connections), mcon); #endif DEBUG_TRACE("Start processing connection from %s", conn->request_info.remote_addr); /* Loop over multiple requests sent using the same connection * (while "keep alive"). */ do { DEBUG_TRACE("calling get_request (%i times for this connection)", conn->handled_requests + 1); #if defined(USE_SERVER_STATS) conn->conn_state = 3; /* ready */ #endif if (!get_request(conn, ebuf, sizeof(ebuf), &reqerr)) { /* The request sent by the client could not be understood by * the server, or it was incomplete or a timeout. Send an * error message and close the connection. */ if (reqerr > 0) { DEBUG_ASSERT(ebuf[0] != '\0'); mg_send_http_error(conn, reqerr, "%s", ebuf); } } else if (strcmp(ri->http_version, "1.0") && strcmp(ri->http_version, "1.1")) { /* HTTP/2 is not allowed here */ mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, sizeof(ebuf), "Bad HTTP version: [%s]", ri->http_version); mg_send_http_error(conn, 505, "%s", ebuf); } if (ebuf[0] == '\0') { uri_type = get_uri_type(conn->request_info.request_uri); switch (uri_type) { case 1: /* Asterisk */ conn->request_info.local_uri_raw = 0; /* TODO: Deal with '*'. */ break; case 2: /* relative uri */ conn->request_info.local_uri_raw = conn->request_info.request_uri; break; case 3: case 4: /* absolute uri (with/without port) */ hostend = get_rel_url_at_current_server( conn->request_info.request_uri, conn); if (hostend) { conn->request_info.local_uri_raw = hostend; } else { conn->request_info.local_uri_raw = NULL; } break; default: mg_snprintf(conn, NULL, /* No truncation check for ebuf */ ebuf, sizeof(ebuf), "Invalid URI"); mg_send_http_error(conn, 400, "%s", ebuf); conn->request_info.local_uri_raw = NULL; break; } conn->request_info.local_uri = (char *)conn->request_info.local_uri_raw; } if (ebuf[0] != '\0') { conn->protocol_type = -1; } else { /* HTTP/1 allows protocol upgrade */ conn->protocol_type = should_switch_to_protocol(conn); if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) { /* This will occur, if a HTTP/1.1 request should be upgraded * to HTTP/2 - but not if HTTP/2 is negotiated using ALPN. * Since most (all?) major browsers only support HTTP/2 using * ALPN, this is hard to test and very low priority. * Deactivate it (at least for now). */ conn->protocol_type = PROTOCOL_TYPE_HTTP1; } } DEBUG_TRACE("http: %s, error: %s", (ri->http_version ? ri->http_version : "none"), (ebuf[0] ? ebuf : "none")); if (ebuf[0] == '\0') { if (conn->request_info.local_uri) { /* handle request to local server */ handle_request_stat_log(conn); } else { /* TODO: handle non-local request (PROXY) */ conn->must_close = 1; } } else { conn->must_close = 1; } /* Response complete. Free header buffer */ free_buffered_response_header_list(conn); if (ri->remote_user != NULL) { mg_free((void *)ri->remote_user); /* Important! When having connections with and without auth * would cause double free and then crash */ ri->remote_user = NULL; } /* NOTE(lsm): order is important here. should_keep_alive() call * is using parsed request, which will be invalid after * memmove's below. * Therefore, memorize should_keep_alive() result now for later * use in loop exit condition. */ /* Enable it only if this request is completely discardable. */ keep_alive = STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag) && should_keep_alive(conn) && (conn->content_len >= 0) && (conn->request_len > 0) && ((conn->is_chunked == 4) || (!conn->is_chunked && ((conn->consumed_content == conn->content_len) || ((conn->request_len + conn->content_len) <= conn->data_len)))) && (conn->protocol_type == PROTOCOL_TYPE_HTTP1); if (keep_alive) { /* Discard all buffered data for this request */ discard_len = ((conn->request_len + conn->content_len) < conn->data_len) ? (int)(conn->request_len + conn->content_len) : conn->data_len; conn->data_len -= discard_len; if (conn->data_len > 0) { DEBUG_TRACE("discard_len = %d", discard_len); memmove(conn->buf, conn->buf + discard_len, (size_t)conn->data_len); } } DEBUG_ASSERT(conn->data_len >= 0); DEBUG_ASSERT(conn->data_len <= conn->buf_size); if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) { DEBUG_TRACE("internal error: data_len = %li, buf_size = %li", (long int)conn->data_len, (long int)conn->buf_size); break; } conn->handled_requests++; } while (keep_alive); DEBUG_TRACE("Done processing connection from %s (%f sec)", conn->request_info.remote_addr, difftime(time(NULL), conn->conn_birth_time)); close_connection(conn); #if defined(USE_SERVER_STATS) mg_atomic_add(&(conn->phys_ctx->total_requests), conn->handled_requests); mg_atomic_dec(&(conn->phys_ctx->active_connections)); #endif } #if defined(ALTERNATIVE_QUEUE) static void produce_socket(struct mg_context *ctx, const struct socket *sp) { unsigned int i; while (!ctx->stop_flag) { for (i = 0; i < ctx->cfg_worker_threads; i++) { /* find a free worker slot and signal it */ if (ctx->client_socks[i].in_use == 2) { (void)pthread_mutex_lock(&ctx->thread_mutex); if ((ctx->client_socks[i].in_use == 2) && !ctx->stop_flag) { ctx->client_socks[i] = *sp; ctx->client_socks[i].in_use = 1; /* socket has been moved to the consumer */ (void)pthread_mutex_unlock(&ctx->thread_mutex); (void)event_signal(ctx->client_wait_events[i]); return; } (void)pthread_mutex_unlock(&ctx->thread_mutex); } } /* queue is full */ mg_sleep(1); } /* must consume */ set_blocking_mode(sp->sock); closesocket(sp->sock); } static int consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index) { DEBUG_TRACE("%s", "going idle"); (void)pthread_mutex_lock(&ctx->thread_mutex); ctx->client_socks[thread_index].in_use = 2; (void)pthread_mutex_unlock(&ctx->thread_mutex); event_wait(ctx->client_wait_events[thread_index]); (void)pthread_mutex_lock(&ctx->thread_mutex); *sp = ctx->client_socks[thread_index]; if (ctx->stop_flag) { (void)pthread_mutex_unlock(&ctx->thread_mutex); if (sp->in_use == 1) { /* must consume */ set_blocking_mode(sp->sock); closesocket(sp->sock); } return 0; } (void)pthread_mutex_unlock(&ctx->thread_mutex); if (sp->in_use == 1) { DEBUG_TRACE("grabbed socket %d, going busy", sp->sock); return 1; } /* must not reach here */ DEBUG_ASSERT(0); return 0; } #else /* ALTERNATIVE_QUEUE */ /* Worker threads take accepted socket from the queue */ static int consume_socket(struct mg_context *ctx, struct socket *sp, int thread_index) { (void)thread_index; (void)pthread_mutex_lock(&ctx->thread_mutex); DEBUG_TRACE("%s", "going idle"); /* If the queue is empty, wait. We're idle at this point. */ while ((ctx->sq_head == ctx->sq_tail) && (STOP_FLAG_IS_ZERO(&ctx->stop_flag))) { pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex); } /* If we're stopping, sq_head may be equal to sq_tail. */ if (ctx->sq_head > ctx->sq_tail) { /* Copy socket from the queue and increment tail */ *sp = ctx->squeue[ctx->sq_tail % ctx->sq_size]; ctx->sq_tail++; DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1); /* Wrap pointers if needed */ while (ctx->sq_tail > ctx->sq_size) { ctx->sq_tail -= ctx->sq_size; ctx->sq_head -= ctx->sq_size; } } (void)pthread_cond_signal(&ctx->sq_empty); (void)pthread_mutex_unlock(&ctx->thread_mutex); return STOP_FLAG_IS_ZERO(&ctx->stop_flag); } /* Master thread adds accepted socket to a queue */ static void produce_socket(struct mg_context *ctx, const struct socket *sp) { int queue_filled; (void)pthread_mutex_lock(&ctx->thread_mutex); queue_filled = ctx->sq_head - ctx->sq_tail; /* If the queue is full, wait */ while (STOP_FLAG_IS_ZERO(&ctx->stop_flag) && (queue_filled >= ctx->sq_size)) { ctx->sq_blocked = 1; /* Status information: All threads busy */ #if defined(USE_SERVER_STATS) if (queue_filled > ctx->sq_max_fill) { ctx->sq_max_fill = queue_filled; } #endif (void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex); ctx->sq_blocked = 0; /* Not blocked now */ queue_filled = ctx->sq_head - ctx->sq_tail; } if (queue_filled < ctx->sq_size) { /* Copy socket to the queue and increment head */ ctx->squeue[ctx->sq_head % ctx->sq_size] = *sp; ctx->sq_head++; DEBUG_TRACE("queued socket %d", sp ? sp->sock : -1); } queue_filled = ctx->sq_head - ctx->sq_tail; #if defined(USE_SERVER_STATS) if (queue_filled > ctx->sq_max_fill) { ctx->sq_max_fill = queue_filled; } #endif (void)pthread_cond_signal(&ctx->sq_full); (void)pthread_mutex_unlock(&ctx->thread_mutex); } #endif /* ALTERNATIVE_QUEUE */ static void worker_thread_run(struct mg_connection *conn) { struct mg_context *ctx = conn->phys_ctx; int thread_index; struct mg_workerTLS tls; mg_set_thread_name("worker"); tls.is_master = 0; tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max); #if defined(_WIN32) tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL); #endif /* Initialize thread local storage before calling any callback */ pthread_setspecific(sTlsKey, &tls); /* Check if there is a user callback */ if (ctx->callbacks.init_thread) { /* call init_thread for a worker thread (type 1), and store the * return value */ tls.user_ptr = ctx->callbacks.init_thread(ctx, 1); } else { /* No callback: set user pointer to NULL */ tls.user_ptr = NULL; } /* Connection structure has been pre-allocated */ thread_index = (int)(conn - ctx->worker_connections); if ((thread_index < 0) || ((unsigned)thread_index >= (unsigned)ctx->cfg_worker_threads)) { mg_cry_ctx_internal(ctx, "Internal error: Invalid worker index %i", thread_index); return; } /* Request buffers are not pre-allocated. They are private to the * request and do not contain any state information that might be * of interest to anyone observing a server status. */ conn->buf = (char *)mg_malloc_ctx(ctx->max_request_size, conn->phys_ctx); if (conn->buf == NULL) { mg_cry_ctx_internal( ctx, "Out of memory: Cannot allocate buffer for worker %i", thread_index); return; } conn->buf_size = (int)ctx->max_request_size; conn->dom_ctx = &(ctx->dd); /* Use default domain and default host */ conn->tls_user_ptr = tls.user_ptr; /* store ptr for quick access */ conn->request_info.user_data = ctx->user_data; /* Allocate a mutex for this connection to allow communication both * within the request handler and from elsewhere in the application */ if (0 != pthread_mutex_init(&conn->mutex, &pthread_mutex_attr)) { mg_free(conn->buf); mg_cry_ctx_internal(ctx, "%s", "Cannot create mutex"); return; } #if defined(USE_SERVER_STATS) conn->conn_state = 1; /* not consumed */ #endif /* Call consume_socket() even when ctx->stop_flag > 0, to let it * signal sq_empty condvar to wake up the master waiting in * produce_socket() */ while (consume_socket(ctx, &conn->client, thread_index)) { /* New connections must start with new protocol negotiation */ tls.alpn_proto = NULL; #if defined(USE_SERVER_STATS) conn->conn_close_time = 0; #endif conn->conn_birth_time = time(NULL); /* Fill in IP, port info early so even if SSL setup below fails, * error handler would have the corresponding info. * Thanks to Johannes Winkelmann for the patch. */ conn->request_info.remote_port = ntohs(USA_IN_PORT_UNSAFE(&conn->client.rsa)); conn->request_info.server_port = ntohs(USA_IN_PORT_UNSAFE(&conn->client.lsa)); sockaddr_to_string(conn->request_info.remote_addr, sizeof(conn->request_info.remote_addr), &conn->client.rsa); DEBUG_TRACE("Incoming %sconnection from %s", (conn->client.is_ssl ? "SSL " : ""), conn->request_info.remote_addr); conn->request_info.is_ssl = conn->client.is_ssl; if (conn->client.is_ssl) { #if defined(USE_MBEDTLS) /* HTTPS connection */ if (mbed_ssl_accept(&(conn->ssl), conn->dom_ctx->ssl_ctx, (int *)&(conn->client.sock), conn->phys_ctx) == 0) { /* conn->dom_ctx is set in get_request */ /* process HTTPS connection */ init_connection(conn); conn->connection_type = CONNECTION_TYPE_REQUEST; conn->protocol_type = PROTOCOL_TYPE_HTTP1; process_new_connection(conn); } else { /* make sure the connection is cleaned up on SSL failure */ close_connection(conn); } #elif !defined(NO_SSL) /* HTTPS connection */ if (sslize(conn, SSL_accept, NULL)) { /* conn->dom_ctx is set in get_request */ /* Get SSL client certificate information (if set) */ struct mg_client_cert client_cert; if (ssl_get_client_cert_info(conn, &client_cert)) { conn->request_info.client_cert = &client_cert; } /* process HTTPS connection */ #if defined(USE_HTTP2) if ((tls.alpn_proto != NULL) && (!memcmp(tls.alpn_proto, "\x02h2", 3))) { /* process HTTPS/2 connection */ init_connection(conn); conn->connection_type = CONNECTION_TYPE_REQUEST; conn->protocol_type = PROTOCOL_TYPE_HTTP2; conn->content_len = -1; /* content length is not predefined */ conn->is_chunked = 0; /* HTTP2 is never chunked */ process_new_http2_connection(conn); } else #endif { /* process HTTPS/1.x or WEBSOCKET-SECURE connection */ init_connection(conn); conn->connection_type = CONNECTION_TYPE_REQUEST; /* Start with HTTP, WS will be an "upgrade" request later */ conn->protocol_type = PROTOCOL_TYPE_HTTP1; process_new_connection(conn); } /* Free client certificate info */ if (conn->request_info.client_cert) { mg_free((void *)(conn->request_info.client_cert->subject)); mg_free((void *)(conn->request_info.client_cert->issuer)); mg_free((void *)(conn->request_info.client_cert->serial)); mg_free((void *)(conn->request_info.client_cert->finger)); /* Free certificate memory */ X509_free( (X509 *)conn->request_info.client_cert->peer_cert); conn->request_info.client_cert->peer_cert = 0; conn->request_info.client_cert->subject = 0; conn->request_info.client_cert->issuer = 0; conn->request_info.client_cert->serial = 0; conn->request_info.client_cert->finger = 0; conn->request_info.client_cert = 0; } } else { /* make sure the connection is cleaned up on SSL failure */ close_connection(conn); } #endif } else { /* process HTTP connection */ init_connection(conn); conn->connection_type = CONNECTION_TYPE_REQUEST; /* Start with HTTP, WS will be an "upgrade" request later */ conn->protocol_type = PROTOCOL_TYPE_HTTP1; process_new_connection(conn); } DEBUG_TRACE("%s", "Connection closed"); #if defined(USE_SERVER_STATS) conn->conn_close_time = time(NULL); #endif } /* Call exit thread user callback */ if (ctx->callbacks.exit_thread) { ctx->callbacks.exit_thread(ctx, 1, tls.user_ptr); } /* delete thread local storage objects */ pthread_setspecific(sTlsKey, NULL); #if defined(_WIN32) CloseHandle(tls.pthread_cond_helper_mutex); #endif pthread_mutex_destroy(&conn->mutex); /* Free the request buffer. */ conn->buf_size = 0; mg_free(conn->buf); conn->buf = NULL; /* Free cleaned URI (if any) */ if (conn->request_info.local_uri != conn->request_info.local_uri_raw) { mg_free((void *)conn->request_info.local_uri); conn->request_info.local_uri = NULL; } #if defined(USE_SERVER_STATS) conn->conn_state = 9; /* done */ #endif DEBUG_TRACE("%s", "exiting"); } /* Threads have different return types on Windows and Unix. */ #if defined(_WIN32) static unsigned __stdcall worker_thread(void *thread_func_param) { worker_thread_run((struct mg_connection *)thread_func_param); return 0; } #else static void * worker_thread(void *thread_func_param) { #if !defined(__ZEPHYR__) struct sigaction sa; /* Ignore SIGPIPE */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); #endif worker_thread_run((struct mg_connection *)thread_func_param); return NULL; } #endif /* _WIN32 */ /* This is an internal function, thus all arguments are expected to be * valid - a NULL check is not required. */ static void accept_new_connection(const struct socket *listener, struct mg_context *ctx) { struct socket so; char src_addr[IP_ADDR_STR_LEN]; socklen_t len = sizeof(so.rsa); #if !defined(__ZEPHYR__) int on = 1; #endif memset(&so, 0, sizeof(so)); if ((so.sock = accept(listener->sock, &so.rsa.sa, &len)) == INVALID_SOCKET) { } else if (check_acl(ctx, &so.rsa) != 1) { sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa); mg_cry_ctx_internal(ctx, "%s: %s is not allowed to connect", __func__, src_addr); closesocket(so.sock); } else { /* Put so socket structure into the queue */ DEBUG_TRACE("Accepted socket %d", (int)so.sock); set_close_on_exec(so.sock, NULL, ctx); so.is_ssl = listener->is_ssl; so.ssl_redir = listener->ssl_redir; if (getsockname(so.sock, &so.lsa.sa, &len) != 0) { mg_cry_ctx_internal(ctx, "%s: getsockname() failed: %s", __func__, strerror(ERRNO)); } #if !defined(__ZEPHYR__) if ((so.lsa.sa.sa_family == AF_INET) || (so.lsa.sa.sa_family == AF_INET6)) { /* Set TCP keep-alive for TCP sockets (IPv4 and IPv6). * This is needed because if HTTP-level keep-alive * is enabled, and client resets the connection, server won't get * TCP FIN or RST and will keep the connection open forever. With * TCP keep-alive, next keep-alive handshake will figure out that * the client is down and will close the server end. * Thanks to Igor Klopov who suggested the patch. */ if (setsockopt(so.sock, SOL_SOCKET, SO_KEEPALIVE, (SOCK_OPT_TYPE)&on, sizeof(on)) != 0) { mg_cry_ctx_internal( ctx, "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s", __func__, strerror(ERRNO)); } } #endif /* Disable TCP Nagle's algorithm. Normally TCP packets are coalesced * to effectively fill up the underlying IP packet payload and * reduce the overhead of sending lots of small buffers. However * this hurts the server's throughput (ie. operations per second) * when HTTP 1.1 persistent connections are used and the responses * are relatively small (eg. less than 1400 bytes). */ if ((ctx->dd.config[CONFIG_TCP_NODELAY] != NULL) && (!strcmp(ctx->dd.config[CONFIG_TCP_NODELAY], "1"))) { if (set_tcp_nodelay(&so, 1) != 0) { mg_cry_ctx_internal( ctx, "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s", __func__, strerror(ERRNO)); } } /* The "non blocking" property should already be * inherited from the parent socket. Set it for * non-compliant socket implementations. */ set_non_blocking_mode(so.sock); so.in_use = 0; produce_socket(ctx, &so); } } static void master_thread_run(struct mg_context *ctx) { struct mg_workerTLS tls; struct mg_pollfd *pfd; unsigned int i; unsigned int workerthreadcount; if (!ctx) { return; } mg_set_thread_name("master"); /* Increase priority of the master thread */ #if defined(_WIN32) SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); #elif defined(USE_MASTER_THREAD_PRIORITY) int min_prio = sched_get_priority_min(SCHED_RR); int max_prio = sched_get_priority_max(SCHED_RR); if ((min_prio >= 0) && (max_prio >= 0) && ((USE_MASTER_THREAD_PRIORITY) <= max_prio) && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) { struct sched_param sched_param = {0}; sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY); pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param); } #endif /* Initialize thread local storage */ #if defined(_WIN32) tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL); #endif tls.is_master = 1; pthread_setspecific(sTlsKey, &tls); if (ctx->callbacks.init_thread) { /* Callback for the master thread (type 0) */ tls.user_ptr = ctx->callbacks.init_thread(ctx, 0); } else { tls.user_ptr = NULL; } /* Lua background script "start" event */ #if defined(USE_LUA) if (ctx->lua_background_state) { lua_State *lstate = (lua_State *)ctx->lua_background_state; pthread_mutex_lock(&ctx->lua_bg_mutex); /* call "start()" in Lua */ lua_getglobal(lstate, "start"); if (lua_type(lstate, -1) == LUA_TFUNCTION) { int ret = lua_pcall(lstate, /* args */ 0, /* results */ 0, 0); if (ret != 0) { struct mg_connection fc; lua_cry(fake_connection(&fc, ctx), ret, lstate, "lua_background_script", "start"); } } else { lua_pop(lstate, 1); } /* determine if there is a "log()" function in Lua background script */ lua_getglobal(lstate, "log"); if (lua_type(lstate, -1) == LUA_TFUNCTION) { ctx->lua_bg_log_available = 1; } lua_pop(lstate, 1); pthread_mutex_unlock(&ctx->lua_bg_mutex); } #endif /* Server starts *now* */ ctx->start_time = time(NULL); /* Server accept loop */ pfd = ctx->listening_socket_fds; while (STOP_FLAG_IS_ZERO(&ctx->stop_flag)) { for (i = 0; i < ctx->num_listening_sockets; i++) { pfd[i].fd = ctx->listening_sockets[i].sock; pfd[i].events = POLLIN; } if (mg_poll(pfd, ctx->num_listening_sockets, SOCKET_TIMEOUT_QUANTUM, &(ctx->stop_flag)) > 0) { for (i = 0; i < ctx->num_listening_sockets; i++) { /* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the * successful poll, and POLLIN is defined as * (POLLRDNORM | POLLRDBAND) * Therefore, we're checking pfd[i].revents & POLLIN, not * pfd[i].revents == POLLIN. */ if (STOP_FLAG_IS_ZERO(&ctx->stop_flag) && (pfd[i].revents & POLLIN)) { accept_new_connection(&ctx->listening_sockets[i], ctx); } } } } /* Here stop_flag is 1 - Initiate shutdown. */ DEBUG_TRACE("%s", "stopping workers"); /* Stop signal received: somebody called mg_stop. Quit. */ close_all_listening_sockets(ctx); /* Wakeup workers that are waiting for connections to handle. */ #if defined(ALTERNATIVE_QUEUE) for (i = 0; i < ctx->cfg_worker_threads; i++) { event_signal(ctx->client_wait_events[i]); } #else (void)pthread_mutex_lock(&ctx->thread_mutex); pthread_cond_broadcast(&ctx->sq_full); (void)pthread_mutex_unlock(&ctx->thread_mutex); #endif /* Join all worker threads to avoid leaking threads. */ workerthreadcount = ctx->cfg_worker_threads; for (i = 0; i < workerthreadcount; i++) { if (ctx->worker_threadids[i] != 0) { mg_join_thread(ctx->worker_threadids[i]); } } #if defined(USE_LUA) /* Free Lua state of lua background task */ if (ctx->lua_background_state) { lua_State *lstate = (lua_State *)ctx->lua_background_state; ctx->lua_bg_log_available = 0; /* call "stop()" in Lua */ pthread_mutex_lock(&ctx->lua_bg_mutex); lua_getglobal(lstate, "stop"); if (lua_type(lstate, -1) == LUA_TFUNCTION) { int ret = lua_pcall(lstate, /* args */ 0, /* results */ 0, 0); if (ret != 0) { struct mg_connection fc; lua_cry(fake_connection(&fc, ctx), ret, lstate, "lua_background_script", "stop"); } } DEBUG_TRACE("Close Lua background state %p", lstate); lua_close(lstate); ctx->lua_background_state = 0; pthread_mutex_unlock(&ctx->lua_bg_mutex); } #endif DEBUG_TRACE("%s", "exiting"); /* call exit thread callback */ if (ctx->callbacks.exit_thread) { /* Callback for the master thread (type 0) */ ctx->callbacks.exit_thread(ctx, 0, tls.user_ptr); } #if defined(_WIN32) CloseHandle(tls.pthread_cond_helper_mutex); #endif pthread_setspecific(sTlsKey, NULL); /* Signal mg_stop() that we're done. * WARNING: This must be the very last thing this * thread does, as ctx becomes invalid after this line. */ STOP_FLAG_ASSIGN(&ctx->stop_flag, 2); } /* Threads have different return types on Windows and Unix. */ #if defined(_WIN32) static unsigned __stdcall master_thread(void *thread_func_param) { master_thread_run((struct mg_context *)thread_func_param); return 0; } #else static void * master_thread(void *thread_func_param) { #if !defined(__ZEPHYR__) struct sigaction sa; /* Ignore SIGPIPE */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); #endif master_thread_run((struct mg_context *)thread_func_param); return NULL; } #endif /* _WIN32 */ static void free_context(struct mg_context *ctx) { int i; struct mg_handler_info *tmp_rh; if (ctx == NULL) { return; } /* Call user callback */ if (ctx->callbacks.exit_context) { ctx->callbacks.exit_context(ctx); } /* All threads exited, no sync is needed. Destroy thread mutex and * condvars */ (void)pthread_mutex_destroy(&ctx->thread_mutex); #if defined(ALTERNATIVE_QUEUE) mg_free(ctx->client_socks); if (ctx->client_wait_events != NULL) { for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) { event_destroy(ctx->client_wait_events[i]); } mg_free(ctx->client_wait_events); } #else (void)pthread_cond_destroy(&ctx->sq_empty); (void)pthread_cond_destroy(&ctx->sq_full); mg_free(ctx->squeue); #endif /* Destroy other context global data structures mutex */ (void)pthread_mutex_destroy(&ctx->nonce_mutex); #if defined(USE_LUA) (void)pthread_mutex_destroy(&ctx->lua_bg_mutex); #endif /* Deallocate config parameters */ for (i = 0; i < NUM_OPTIONS; i++) { if (ctx->dd.config[i] != NULL) { #if defined(_MSC_VER) # pragma warning(suppress : 6001) #endif mg_free(ctx->dd.config[i]); } } /* Deallocate request handlers */ while (ctx->dd.handlers) { tmp_rh = ctx->dd.handlers; ctx->dd.handlers = tmp_rh->next; mg_free(tmp_rh->uri); mg_free(tmp_rh); } #if defined(USE_MBEDTLS) if (ctx->dd.ssl_ctx != NULL) { mbed_sslctx_uninit(ctx->dd.ssl_ctx); mg_free(ctx->dd.ssl_ctx); ctx->dd.ssl_ctx = NULL; } #elif !defined(NO_SSL) /* Deallocate SSL context */ if (ctx->dd.ssl_ctx != NULL) { void *ssl_ctx = (void *)ctx->dd.ssl_ctx; int callback_ret = (ctx->callbacks.external_ssl_ctx == NULL) ? 0 : (ctx->callbacks.external_ssl_ctx(&ssl_ctx, ctx->user_data)); if (callback_ret == 0) { SSL_CTX_free(ctx->dd.ssl_ctx); } /* else: ignore error and omit SSL_CTX_free in case * callback_ret is 1 */ } #endif /* !NO_SSL */ /* Deallocate worker thread ID array */ mg_free(ctx->worker_threadids); /* Deallocate worker thread ID array */ mg_free(ctx->worker_connections); /* deallocate system name string */ mg_free(ctx->systemName); /* Deallocate context itself */ mg_free(ctx); } CIVETWEB_API void mg_stop(struct mg_context *ctx) { pthread_t mt; if (!ctx) { return; } /* We don't use a lock here. Calling mg_stop with the same ctx from * two threads is not allowed. */ mt = ctx->masterthreadid; if (mt == 0) { return; } ctx->masterthreadid = 0; /* Set stop flag, so all threads know they have to exit. */ STOP_FLAG_ASSIGN(&ctx->stop_flag, 1); /* Join timer thread */ #if defined(USE_TIMERS) timers_exit(ctx); #endif /* Wait until everything has stopped. */ while (!STOP_FLAG_IS_TWO(&ctx->stop_flag)) { (void)mg_sleep(10); } /* Wait to stop master thread */ mg_join_thread(mt); /* Close remaining Lua states */ #if defined(USE_LUA) lua_ctx_exit(ctx); #endif /* Free memory */ free_context(ctx); } static void get_system_name(char **sysName) { #if defined(_WIN32) char name[128]; DWORD dwVersion = 0; DWORD dwMajorVersion = 0; DWORD dwMinorVersion = 0; DWORD dwBuild = 0; BOOL wowRet, isWoW = FALSE; #if defined(_MSC_VER) # pragma warning(push) /* GetVersion was declared deprecated */ # pragma warning(disable : 4996) #endif dwVersion = GetVersion(); #if defined(_MSC_VER) # pragma warning(pop) #endif dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0); (void)dwBuild; wowRet = IsWow64Process(GetCurrentProcess(), &isWoW); snprintf(name, sizeof(name), "Windows %u.%u%s", (unsigned)dwMajorVersion, (unsigned)dwMinorVersion, (wowRet ? (isWoW ? " (WoW64)" : "") : " (?)")); *sysName = mg_strdup(name); #elif defined(__ZEPHYR__) *sysName = mg_strdup("Zephyr OS"); #else struct utsname name; memset(&name, 0, sizeof(name)); uname(&name); *sysName = mg_strdup(name.sysname); #endif } static void legacy_init(const char **options) { const char *ports_option = config_options[LISTENING_PORTS].default_value; if (options) { const char **run_options = options; const char *optname = config_options[LISTENING_PORTS].name; /* Try to find the "listening_ports" option */ while (*run_options) { if (!strcmp(*run_options, optname)) { ports_option = run_options[1]; } run_options += 2; } } if (is_ssl_port_used(ports_option)) { /* Initialize with SSL support */ mg_init_library(MG_FEATURES_TLS); } else { /* Initialize without SSL support */ mg_init_library(MG_FEATURES_DEFAULT); } } CIVETWEB_API struct mg_context * mg_start2(struct mg_init_data *init, struct mg_error_data *error) { struct mg_context *ctx; const char *name, *value, *default_value; int idx, ok, workerthreadcount; unsigned int i; int itmp; void (*exit_callback)(const struct mg_context *ctx) = 0; const char **options = ((init != NULL) ? (init->configuration_options) : (NULL)); struct mg_workerTLS tls; if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OK; error->code_sub = 0; if (error->text_buffer_size > 0) { *error->text = 0; } } if (mg_init_library_called == 0) { /* Legacy INIT, if mg_start is called without mg_init_library. * Note: This will cause a memory leak when unloading the library. */ legacy_init(options); } if (mg_init_library_called == 0) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", "Library uninitialized"); } return NULL; } /* Allocate context and initialize reasonable general case defaults. */ ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx)); if (ctx == NULL) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY; error->code_sub = (unsigned)sizeof(*ctx); mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", "Out of memory"); } return NULL; } /* Random number generator will initialize at the first call */ ctx->dd.auth_nonce_mask = (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options); /* Save started thread index to reuse in other external API calls * For the sake of thread synchronization all non-civetweb threads * can be considered as single external thread */ ctx->starter_thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max); tls.is_master = -1; /* Thread calling mg_start */ tls.thread_idx = ctx->starter_thread_idx; #if defined(_WIN32) tls.pthread_cond_helper_mutex = NULL; #endif pthread_setspecific(sTlsKey, &tls); ok = (0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr)); #if !defined(ALTERNATIVE_QUEUE) ok &= (0 == pthread_cond_init(&ctx->sq_empty, NULL)); ok &= (0 == pthread_cond_init(&ctx->sq_full, NULL)); ctx->sq_blocked = 0; #endif ok &= (0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr)); #if defined(USE_LUA) ok &= (0 == pthread_mutex_init(&ctx->lua_bg_mutex, &pthread_mutex_attr)); #endif if (!ok) { unsigned error_id = (unsigned)ERRNO; const char *err_msg = "Cannot initialize thread synchronization objects"; /* Fatal error - abort start. However, this situation should never * occur in practice. */ mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OS_ERROR; error->code_sub = error_id; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } mg_free(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } if ((init != NULL) && (init->callbacks != NULL)) { /* Set all callbacks except exit_context. */ ctx->callbacks = *init->callbacks; exit_callback = init->callbacks->exit_context; /* The exit callback is activated once the context is successfully * created. It should not be called, if an incomplete context object * is deleted during a failed initialization. */ ctx->callbacks.exit_context = 0; } ctx->user_data = ((init != NULL) ? (init->user_data) : (NULL)); ctx->dd.handlers = NULL; ctx->dd.next = NULL; #if defined(USE_LUA) lua_ctx_init(ctx); #endif /* Store options */ while (options && (name = *options++) != NULL) { idx = get_option_index(name); if (idx == -1) { mg_cry_ctx_internal(ctx, "Invalid option: %s", name); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_OPTION; error->code_sub = (unsigned)-1; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Invalid configuration option: %s", name); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } else if ((value = *options++) == NULL) { mg_cry_ctx_internal(ctx, "%s: option value cannot be NULL", name); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_OPTION; error->code_sub = (unsigned)idx; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Invalid configuration option value: %s", name); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } if (ctx->dd.config[idx] != NULL) { /* A duplicate configuration option is not an error - the last * option value will be used. */ mg_cry_ctx_internal(ctx, "warning: %s: duplicate option", name); mg_free(ctx->dd.config[idx]); } ctx->dd.config[idx] = mg_strdup_ctx(value, ctx); DEBUG_TRACE("[%s] -> [%s]", name, value); } /* Set default value if needed */ for (i = 0; config_options[i].name != NULL; i++) { default_value = config_options[i].default_value; if ((ctx->dd.config[i] == NULL) && (default_value != NULL)) { ctx->dd.config[i] = mg_strdup_ctx(default_value, ctx); } } /* Request size option */ itmp = atoi(ctx->dd.config[MAX_REQUEST_SIZE]); if (itmp < 1024) { mg_cry_ctx_internal(ctx, "%s too small", config_options[MAX_REQUEST_SIZE].name); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_OPTION; error->code_sub = (unsigned)MAX_REQUEST_SIZE; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Invalid configuration option value: %s", config_options[MAX_REQUEST_SIZE].name); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } ctx->max_request_size = (unsigned)itmp; /* Queue length */ #if !defined(ALTERNATIVE_QUEUE) itmp = atoi(ctx->dd.config[CONNECTION_QUEUE_SIZE]); if (itmp < 1) { mg_cry_ctx_internal(ctx, "%s too small", config_options[CONNECTION_QUEUE_SIZE].name); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_OPTION; error->code_sub = CONNECTION_QUEUE_SIZE; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Invalid configuration option value: %s", config_options[CONNECTION_QUEUE_SIZE].name); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } ctx->squeue = (struct socket *)mg_calloc((unsigned int)itmp, sizeof(struct socket)); if (ctx->squeue == NULL) { mg_cry_ctx_internal(ctx, "Out of memory: Cannot allocate %s", config_options[CONNECTION_QUEUE_SIZE].name); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY; error->code_sub = (unsigned)itmp * (unsigned)sizeof(struct socket); mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Out of memory: Cannot allocate %s", config_options[CONNECTION_QUEUE_SIZE].name); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } ctx->sq_size = itmp; #endif /* Worker thread count option */ workerthreadcount = atoi(ctx->dd.config[NUM_THREADS]); if ((workerthreadcount > MAX_WORKER_THREADS) || (workerthreadcount <= 0)) { if (workerthreadcount <= 0) { mg_cry_ctx_internal(ctx, "%s", "Invalid number of worker threads"); } else { mg_cry_ctx_internal(ctx, "%s", "Too many worker threads"); } if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_OPTION; error->code_sub = NUM_THREADS; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Invalid configuration option value: %s", config_options[NUM_THREADS].name); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } /* Document root */ #if defined(NO_FILES) if (ctx->dd.config[DOCUMENT_ROOT] != NULL) { mg_cry_ctx_internal(ctx, "%s", "Document root must not be set"); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_OPTION; error->code_sub = (unsigned)DOCUMENT_ROOT; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Invalid configuration option value: %s", config_options[DOCUMENT_ROOT].name); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } #endif get_system_name(&ctx->systemName); #if defined(USE_LUA) /* If a Lua background script has been configured, start it. */ ctx->lua_bg_log_available = 0; if (ctx->dd.config[LUA_BACKGROUND_SCRIPT] != NULL) { char ebuf[256]; struct vec opt_vec; struct vec eq_vec; const char *sparams; memset(ebuf, 0, sizeof(ebuf)); pthread_mutex_lock(&ctx->lua_bg_mutex); /* Create a Lua state, load all standard libraries and the mg table */ lua_State *state = mg_lua_context_script_prepare( ctx->dd.config[LUA_BACKGROUND_SCRIPT], ctx, ebuf, sizeof(ebuf)); if (!state) { mg_cry_ctx_internal(ctx, "lua_background_script load error: %s", ebuf); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_SCRIPT_ERROR; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Error in script %s: %s", config_options[LUA_BACKGROUND_SCRIPT].name, ebuf); } pthread_mutex_unlock(&ctx->lua_bg_mutex); free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } /* Add a table with parameters into mg.params */ sparams = ctx->dd.config[LUA_BACKGROUND_SCRIPT_PARAMS]; if (sparams && sparams[0]) { lua_getglobal(state, "mg"); lua_pushstring(state, "params"); lua_newtable(state); while ((sparams = next_option(sparams, &opt_vec, &eq_vec)) != NULL) { reg_llstring( state, opt_vec.ptr, opt_vec.len, eq_vec.ptr, eq_vec.len); if (mg_strncasecmp(sparams, opt_vec.ptr, opt_vec.len) == 0) break; } lua_rawset(state, -3); lua_pop(state, 1); } /* Call script */ state = mg_lua_context_script_run(state, ctx->dd.config[LUA_BACKGROUND_SCRIPT], ctx, ebuf, sizeof(ebuf)); if (!state) { mg_cry_ctx_internal(ctx, "lua_background_script start error: %s", ebuf); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_SCRIPT_ERROR; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Error in script %s: %s", config_options[DOCUMENT_ROOT].name, ebuf); } pthread_mutex_unlock(&ctx->lua_bg_mutex); free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } /* state remains valid */ ctx->lua_background_state = (void *)state; pthread_mutex_unlock(&ctx->lua_bg_mutex); } else { ctx->lua_background_state = 0; } #endif /* Step by step initialization of ctx - depending on build options */ #if !defined(NO_FILESYSTEMS) if (!set_gpass_option(ctx, NULL)) { const char *err_msg = "Invalid global password file"; /* Fatal error - abort start. */ mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_PASS_FILE; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } #endif #if defined(USE_MBEDTLS) if (!mg_sslctx_init(ctx, NULL)) { const char *err_msg = "Error initializing SSL context"; /* Fatal error - abort start. */ mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } #elif !defined(NO_SSL) if (!init_ssl_ctx(ctx, NULL)) { const char *err_msg = "Error initializing SSL context"; /* Fatal error - abort start. */ mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } #endif if (!set_ports_option(ctx)) { const char *err_msg = "Failed to setup server ports"; /* Fatal error - abort start. */ mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_PORTS_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } #if !defined(_WIN32) && !defined(__ZEPHYR__) if (!set_uid_option(ctx)) { const char *err_msg = "Failed to run as configured user"; /* Fatal error - abort start. */ mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_USER_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } #endif if (!set_acl_option(ctx)) { const char *err_msg = "Failed to setup access control list"; /* Fatal error - abort start. */ mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_ACL_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount)); ctx->worker_threadids = (pthread_t *)mg_calloc_ctx(ctx->cfg_worker_threads, sizeof(pthread_t), ctx); if (ctx->worker_threadids == NULL) { const char *err_msg = "Not enough memory for worker thread ID array"; mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY; error->code_sub = (unsigned)ctx->cfg_worker_threads * (unsigned)sizeof(pthread_t); mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } ctx->worker_connections = (struct mg_connection *)mg_calloc_ctx(ctx->cfg_worker_threads, sizeof(struct mg_connection), ctx); if (ctx->worker_connections == NULL) { const char *err_msg = "Not enough memory for worker thread connection array"; mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY; error->code_sub = (unsigned)ctx->cfg_worker_threads * (unsigned)sizeof(struct mg_connection); mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } #if defined(ALTERNATIVE_QUEUE) ctx->client_wait_events = (void **)mg_calloc_ctx(ctx->cfg_worker_threads, sizeof(ctx->client_wait_events[0]), ctx); if (ctx->client_wait_events == NULL) { const char *err_msg = "Not enough memory for worker event array"; mg_cry_ctx_internal(ctx, "%s", err_msg); mg_free(ctx->worker_threadids); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY; error->code_sub = (unsigned)ctx->cfg_worker_threads * (unsigned)sizeof(ctx->client_wait_events[0]); mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } ctx->client_socks = (struct socket *)mg_calloc_ctx(ctx->cfg_worker_threads, sizeof(ctx->client_socks[0]), ctx); if (ctx->client_socks == NULL) { const char *err_msg = "Not enough memory for worker socket array"; mg_cry_ctx_internal(ctx, "%s", err_msg); mg_free(ctx->client_wait_events); mg_free(ctx->worker_threadids); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY; error->code_sub = (unsigned)ctx->cfg_worker_threads * (unsigned)sizeof(ctx->client_socks[0]); mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) { ctx->client_wait_events[i] = event_create(); if (ctx->client_wait_events[i] == 0) { const char *err_msg = "Error creating worker event %i"; mg_cry_ctx_internal(ctx, err_msg, i); while (i > 0) { i--; event_destroy(ctx->client_wait_events[i]); } mg_free(ctx->client_socks); mg_free(ctx->client_wait_events); mg_free(ctx->worker_threadids); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OS_ERROR; error->code_sub = (unsigned)ERRNO; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, err_msg, i); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } } #endif #if defined(USE_TIMERS) if (timers_init(ctx) != 0) { const char *err_msg = "Error creating timers"; mg_cry_ctx_internal(ctx, "%s", err_msg); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OS_ERROR; error->code_sub = (unsigned)ERRNO; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", err_msg); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } #endif /* Context has been created - init user libraries */ if (ctx->callbacks.init_context) { ctx->callbacks.init_context(ctx); } /* From now, the context is successfully created. * When it is destroyed, the exit callback should be called. */ ctx->callbacks.exit_context = exit_callback; ctx->context_type = CONTEXT_SERVER; /* server context */ /* Start worker threads */ for (i = 0; i < ctx->cfg_worker_threads; i++) { /* worker_thread sets up the other fields */ ctx->worker_connections[i].phys_ctx = ctx; if (mg_start_thread_with_id(worker_thread, &ctx->worker_connections[i], &ctx->worker_threadids[i]) != 0) { long error_no = (long)ERRNO; /* thread was not created */ if (i > 0) { /* If the second, third, ... thread cannot be created, set a * warning, but keep running. */ mg_cry_ctx_internal(ctx, "Cannot start worker thread %i: error %ld", i + 1, error_no); /* If the server initialization should stop here, all * threads that have already been created must be stopped * first, before any free_context(ctx) call. */ } else { /* If the first worker thread cannot be created, stop * initialization and free the entire server context. */ mg_cry_ctx_internal(ctx, "Cannot create threads: error %ld", error_no); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OS_ERROR; error->code_sub = (unsigned)error_no; mg_snprintf( NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Cannot create first worker thread: error %ld", error_no); } free_context(ctx); pthread_setspecific(sTlsKey, NULL); return NULL; } break; } } /* Start master (listening) thread */ mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid); pthread_setspecific(sTlsKey, NULL); return ctx; } CIVETWEB_API struct mg_context * mg_start(const struct mg_callbacks *callbacks, void *user_data, const char **options) { struct mg_init_data init = {0}; init.callbacks = callbacks; init.user_data = user_data; init.configuration_options = options; return mg_start2(&init, NULL); } /* Add an additional domain to an already running web server. */ CIVETWEB_API int mg_start_domain2(struct mg_context *ctx, const char **options, struct mg_error_data *error) { const char *name; const char *value; const char *default_value; struct mg_domain_context *new_dom; struct mg_domain_context *dom; int idx, i; if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OK; error->code_sub = 0; if (error->text_buffer_size > 0) { *error->text = 0; } } if ((ctx == NULL) || (options == NULL)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_PARAM; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", "Invalid parameters"); } return -1; } if (!STOP_FLAG_IS_ZERO(&ctx->stop_flag)) { if (error != NULL) { error->code = MG_ERROR_DATA_CODE_SERVER_STOPPED; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", "Server already stopped"); } return -7; } new_dom = (struct mg_domain_context *) mg_calloc_ctx(1, sizeof(struct mg_domain_context), ctx); if (!new_dom) { /* Out of memory */ if (error != NULL) { error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY; error->code_sub = (unsigned)sizeof(struct mg_domain_context); mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", "Out or memory"); } return -6; } /* Store options - TODO: unite duplicate code */ while (options && (name = *options++) != NULL) { idx = get_option_index(name); if (idx == -1) { mg_cry_ctx_internal(ctx, "Invalid option: %s", name); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_OPTION; error->code_sub = (unsigned)-1; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Invalid option: %s", name); } mg_free(new_dom); return -2; } else if ((value = *options++) == NULL) { mg_cry_ctx_internal(ctx, "%s: option value cannot be NULL", name); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INVALID_OPTION; error->code_sub = (unsigned)idx; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Invalid option value: %s", name); } mg_free(new_dom); return -2; } if (new_dom->config[idx] != NULL) { /* Duplicate option: Later values overwrite earlier ones. */ mg_cry_ctx_internal(ctx, "warning: %s: duplicate option", name); mg_free(new_dom->config[idx]); } new_dom->config[idx] = mg_strdup_ctx(value, ctx); DEBUG_TRACE("[%s] -> [%s]", name, value); } /* Authentication domain is mandatory */ /* TODO: Maybe use a new option hostname? */ if (!new_dom->config[AUTHENTICATION_DOMAIN]) { mg_cry_ctx_internal(ctx, "%s", "authentication domain required"); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_MISSING_OPTION; error->code_sub = AUTHENTICATION_DOMAIN; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Mandatory option %s missing", config_options[AUTHENTICATION_DOMAIN].name); } mg_free(new_dom); return -4; } /* Set default value if needed. Take the config value from * ctx as a default value. */ for (i = 0; config_options[i].name != NULL; i++) { default_value = ctx->dd.config[i]; if ((new_dom->config[i] == NULL) && (default_value != NULL)) { new_dom->config[i] = mg_strdup_ctx(default_value, ctx); } } new_dom->handlers = NULL; new_dom->next = NULL; new_dom->nonce_count = 0; new_dom->auth_nonce_mask = get_random() ^ (get_random() << 31); #if defined(USE_LUA) && defined(USE_WEBSOCKET) new_dom->shared_lua_websockets = NULL; #endif #if !defined(NO_SSL) && !defined(USE_MBEDTLS) if (!init_ssl_ctx(ctx, new_dom)) { /* Init SSL failed */ if (error != NULL) { error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "%s", "Initializing SSL context failed"); } mg_free(new_dom); return -3; } #endif /* Add element to linked list. */ mg_lock_context(ctx); idx = 0; dom = &(ctx->dd); for (;;) { if (!mg_strcasecmp(new_dom->config[AUTHENTICATION_DOMAIN], dom->config[AUTHENTICATION_DOMAIN])) { /* Domain collision */ mg_cry_ctx_internal(ctx, "domain %s already in use", new_dom->config[AUTHENTICATION_DOMAIN]); if (error != NULL) { error->code = MG_ERROR_DATA_CODE_DUPLICATE_DOMAIN; mg_snprintf(NULL, NULL, /* No truncation check for error buffers */ error->text, error->text_buffer_size, "Domain %s specified by %s is already in use", new_dom->config[AUTHENTICATION_DOMAIN], config_options[AUTHENTICATION_DOMAIN].name); } mg_free(new_dom); mg_unlock_context(ctx); return -5; } /* Count number of domains */ idx++; if (dom->next == NULL) { dom->next = new_dom; break; } dom = dom->next; } mg_unlock_context(ctx); /* Return domain number */ return idx; } CIVETWEB_API int mg_start_domain(struct mg_context *ctx, const char **options) { return mg_start_domain2(ctx, options, NULL); } /* Feature check API function */ CIVETWEB_API unsigned mg_check_feature(unsigned feature) { static const unsigned feature_set = 0 /* Set bits for available features according to API documentation. * This bit mask is created at compile time, according to the active * preprocessor defines. It is a single const value at runtime. */ #if !defined(NO_FILES) | MG_FEATURES_FILES #endif #if !defined(NO_SSL) || defined(USE_MBEDTLS) | MG_FEATURES_SSL #endif #if !defined(NO_CGI) | MG_FEATURES_CGI #endif #if defined(USE_IPV6) | MG_FEATURES_IPV6 #endif #if defined(USE_WEBSOCKET) | MG_FEATURES_WEBSOCKET #endif #if defined(USE_LUA) | MG_FEATURES_LUA #endif #if defined(USE_DUKTAPE) | MG_FEATURES_SSJS #endif #if !defined(NO_CACHING) | MG_FEATURES_CACHE #endif #if defined(USE_SERVER_STATS) | MG_FEATURES_STATS #endif #if defined(USE_ZLIB) | MG_FEATURES_COMPRESSION #endif #if defined(USE_HTTP2) | MG_FEATURES_HTTP2 #endif #if defined(USE_X_DOM_SOCKET) | MG_FEATURES_X_DOMAIN_SOCKET #endif /* Set some extra bits not defined in the API documentation. * These bits may change without further notice. */ #if defined(MG_LEGACY_INTERFACE) | 0x80000000u #endif #if defined(MG_EXPERIMENTAL_INTERFACES) | 0x40000000u #endif #if !defined(NO_RESPONSE_BUFFERING) | 0x20000000u #endif #if defined(MEMORY_DEBUGGING) | 0x10000000u #endif ; return (feature & feature_set); } static size_t mg_str_append(char **dst, char *end, const char *src) { size_t len = strlen(src); if (*dst != end) { /* Append src if enough space, or close dst. */ if ((size_t)(end - *dst) > len) { strcpy(*dst, src); *dst += len; } else { *dst = end; } } return len; } /* Get system information. It can be printed or stored by the caller. * Return the size of available information. */ CIVETWEB_API int mg_get_system_info(char *buffer, int buflen) { char *end, *append_eoobj = NULL, block[256]; size_t system_info_length = 0; #if defined(_WIN32) static const char eol[] = "\r\n", eoobj[] = "\r\n}\r\n"; #else static const char eol[] = "\n", eoobj[] = "\n}\n"; #endif if ((buffer == NULL) || (buflen < 1)) { buflen = 0; end = buffer; } else { *buffer = 0; end = buffer + buflen; } if (buflen > (int)(sizeof(eoobj) - 1)) { /* has enough space to append eoobj */ append_eoobj = buffer; if (end) { end -= sizeof(eoobj) - 1; } } system_info_length += mg_str_append(&buffer, end, "{"); /* Server version */ { const char *version = mg_version(); mg_snprintf(NULL, NULL, block, sizeof(block), "%s\"version\" : \"%s\"", eol, version); system_info_length += mg_str_append(&buffer, end, block); } /* System info */ { #if defined(_WIN32) DWORD dwVersion = 0; DWORD dwMajorVersion = 0; DWORD dwMinorVersion = 0; SYSTEM_INFO si; GetSystemInfo(&si); #if defined(_MSC_VER) # pragma warning(push) /* GetVersion was declared deprecated */ # pragma warning(disable : 4996) #endif dwVersion = GetVersion(); #if defined(_MSC_VER) # pragma warning(pop) #endif dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"os\" : \"Windows %u.%u\"", eol, (unsigned)dwMajorVersion, (unsigned)dwMinorVersion); system_info_length += mg_str_append(&buffer, end, block); mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"cpu\" : \"type %u, cores %u, mask %x\"", eol, (unsigned)si.wProcessorArchitecture, (unsigned)si.dwNumberOfProcessors, (unsigned)si.dwActiveProcessorMask); system_info_length += mg_str_append(&buffer, end, block); #elif defined(__ZEPHYR__) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"os\" : \"%s %s\"", eol, "Zephyr OS", ZEPHYR_VERSION); system_info_length += mg_str_append(&buffer, end, block); #else struct utsname name; memset(&name, 0, sizeof(name)); uname(&name); mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"os\" : \"%s %s (%s) - %s\"", eol, name.sysname, name.version, name.release, name.machine); system_info_length += mg_str_append(&buffer, end, block); #endif } /* Features */ { mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"features\" : %lu" ",%s\"feature_list\" : \"Server:%s%s%s%s%s%s%s%s%s\"", eol, (unsigned long)mg_check_feature(0xFFFFFFFFu), eol, mg_check_feature(MG_FEATURES_FILES) ? " Files" : "", mg_check_feature(MG_FEATURES_SSL) ? " HTTPS" : "", mg_check_feature(MG_FEATURES_CGI) ? " CGI" : "", mg_check_feature(MG_FEATURES_IPV6) ? " IPv6" : "", mg_check_feature(MG_FEATURES_WEBSOCKET) ? " WebSockets" : "", mg_check_feature(MG_FEATURES_LUA) ? " Lua" : "", mg_check_feature(MG_FEATURES_SSJS) ? " JavaScript" : "", mg_check_feature(MG_FEATURES_CACHE) ? " Cache" : "", mg_check_feature(MG_FEATURES_STATS) ? " Stats" : ""); system_info_length += mg_str_append(&buffer, end, block); #if defined(USE_LUA) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"lua_version\" : \"%u (%s)\"", eol, (unsigned)LUA_VERSION_NUM, LUA_RELEASE); system_info_length += mg_str_append(&buffer, end, block); #endif #if defined(USE_DUKTAPE) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"javascript\" : \"Duktape %u.%u.%u\"", eol, (unsigned)DUK_VERSION / 10000, ((unsigned)DUK_VERSION / 100) % 100, (unsigned)DUK_VERSION % 100); system_info_length += mg_str_append(&buffer, end, block); #endif } /* Build identifier. If BUILD_DATE is not set, __DATE__ will be used. */ { #if defined(BUILD_DATE) const char *bd = BUILD_DATE; #else #if defined(GCC_DIAGNOSTIC) #if GCC_VERSION >= 40900 # pragma GCC diagnostic push /* Disable idiotic compiler warning -Wdate-time, appeared in gcc5. This * does not work in some versions. If "BUILD_DATE" is defined to some * string, it is used instead of __DATE__. */ # pragma GCC diagnostic ignored "-Wdate-time" #endif #endif const char *bd = __DATE__; #if defined(GCC_DIAGNOSTIC) #if GCC_VERSION >= 40900 # pragma GCC diagnostic pop #endif #endif #endif mg_snprintf( NULL, NULL, block, sizeof(block), ",%s\"build\" : \"%s\"", eol, bd); system_info_length += mg_str_append(&buffer, end, block); } /* Compiler information */ /* http://sourceforge.net/p/predef/wiki/Compilers/ */ { #if defined(_MSC_VER) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"MSC: %u (%u)\"", eol, (unsigned)_MSC_VER, (unsigned)_MSC_FULL_VER); system_info_length += mg_str_append(&buffer, end, block); #elif defined(__MINGW64__) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"MinGW64: %u.%u\"", eol, (unsigned)__MINGW64_VERSION_MAJOR, (unsigned)__MINGW64_VERSION_MINOR); system_info_length += mg_str_append(&buffer, end, block); mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"MinGW32: %u.%u\"", eol, (unsigned)__MINGW32_MAJOR_VERSION, (unsigned)__MINGW32_MINOR_VERSION); system_info_length += mg_str_append(&buffer, end, block); #elif defined(__MINGW32__) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"MinGW32: %u.%u\"", eol, (unsigned)__MINGW32_MAJOR_VERSION, (unsigned)__MINGW32_MINOR_VERSION); system_info_length += mg_str_append(&buffer, end, block); #elif defined(__clang__) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"clang: %u.%u.%u (%s)\"", eol, __clang_major__, __clang_minor__, __clang_patchlevel__, __clang_version__); system_info_length += mg_str_append(&buffer, end, block); #elif defined(__GNUC__) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"gcc: %u.%u.%u\"", eol, (unsigned)__GNUC__, (unsigned)__GNUC_MINOR__, (unsigned)__GNUC_PATCHLEVEL__); system_info_length += mg_str_append(&buffer, end, block); #elif defined(__INTEL_COMPILER) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"Intel C/C++: %u\"", eol, (unsigned)__INTEL_COMPILER); system_info_length += mg_str_append(&buffer, end, block); #elif defined(__BORLANDC__) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"Borland C: 0x%x\"", eol, (unsigned)__BORLANDC__); system_info_length += mg_str_append(&buffer, end, block); #elif defined(__SUNPRO_C) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"Solaris: 0x%x\"", eol, (unsigned)__SUNPRO_C); system_info_length += mg_str_append(&buffer, end, block); #else mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"compiler\" : \"other\"", eol); system_info_length += mg_str_append(&buffer, end, block); #endif } /* Determine 32/64 bit data mode. * see https://en.wikipedia.org/wiki/64-bit_computing */ { mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"data_model\" : \"int:%u/%u/%u/%u, float:%u/%u/%u, " "char:%u/%u, " "ptr:%u, size:%u, time:%u\"", eol, (unsigned)sizeof(short), (unsigned)sizeof(int), (unsigned)sizeof(long), (unsigned)sizeof(long long), (unsigned)sizeof(float), (unsigned)sizeof(double), (unsigned)sizeof(long double), (unsigned)sizeof(char), (unsigned)sizeof(wchar_t), (unsigned)sizeof(void *), (unsigned)sizeof(size_t), (unsigned)sizeof(time_t)); system_info_length += mg_str_append(&buffer, end, block); } /* Terminate string */ if (append_eoobj) { strcat(append_eoobj, eoobj); } system_info_length += sizeof(eoobj) - 1; return (int)system_info_length; } /* Get context information. It can be printed or stored by the caller. * Return the size of available information. */ CIVETWEB_API int mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen) { #if defined(USE_SERVER_STATS) char *end, *append_eoobj = NULL, block[256]; size_t context_info_length = 0; #if defined(_WIN32) static const char eol[] = "\r\n", eoobj[] = "\r\n}\r\n"; #else static const char eol[] = "\n", eoobj[] = "\n}\n"; #endif struct mg_memory_stat *ms = get_memory_stat((struct mg_context *)ctx); if ((buffer == NULL) || (buflen < 1)) { buflen = 0; end = buffer; } else { *buffer = 0; end = buffer + buflen; } if (buflen > (int)(sizeof(eoobj) - 1)) { /* has enough space to append eoobj */ append_eoobj = buffer; end -= sizeof(eoobj) - 1; } context_info_length += mg_str_append(&buffer, end, "{"); if (ms) { /* <-- should be always true */ /* Memory information */ int blockCount = (int)ms->blockCount; int64_t totalMemUsed = ms->totalMemUsed; int64_t maxMemUsed = ms->maxMemUsed; if (totalMemUsed > maxMemUsed) { maxMemUsed = totalMemUsed; } mg_snprintf(NULL, NULL, block, sizeof(block), "%s\"memory\" : {%s" "\"blocks\" : %i,%s" "\"used\" : %" INT64_FMT ",%s" "\"maxUsed\" : %" INT64_FMT "%s" "}", eol, eol, blockCount, eol, totalMemUsed, eol, maxMemUsed, eol); context_info_length += mg_str_append(&buffer, end, block); } if (ctx) { /* Declare all variables at begin of the block, to comply * with old C standards. */ char start_time_str[64] = {0}; char now_str[64] = {0}; time_t start_time = ctx->start_time; time_t now = time(NULL); int64_t total_data_read, total_data_written; int active_connections = (int)ctx->active_connections; int max_active_connections = (int)ctx->max_active_connections; int total_connections = (int)ctx->total_connections; if (active_connections > max_active_connections) { max_active_connections = active_connections; } if (active_connections > total_connections) { total_connections = active_connections; } /* Connections information */ mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"connections\" : {%s" "\"active\" : %i,%s" "\"maxActive\" : %i,%s" "\"total\" : %i%s" "}", eol, eol, active_connections, eol, max_active_connections, eol, total_connections, eol); context_info_length += mg_str_append(&buffer, end, block); /* Queue information */ #if !defined(ALTERNATIVE_QUEUE) mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"queue\" : {%s" "\"length\" : %i,%s" "\"filled\" : %i,%s" "\"maxFilled\" : %i,%s" "\"full\" : %s%s" "}", eol, eol, ctx->sq_size, eol, ctx->sq_head - ctx->sq_tail, eol, ctx->sq_max_fill, eol, (ctx->sq_blocked ? "true" : "false"), eol); context_info_length += mg_str_append(&buffer, end, block); #endif /* Requests information */ mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"requests\" : {%s" "\"total\" : %lu%s" "}", eol, eol, (unsigned long)ctx->total_requests, eol); context_info_length += mg_str_append(&buffer, end, block); /* Data information */ total_data_read = mg_atomic_add64((volatile int64_t *)&ctx->total_data_read, 0); total_data_written = mg_atomic_add64((volatile int64_t *)&ctx->total_data_written, 0); mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"data\" : {%s" "\"read\" : %" INT64_FMT ",%s" "\"written\" : %" INT64_FMT "%s" "}", eol, eol, total_data_read, eol, total_data_written, eol); context_info_length += mg_str_append(&buffer, end, block); /* Execution time information */ gmt_time_string(start_time_str, sizeof(start_time_str) - 1, &start_time); gmt_time_string(now_str, sizeof(now_str) - 1, &now); mg_snprintf(NULL, NULL, block, sizeof(block), ",%s\"time\" : {%s" "\"uptime\" : %.0f,%s" "\"start\" : \"%s\",%s" "\"now\" : \"%s\"%s" "}", eol, eol, difftime(now, start_time), eol, start_time_str, eol, now_str, eol); context_info_length += mg_str_append(&buffer, end, block); } /* Terminate string */ if (append_eoobj) { strcat(append_eoobj, eoobj); } context_info_length += sizeof(eoobj) - 1; return (int)context_info_length; #else (void)ctx; if ((buffer != NULL) && (buflen > 0)) { *buffer = 0; } return 0; #endif } CIVETWEB_API void mg_disable_connection_keep_alive(struct mg_connection *conn) { /* https://github.com/civetweb/civetweb/issues/727 */ if (conn != NULL) { conn->must_close = 1; } } #if defined(MG_EXPERIMENTAL_INTERFACES) /* Get connection information. It can be printed or stored by the caller. * Return the size of available information. */ CIVETWEB_API int mg_get_connection_info(const struct mg_context *ctx, int idx, char *buffer, int buflen) { const struct mg_connection *conn; const struct mg_request_info *ri; char *end, *append_eoobj = NULL, block[256]; size_t connection_info_length = 0; int state = 0; const char *state_str = "unknown"; #if defined(_WIN32) static const char eol[] = "\r\n", eoobj[] = "\r\n}\r\n"; #else static const char eol[] = "\n", eoobj[] = "\n}\n"; #endif if ((buffer == NULL) || (buflen < 1)) { buflen = 0; end = buffer; } else { *buffer = 0; end = buffer + buflen; } if (buflen > (int)(sizeof(eoobj) - 1)) { /* has enough space to append eoobj */ append_eoobj = buffer; end -= sizeof(eoobj) - 1; } if ((ctx == NULL) || (idx < 0)) { /* Parameter error */ return 0; } if ((unsigned)idx >= ctx->cfg_worker_threads) { /* Out of range */ return 0; } /* Take connection [idx]. This connection is not locked in * any way, so some other thread might use it. */ conn = (ctx->worker_connections) + idx; /* Initialize output string */ connection_info_length += mg_str_append(&buffer, end, "{"); /* Init variables */ ri = &(conn->request_info); #if defined(USE_SERVER_STATS) state = conn->conn_state; /* State as string */ switch (state) { case 0: state_str = "undefined"; break; case 1: state_str = "not used"; break; case 2: state_str = "init"; break; case 3: state_str = "ready"; break; case 4: state_str = "processing"; break; case 5: state_str = "processed"; break; case 6: state_str = "to close"; break; case 7: state_str = "closing"; break; case 8: state_str = "closed"; break; case 9: state_str = "done"; break; } #endif /* Connection info */ if ((state >= 3) && (state < 9)) { mg_snprintf(NULL, NULL, block, sizeof(block), "%s\"connection\" : {%s" "\"remote\" : {%s" "\"protocol\" : \"%s\",%s" "\"addr\" : \"%s\",%s" "\"port\" : %u%s" "},%s" "\"handled_requests\" : %u%s" "}", eol, eol, eol, get_proto_name(conn), eol, ri->remote_addr, eol, ri->remote_port, eol, eol, conn->handled_requests, eol); connection_info_length += mg_str_append(&buffer, end, block); } /* Request info */ if ((state >= 4) && (state < 6)) { mg_snprintf(NULL, NULL, block, sizeof(block), "%s%s\"request_info\" : {%s" "\"method\" : \"%s\",%s" "\"uri\" : \"%s\",%s" "\"query\" : %s%s%s%s" "}", (connection_info_length > 1 ? "," : ""), eol, eol, ri->request_method, eol, ri->request_uri, eol, ri->query_string ? "\"" : "", ri->query_string ? ri->query_string : "null", ri->query_string ? "\"" : "", eol); connection_info_length += mg_str_append(&buffer, end, block); } /* Execution time information */ if ((state >= 2) && (state < 9)) { char start_time_str[64] = {0}; char close_time_str[64] = {0}; time_t start_time = conn->conn_birth_time; time_t close_time = 0; double time_diff; gmt_time_string(start_time_str, sizeof(start_time_str) - 1, &start_time); #if defined(USE_SERVER_STATS) close_time = conn->conn_close_time; #endif if (close_time != 0) { time_diff = difftime(close_time, start_time); gmt_time_string(close_time_str, sizeof(close_time_str) - 1, &close_time); } else { time_t now = time(NULL); time_diff = difftime(now, start_time); close_time_str[0] = 0; /* or use "now" ? */ } mg_snprintf(NULL, NULL, block, sizeof(block), "%s%s\"time\" : {%s" "\"uptime\" : %.0f,%s" "\"start\" : \"%s\",%s" "\"closed\" : \"%s\"%s" "}", (connection_info_length > 1 ? "," : ""), eol, eol, time_diff, eol, start_time_str, eol, close_time_str, eol); connection_info_length += mg_str_append(&buffer, end, block); } /* Remote user name */ if ((ri->remote_user) && (state < 9)) { mg_snprintf(NULL, NULL, block, sizeof(block), "%s%s\"user\" : {%s" "\"name\" : \"%s\",%s" "}", (connection_info_length > 1 ? "," : ""), eol, eol, ri->remote_user, eol); connection_info_length += mg_str_append(&buffer, end, block); } /* Data block */ if (state >= 3) { mg_snprintf(NULL, NULL, block, sizeof(block), "%s%s\"data\" : {%s" "\"read\" : %" INT64_FMT ",%s" "\"written\" : %" INT64_FMT "%s" "}", (connection_info_length > 1 ? "," : ""), eol, eol, conn->consumed_content, eol, conn->num_bytes_sent, eol); connection_info_length += mg_str_append(&buffer, end, block); } /* State */ mg_snprintf(NULL, NULL, block, sizeof(block), "%s%s\"state\" : \"%s\"", (connection_info_length > 1 ? "," : ""), eol, state_str); connection_info_length += mg_str_append(&buffer, end, block); /* Terminate string */ if (append_eoobj) { strcat(append_eoobj, eoobj); } connection_info_length += sizeof(eoobj) - 1; return (int)connection_info_length; } #if 0 /* Get handler information. It can be printed or stored by the caller. * Return the size of available information. */ CIVETWEB_API int mg_get_handler_info(struct mg_context *ctx, char *buffer, int buflen) { int handler_info_len = 0; struct mg_handler_info *tmp_rh; mg_lock_context(ctx); for (tmp_rh = ctx->dd.handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) { if (buflen > handler_info_len+ tmp_rh->uri_len) { memcpy(buffer+handler_info_len, tmp_rh->uri, tmp_rh->uri_len); } handler_info_len += tmp_rh->uri_len; switch (tmp_rh->handler_type) { case REQUEST_HANDLER: (void)tmp_rh->handler; break; case WEBSOCKET_HANDLER: (void)tmp_rh->connect_handler; (void) tmp_rh->ready_handler; (void) tmp_rh->data_handler; (void) tmp_rh->close_handler; break; case AUTH_HANDLER: (void) tmp_rh->auth_handler; break; } (void)cbdata; } mg_unlock_context(ctx); return handler_info_len; } #endif #endif /* Initialize this library. This function does not need to be thread safe. */ CIVETWEB_API unsigned mg_init_library(unsigned features) { unsigned features_to_init = mg_check_feature(features & 0xFFu); unsigned features_inited = features_to_init; if (mg_init_library_called <= 0) { /* Not initialized yet */ if (0 != pthread_mutex_init(&global_lock_mutex, NULL)) { return 0; } } mg_global_lock(); if (mg_init_library_called <= 0) { int i; size_t len; #if defined(_WIN32) int file_mutex_init = 1; int wsa = 1; #else int mutexattr_init = 1; #endif int failed = 1; int key_create = pthread_key_create(&sTlsKey, tls_dtor); if (key_create == 0) { #if defined(_WIN32) file_mutex_init = pthread_mutex_init(&global_log_file_lock, &pthread_mutex_attr); if (file_mutex_init == 0) { /* Start WinSock */ WSADATA data; failed = wsa = WSAStartup(MAKEWORD(2, 2), &data); } #else mutexattr_init = pthread_mutexattr_init(&pthread_mutex_attr); if (mutexattr_init == 0) { failed = pthread_mutexattr_settype(&pthread_mutex_attr, PTHREAD_MUTEX_RECURSIVE); } #endif } if (failed) { #if defined(_WIN32) if (wsa == 0) { (void)WSACleanup(); } if (file_mutex_init == 0) { (void)pthread_mutex_destroy(&global_log_file_lock); } #else if (mutexattr_init == 0) { (void)pthread_mutexattr_destroy(&pthread_mutex_attr); } #endif if (key_create == 0) { (void)pthread_key_delete(sTlsKey); } mg_global_unlock(); (void)pthread_mutex_destroy(&global_lock_mutex); return 0; } len = 1; for (i = 0; http_methods[i].name != NULL; i++) { size_t sl = strlen(http_methods[i].name); len += sl; if (i > 0) { len += 2; } } all_methods = (char *)mg_malloc(len); if (!all_methods) { /* Must never happen */ mg_global_unlock(); (void)pthread_mutex_destroy(&global_lock_mutex); return 0; } all_methods[0] = 0; for (i = 0; http_methods[i].name != NULL; i++) { if (i > 0) { strcat(all_methods, ", "); strcat(all_methods, http_methods[i].name); } else { strcpy(all_methods, http_methods[i].name); } } } #if defined(USE_LUA) lua_init_optional_libraries(); #endif #if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \ || defined(OPENSSL_API_3_0)) \ && !defined(NO_SSL) if (features_to_init & MG_FEATURES_SSL) { if (!mg_openssl_initialized) { char ebuf[128]; if (initialize_openssl(ebuf, sizeof(ebuf))) { mg_openssl_initialized = 1; } else { (void)ebuf; DEBUG_TRACE("Initializing SSL failed: %s", ebuf); features_inited &= ~((unsigned)(MG_FEATURES_SSL)); } } else { /* ssl already initialized */ } } #endif if (mg_init_library_called <= 0) { mg_init_library_called = 1; } else { mg_init_library_called++; } mg_global_unlock(); return features_inited; } /* Un-initialize this library. */ CIVETWEB_API unsigned mg_exit_library(void) { if (mg_init_library_called <= 0) { return 0; } mg_global_lock(); mg_init_library_called--; if (mg_init_library_called == 0) { #if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1)) && !defined(NO_SSL) if (mg_openssl_initialized) { uninitialize_openssl(); mg_openssl_initialized = 0; } #endif #if defined(_WIN32) (void)WSACleanup(); (void)pthread_mutex_destroy(&global_log_file_lock); #else (void)pthread_mutexattr_destroy(&pthread_mutex_attr); #endif (void)pthread_key_delete(sTlsKey); #if defined(USE_LUA) lua_exit_optional_libraries(); #endif mg_free(all_methods); all_methods = NULL; mg_global_unlock(); (void)pthread_mutex_destroy(&global_lock_mutex); return 1; } mg_global_unlock(); return 1; } /* End of civetweb.c */ webfakes/src/cleancall.h0000644000176200001440000000254514323222672014730 0ustar liggesusers#ifndef CLEANCALL_H #define CLEANCALL_H #include #include // -------------------------------------------------------------------- // Internals // -------------------------------------------------------------------- typedef union {void* p; DL_FUNC fn;} fn_ptr; #if (defined(R_VERSION) && R_VERSION < R_Version(3, 4, 0)) SEXP R_MakeExternalPtrFn(DL_FUNC p, SEXP tag, SEXP prot); DL_FUNC R_ExternalPtrAddrFn(SEXP s); #endif // -------------------------------------------------------------------- // API for packages that embed cleancall // -------------------------------------------------------------------- // The R API does not have a setter for external function pointers SEXP cleancall_MakeExternalPtrFn(DL_FUNC p, SEXP tag, SEXP prot); void cleancall_SetExternalPtrAddrFn(SEXP s, DL_FUNC p); #define CLEANCALL_METHOD_RECORD \ {"cleancall_call", (DL_FUNC) &cleancall_call, 2} SEXP cleancall_call(SEXP args, SEXP env); extern SEXP cleancall_fns_dot_call; void cleancall_init(void); // -------------------------------------------------------------------- // Public API // -------------------------------------------------------------------- SEXP r_with_cleanup_context(SEXP (*fn)(void* data), void* data); void r_call_on_exit(void (*fn)(void* data), void* data); void r_call_on_early_exit(void (*fn)(void* data), void* data); #endif webfakes/src/md5.h0000644000176200001440000003634614740430263013505 0ustar liggesusers/* * This an amalgamation of md5.c and md5.h into a single file * with all static declaration to reduce linker conflicts * in Civetweb. * * The MD5_STATIC declaration was added to facilitate static * inclusion. * No Face Press, LLC */ /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being copyrighted. The original and principal author of md5.h is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 2002-04-13 lpd Removed support for non-ANSI compilers; removed references to Ghostscript; clarified derivation from RFC 1321; now handles byte order either statically or dynamically. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); added conditionalization for C++ compilation from Martin Purschke . 1999-05-03 lpd Original version. */ #if !defined(md5_INCLUDED) #define md5_INCLUDED /* * This package supports both compile-time and run-time determination of CPU * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is * defined as non-zero, the code will be compiled to run only on big-endian * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to * run on either big- or little-endian CPUs, but will run slightly less * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. */ typedef unsigned char md5_byte_t; /* 8-bit byte */ typedef unsigned int md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ typedef struct md5_state_s { md5_word_t count[2]; /* message length in bits, lsw first */ md5_word_t abcd[4]; /* digest buffer */ md5_byte_t buf[64]; /* accumulate block */ } md5_state_t; #if defined(__cplusplus) extern "C" { #endif /* Initialize the algorithm. */ MD5_STATIC void md5_init(md5_state_t *pms); /* Append a string to the message. */ MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes); /* Finish the message and return the digest. */ MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); #if defined(__cplusplus) } /* end extern "C" */ #endif #endif /* md5_INCLUDED */ /* Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com */ /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ /* Independent implementation of MD5 (RFC 1321). This code implements the MD5 Algorithm defined in RFC 1321, whose text is available at http://www.ietf.org/rfc/rfc1321.txt The code is derived from the text of the RFC, including the test suite (section A.5) but excluding the rest of Appendix A. It does not include any code or documentation that is identified in the RFC as being copyrighted. The original and principal author of md5.c is L. Peter Deutsch . Other authors are noted in the change history that follows (in reverse chronological order): 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order either statically or dynamically; added missing #include in library. 2002-03-11 lpd Corrected argument list for main(), and added int return type, in test program and T value program. 2002-02-21 lpd Added missing #include in test program. 2000-07-03 lpd Patched to eliminate warnings about "constant is unsigned in ANSI C, signed in traditional"; made test program self-checking. 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 1999-05-03 lpd Original version. */ #if !defined(MD5_STATIC) #include #include #endif #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ #if defined(ARCH_IS_BIG_ENDIAN) #define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) #else #define BYTE_ORDER (0) #endif #define T_MASK ((md5_word_t)~0) #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) #define T3 (0x242070db) #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) #define T6 (0x4787c62a) #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) #define T9 (0x698098d8) #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) #define T13 (0x6b901122) #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) #define T16 (0x49b40821) #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) #define T19 (0x265e5a51) #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) #define T22 (0x02441453) #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) #define T25 (0x21e1cde6) #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) #define T28 (0x455a14ed) #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) #define T31 (0x676f02d9) #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) #define T35 (0x6d9d6122) #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) #define T38 (0x4bdecfa9) #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) #define T41 (0x289b7ec6) #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) #define T44 (0x04881d05) #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) #define T47 (0x1fa27cf8) #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) #define T50 (0x432aff97) #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) #define T53 (0x655b59c3) #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) #define T57 (0x6fa87e4f) #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) #define T60 (0x4e0811a1) #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) #define T63 (0x2ad7d2bb) #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) { md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; md5_word_t t; #if BYTE_ORDER > 0 /* Define storage only for big-endian CPUs. */ md5_word_t X[16]; #else /* Define storage for little-endian or both types of CPUs. */ md5_word_t xbuf[16]; const md5_word_t *X; #endif { #if BYTE_ORDER == 0 /* * Determine dynamically whether this is a big-endian or * little-endian machine, since we can use a more efficient * algorithm on the latter. */ static const int w = 1; if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ #endif #if BYTE_ORDER <= 0 /* little-endian */ { /* * On little-endian machines, we can process properly aligned * data without copying it. */ if (!(((uintptr_t)data) & 3)) { /* data are properly aligned, a direct assignment is possible */ /* cast through a (void *) should avoid a compiler warning, see https://github.com/bel2125/civetweb/issues/94#issuecomment-98112861 */ X = (const md5_word_t *)(const void *)data; } else { /* not aligned */ memcpy(xbuf, data, 64); X = xbuf; } } #endif #if BYTE_ORDER == 0 else /* dynamic big-endian */ #endif #if BYTE_ORDER >= 0 /* big-endian */ { /* * On big-endian machines, we must arrange the bytes in the * right order. */ const md5_byte_t *xp = data; int i; #if BYTE_ORDER == 0 X = xbuf; /* (dynamic only) */ #else #define xbuf X /* (static only) */ #endif for (i = 0; i < 16; ++i, xp += 4) xbuf[i] = (md5_word_t)(xp[0]) + (md5_word_t)(xp[1] << 8) + (md5_word_t)(xp[2] << 16) + (md5_word_t)(xp[3] << 24); } #endif } #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* Round 1. */ /* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) #define SET(a, b, c, d, k, s, Ti) \ t = (a) + F(b, c, d) + X[k] + (Ti); \ (a) = ROTATE_LEFT(t, s) + (b) /* Do the following 16 operations. */ SET(a, b, c, d, 0, 7, T1); SET(d, a, b, c, 1, 12, T2); SET(c, d, a, b, 2, 17, T3); SET(b, c, d, a, 3, 22, T4); SET(a, b, c, d, 4, 7, T5); SET(d, a, b, c, 5, 12, T6); SET(c, d, a, b, 6, 17, T7); SET(b, c, d, a, 7, 22, T8); SET(a, b, c, d, 8, 7, T9); SET(d, a, b, c, 9, 12, T10); SET(c, d, a, b, 10, 17, T11); SET(b, c, d, a, 11, 22, T12); SET(a, b, c, d, 12, 7, T13); SET(d, a, b, c, 13, 12, T14); SET(c, d, a, b, 14, 17, T15); SET(b, c, d, a, 15, 22, T16); #undef SET /* Round 2. */ /* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define SET(a, b, c, d, k, s, Ti) \ t = (a) + G(b, c, d) + X[k] + (Ti); \ (a) = ROTATE_LEFT(t, s) + (b) /* Do the following 16 operations. */ SET(a, b, c, d, 1, 5, T17); SET(d, a, b, c, 6, 9, T18); SET(c, d, a, b, 11, 14, T19); SET(b, c, d, a, 0, 20, T20); SET(a, b, c, d, 5, 5, T21); SET(d, a, b, c, 10, 9, T22); SET(c, d, a, b, 15, 14, T23); SET(b, c, d, a, 4, 20, T24); SET(a, b, c, d, 9, 5, T25); SET(d, a, b, c, 14, 9, T26); SET(c, d, a, b, 3, 14, T27); SET(b, c, d, a, 8, 20, T28); SET(a, b, c, d, 13, 5, T29); SET(d, a, b, c, 2, 9, T30); SET(c, d, a, b, 7, 14, T31); SET(b, c, d, a, 12, 20, T32); #undef SET /* Round 3. */ /* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ #define H(x, y, z) ((x) ^ (y) ^ (z)) #define SET(a, b, c, d, k, s, Ti) \ t = (a) + H(b, c, d) + X[k] + (Ti); \ (a) = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ SET(a, b, c, d, 5, 4, T33); SET(d, a, b, c, 8, 11, T34); SET(c, d, a, b, 11, 16, T35); SET(b, c, d, a, 14, 23, T36); SET(a, b, c, d, 1, 4, T37); SET(d, a, b, c, 4, 11, T38); SET(c, d, a, b, 7, 16, T39); SET(b, c, d, a, 10, 23, T40); SET(a, b, c, d, 13, 4, T41); SET(d, a, b, c, 0, 11, T42); SET(c, d, a, b, 3, 16, T43); SET(b, c, d, a, 6, 23, T44); SET(a, b, c, d, 9, 4, T45); SET(d, a, b, c, 12, 11, T46); SET(c, d, a, b, 15, 16, T47); SET(b, c, d, a, 2, 23, T48); #undef SET /* Round 4. */ /* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ #define I(x, y, z) ((y) ^ ((x) | ~(z))) #define SET(a, b, c, d, k, s, Ti) \ t = (a) + I(b, c, d) + X[k] + (Ti); \ (a) = ROTATE_LEFT(t, s) + (b) /* Do the following 16 operations. */ SET(a, b, c, d, 0, 6, T49); SET(d, a, b, c, 7, 10, T50); SET(c, d, a, b, 14, 15, T51); SET(b, c, d, a, 5, 21, T52); SET(a, b, c, d, 12, 6, T53); SET(d, a, b, c, 3, 10, T54); SET(c, d, a, b, 10, 15, T55); SET(b, c, d, a, 1, 21, T56); SET(a, b, c, d, 8, 6, T57); SET(d, a, b, c, 15, 10, T58); SET(c, d, a, b, 6, 15, T59); SET(b, c, d, a, 13, 21, T60); SET(a, b, c, d, 4, 6, T61); SET(d, a, b, c, 11, 10, T62); SET(c, d, a, b, 2, 15, T63); SET(b, c, d, a, 9, 21, T64); #undef SET /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block was started.) */ pms->abcd[0] += a; pms->abcd[1] += b; pms->abcd[2] += c; pms->abcd[3] += d; } MD5_STATIC void md5_init(md5_state_t *pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; pms->abcd[3] = 0x10325476; } MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data, size_t nbytes) { const md5_byte_t *p = data; size_t left = nbytes; size_t offset = (pms->count[0] >> 3) & 63; md5_word_t nbits = (md5_word_t)(nbytes << 3); if (nbytes <= 0) return; /* Update the message length. */ pms->count[1] += (md5_word_t)(nbytes >> 29); pms->count[0] += nbits; if (pms->count[0] < nbits) pms->count[1]++; /* Process an initial partial block. */ if (offset) { size_t copy = (offset + nbytes > 64 ? 64 - offset : nbytes); memcpy(pms->buf + offset, p, copy); if (offset + copy < 64) return; p += copy; left -= copy; md5_process(pms, pms->buf); } /* Process full blocks. */ for (; left >= 64; p += 64, left -= 64) md5_process(pms, p); /* Process a final partial block. */ if (left) memcpy(pms->buf, p, left); } MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) { static const md5_byte_t pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ md5_append(pms, data, 8); for (i = 0; i < 16; ++i) digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } /* End of md5.inl */ webfakes/src/mbedtls/0000755000176200001440000000000014740737024014272 5ustar liggesuserswebfakes/src/mbedtls/include/0000755000176200001440000000000015026563042015710 5ustar liggesuserswebfakes/src/mbedtls/include/CMakeLists.txt0000644000176200001440000000127614740737024020463 0ustar liggesusersoption(INSTALL_MBEDTLS_HEADERS "Install Mbed TLS headers." ON) if(INSTALL_MBEDTLS_HEADERS) file(GLOB headers "mbedtls/*.h") file(GLOB psa_headers "psa/*.h") install(FILES ${headers} DESTINATION include/mbedtls PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) install(FILES ${psa_headers} DESTINATION include/psa PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) endif(INSTALL_MBEDTLS_HEADERS) # Make mbedtls_config.h available in an out-of-source build. ssl-opt.sh requires it. if (ENABLE_TESTING AND NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) link_to_source(mbedtls) link_to_source(psa) endif() webfakes/src/mbedtls/include/psa/0000755000176200001440000000000014740737024016500 5ustar liggesuserswebfakes/src/mbedtls/include/psa/crypto_types.h0000644000176200001440000004751114740737024021425 0ustar liggesusers/** * \file psa/crypto_types.h * * \brief PSA cryptography module: type aliases. * * \note This file may not be included directly. Applications must * include psa/crypto.h. Drivers must include the appropriate driver * header file. * * This file contains portable definitions of integral types for properties * of cryptographic keys, designations of cryptographic algorithms, and * error codes returned by the library. * * This header file does not declare any function. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_TYPES_H #define PSA_CRYPTO_TYPES_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" /* Define the MBEDTLS_PRIVATE macro. */ #include "mbedtls/private_access.h" #if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE) #include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE #else #include "crypto_platform.h" #endif #include /** \defgroup error Error codes * @{ */ /** * \brief Function return status. * * This is either #PSA_SUCCESS (which is zero), indicating success, * or a small negative value indicating that an error occurred. Errors are * encoded as one of the \c PSA_ERROR_xxx values defined here. */ /* If #PSA_SUCCESS is already defined, it means that #psa_status_t * is also defined in an external header, so prevent its multiple * definition. */ #ifndef PSA_SUCCESS typedef int32_t psa_status_t; #endif /**@}*/ /** \defgroup crypto_types Key and algorithm types * @{ */ /** \brief Encoding of a key type. * * Values of this type are generally constructed by macros called * `PSA_KEY_TYPE_xxx`. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint16_t psa_key_type_t; /** The type of PSA elliptic curve family identifiers. * * Values of this type are generally constructed by macros called * `PSA_ECC_FAMILY_xxx`. * * The curve identifier is required to create an ECC key using the * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() * macros. * * Values defined by this standard will never be in the range 0x80-0xff. * Vendors who define additional families must use an encoding in this range. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint8_t psa_ecc_family_t; /** The type of PSA Diffie-Hellman group family identifiers. * * Values of this type are generally constructed by macros called * `PSA_DH_FAMILY_xxx`. * * The group identifier is required to create a Diffie-Hellman key using the * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() * macros. * * Values defined by this standard will never be in the range 0x80-0xff. * Vendors who define additional families must use an encoding in this range. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint8_t psa_dh_family_t; /** \brief Encoding of a cryptographic algorithm. * * Values of this type are generally constructed by macros called * `PSA_ALG_xxx`. * * For algorithms that can be applied to multiple key types, this type * does not encode the key type. For example, for symmetric ciphers * based on a block cipher, #psa_algorithm_t encodes the block cipher * mode and the padding mode while the block cipher itself is encoded * via #psa_key_type_t. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint32_t psa_algorithm_t; /**@}*/ /** \defgroup key_lifetimes Key lifetimes * @{ */ /** Encoding of key lifetimes. * * The lifetime of a key indicates where it is stored and what system actions * may create and destroy it. * * Lifetime values have the following structure: * - Bits 0-7 (#PSA_KEY_LIFETIME_GET_PERSISTENCE(\c lifetime)): * persistence level. This value indicates what device management * actions can cause it to be destroyed. In particular, it indicates * whether the key is _volatile_ or _persistent_. * See ::psa_key_persistence_t for more information. * - Bits 8-31 (#PSA_KEY_LIFETIME_GET_LOCATION(\c lifetime)): * location indicator. This value indicates which part of the system * has access to the key material and can perform operations using the key. * See ::psa_key_location_t for more information. * * Volatile keys are automatically destroyed when the application instance * terminates or on a power reset of the device. Persistent keys are * preserved until the application explicitly destroys them or until an * integration-specific device management event occurs (for example, * a factory reset). * * Persistent keys have a key identifier of type #mbedtls_svc_key_id_t. * This identifier remains valid throughout the lifetime of the key, * even if the application instance that created the key terminates. * The application can call psa_open_key() to open a persistent key that * it created previously. * * The default lifetime of a key is #PSA_KEY_LIFETIME_VOLATILE. The lifetime * #PSA_KEY_LIFETIME_PERSISTENT is supported if persistent storage is * available. Other lifetime values may be supported depending on the * library configuration. * * Values of this type are generally constructed by macros called * `PSA_KEY_LIFETIME_xxx`. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint32_t psa_key_lifetime_t; /** Encoding of key persistence levels. * * What distinguishes different persistence levels is what device management * events may cause keys to be destroyed. _Volatile_ keys are destroyed * by a power reset. Persistent keys may be destroyed by events such as * a transfer of ownership or a factory reset. What management events * actually affect persistent keys at different levels is outside the * scope of the PSA Cryptography specification. * * The PSA Cryptography specification defines the following values of * persistence levels: * - \c 0 = #PSA_KEY_PERSISTENCE_VOLATILE: volatile key. * A volatile key is automatically destroyed by the implementation when * the application instance terminates. In particular, a volatile key * is automatically destroyed on a power reset of the device. * - \c 1 = #PSA_KEY_PERSISTENCE_DEFAULT: * persistent key with a default lifetime. * - \c 2-254: currently not supported by Mbed TLS. * - \c 255 = #PSA_KEY_PERSISTENCE_READ_ONLY: * read-only or write-once key. * A key with this persistence level cannot be destroyed. * Mbed TLS does not currently offer a way to create such keys, but * integrations of Mbed TLS can use it for built-in keys that the * application cannot modify (for example, a hardware unique key (HUK)). * * \note Key persistence levels are 8-bit values. Key management * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which * encode the persistence as the lower 8 bits of a 32-bit value. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint8_t psa_key_persistence_t; /** Encoding of key location indicators. * * If an integration of Mbed TLS can make calls to external * cryptoprocessors such as secure elements, the location of a key * indicates which secure element performs the operations on the key. * Depending on the design of the secure element, the key * material may be stored either in the secure element, or * in wrapped (encrypted) form alongside the key metadata in the * primary local storage. * * The PSA Cryptography API specification defines the following values of * location indicators: * - \c 0: primary local storage. * This location is always available. * The primary local storage is typically the same storage area that * contains the key metadata. * - \c 1: primary secure element. * Integrations of Mbed TLS should support this value if there is a secure * element attached to the operating environment. * As a guideline, secure elements may provide higher resistance against * side channel and physical attacks than the primary local storage, but may * have restrictions on supported key types, sizes, policies and operations * and may have different performance characteristics. * - \c 2-0x7fffff: other locations defined by a PSA specification. * The PSA Cryptography API does not currently assign any meaning to these * locations, but future versions of that specification or other PSA * specifications may do so. * - \c 0x800000-0xffffff: vendor-defined locations. * No PSA specification will assign a meaning to locations in this range. * * \note Key location indicators are 24-bit values. Key management * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which * encode the location as the upper 24 bits of a 32-bit value. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint32_t psa_key_location_t; /** Encoding of identifiers of persistent keys. * * - Applications may freely choose key identifiers in the range * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. * - The implementation may define additional key identifiers in the range * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. * - 0 is reserved as an invalid key identifier. * - Key identifiers outside these ranges are reserved for future use. * * \note Values of this type are encoded in the persistent key store. * Any changes to how values are allocated must require careful * consideration to allow backward compatibility. */ typedef uint32_t psa_key_id_t; /** Encoding of key identifiers as seen inside the PSA Crypto implementation. * * When PSA Crypto is built as a library inside an application, this type * is identical to #psa_key_id_t. When PSA Crypto is built as a service * that can store keys on behalf of multiple clients, this type * encodes the #psa_key_id_t value seen by each client application as * well as extra information that identifies the client that owns * the key. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ #if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) typedef psa_key_id_t mbedtls_svc_key_id_t; #else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ /* Implementation-specific: The Mbed TLS library can be built as * part of a multi-client service that exposes the PSA Cryptography API in each * client and encodes the client identity in the key identifier argument of * functions such as psa_open_key(). */ typedef struct { psa_key_id_t MBEDTLS_PRIVATE(key_id); mbedtls_key_owner_id_t MBEDTLS_PRIVATE(owner); } mbedtls_svc_key_id_t; #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ /**@}*/ /** \defgroup policy Key policies * @{ */ /** \brief Encoding of permitted usage on a key. * * Values of this type are generally constructed as bitwise-ors of macros * called `PSA_KEY_USAGE_xxx`. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint32_t psa_key_usage_t; /**@}*/ /** \defgroup attributes Key attributes * @{ */ /** The type of a structure containing key attributes. * * This is an opaque structure that can represent the metadata of a key * object. Metadata that can be stored in attributes includes: * - The location of the key in storage, indicated by its key identifier * and its lifetime. * - The key's policy, comprising usage flags and a specification of * the permitted algorithm(s). * - Information about the key itself: the key type and its size. * - Additional implementation-defined attributes. * * The actual key material is not considered an attribute of a key. * Key attributes do not contain information that is generally considered * highly confidential. * * An attribute structure works like a simple data structure where each function * `psa_set_key_xxx` sets a field and the corresponding function * `psa_get_key_xxx` retrieves the value of the corresponding field. * However, a future version of the library may report values that are * equivalent to the original one, but have a different encoding. Invalid * values may be mapped to different, also invalid values. * * An attribute structure may contain references to auxiliary resources, * for example pointers to allocated memory or indirect references to * pre-calculated values. In order to free such resources, the application * must call psa_reset_key_attributes(). As an exception, calling * psa_reset_key_attributes() on an attribute structure is optional if * the structure has only been modified by the following functions * since it was initialized or last reset with psa_reset_key_attributes(): * - psa_set_key_id() * - psa_set_key_lifetime() * - psa_set_key_type() * - psa_set_key_bits() * - psa_set_key_usage_flags() * - psa_set_key_algorithm() * * Before calling any function on a key attribute structure, the application * must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_key_attributes_t attributes; * memset(&attributes, 0, sizeof(attributes)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_key_attributes_t attributes = {0}; * \endcode * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, * for example: * \code * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * \endcode * - Assign the result of the function psa_key_attributes_init() * to the structure, for example: * \code * psa_key_attributes_t attributes; * attributes = psa_key_attributes_init(); * \endcode * * A freshly initialized attribute structure contains the following * values: * * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. * - key identifier: 0 (which is not a valid key identifier). * - type: \c 0 (meaning that the type is unspecified). * - key size: \c 0 (meaning that the size is unspecified). * - usage flags: \c 0 (which allows no usage except exporting a public key). * - algorithm: \c 0 (which allows no cryptographic usage, but allows * exporting). * * A typical sequence to create a key is as follows: * -# Create and initialize an attribute structure. * -# If the key is persistent, call psa_set_key_id(). * Also call psa_set_key_lifetime() to place the key in a non-default * location. * -# Set the key policy with psa_set_key_usage_flags() and * psa_set_key_algorithm(). * -# Set the key type with psa_set_key_type(). * Skip this step if copying an existing key with psa_copy_key(). * -# When generating a random key with psa_generate_key() or deriving a key * with psa_key_derivation_output_key(), set the desired key size with * psa_set_key_bits(). * -# Call a key creation function: psa_import_key(), psa_generate_key(), * psa_key_derivation_output_key() or psa_copy_key(). This function reads * the attribute structure, creates a key with these attributes, and * outputs a key identifier to the newly created key. * -# The attribute structure is now no longer necessary. * You may call psa_reset_key_attributes(), although this is optional * with the workflow presented here because the attributes currently * defined in this specification do not require any additional resources * beyond the structure itself. * * A typical sequence to query a key's attributes is as follows: * -# Call psa_get_key_attributes(). * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that * you are interested in. * -# Call psa_reset_key_attributes() to free any resources that may be * used by the attribute structure. * * Once a key has been created, it is impossible to change its attributes. */ typedef struct psa_key_attributes_s psa_key_attributes_t; #ifndef __DOXYGEN_ONLY__ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Mbed TLS defines this type in crypto_types.h because it is also * visible to applications through an implementation-specific extension. * For the PSA Cryptography specification, this type is only visible * via crypto_se_driver.h. */ typedef uint64_t psa_key_slot_number_t; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #endif /* !__DOXYGEN_ONLY__ */ /**@}*/ /** \defgroup derivation Key derivation * @{ */ /** \brief Encoding of the step of a key derivation. * * Values of this type are generally constructed by macros called * `PSA_KEY_DERIVATION_INPUT_xxx`. */ typedef uint16_t psa_key_derivation_step_t; /** \brief Custom parameters for key generation or key derivation. * * This is a structure type with at least the following field: * * - \c flags: an unsigned integer type. 0 for the default production parameters. * * Functions that take such a structure as input also take an associated * input buffer \c custom_data of length \c custom_data_length. * * The interpretation of this structure and the associated \c custom_data * parameter depend on the type of the created key. * * - #PSA_KEY_TYPE_RSA_KEY_PAIR: * - \c flags: must be 0. * - \c custom_data: the public exponent, in little-endian order. * This must be an odd integer and must not be 1. * Implementations must support 65537, should support 3 and may * support other values. * When not using a driver, Mbed TLS supports values up to \c INT_MAX. * If this is empty, the default value 65537 is used. * - Other key types: reserved for future use. \c flags must be 0. */ typedef struct psa_custom_key_parameters_s psa_custom_key_parameters_t; /** \brief Custom parameters for key generation or key derivation. * * This is a structure type with at least the following fields: * * - \c flags: an unsigned integer type. 0 for the default production parameters. * - \c data: a flexible array of bytes. * * The interpretation of this structure depend on the type of the * created key. * * - #PSA_KEY_TYPE_RSA_KEY_PAIR: * - \c flags: must be 0. * - \c data: the public exponent, in little-endian order. * This must be an odd integer and must not be 1. * Implementations must support 65537, should support 3 and may * support other values. * When not using a driver, Mbed TLS supports values up to \c INT_MAX. * If this is empty or if the custom production parameters are omitted * altogether, the default value 65537 is used. * - Other key types: reserved for future use. \c flags must be 0. * */ typedef struct psa_key_production_parameters_s psa_key_production_parameters_t; /**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ webfakes/src/mbedtls/include/psa/crypto_values.h0000644000176200001440000035734014740737024021564 0ustar liggesusers/** * \file psa/crypto_values.h * * \brief PSA cryptography module: macros to build and analyze integer values. * * \note This file may not be included directly. Applications must * include psa/crypto.h. Drivers must include the appropriate driver * header file. * * This file contains portable definitions of macros to build and analyze * values of integral types that encode properties of cryptographic keys, * designations of cryptographic algorithms, and error codes returned by * the library. * * Note that many of the constants defined in this file are embedded in * the persistent key store, as part of key metadata (including usage * policies). As a consequence, they must not be changed (unless the storage * format version changes). * * This header file only defines preprocessor macros. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_VALUES_H #define PSA_CRYPTO_VALUES_H #include "mbedtls/private_access.h" /** \defgroup error Error codes * @{ */ /* PSA error codes */ /* Error codes are standardized across PSA domains (framework, crypto, storage, * etc.). Do not change the values in this section or even the expansions * of each macro: it must be possible to `#include` both this header * and some other PSA component's headers in the same C source, * which will lead to duplicate definitions of the `PSA_SUCCESS` and * `PSA_ERROR_xxx` macros, which is ok if and only if the macros expand * to the same sequence of tokens. * * If you must add a new * value, check with the Arm PSA framework group to pick one that other * domains aren't already using. */ /* Tell uncrustify not to touch the constant definitions, otherwise * it might change the spacing to something that is not PSA-compliant * (e.g. adding a space after casts). * * *INDENT-OFF* */ /** The action was completed successfully. */ #define PSA_SUCCESS ((psa_status_t)0) /** An error occurred that does not correspond to any defined * failure cause. * * Implementations may use this error code if none of the other standard * error codes are applicable. */ #define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) /** The requested operation or a parameter is not supported * by this implementation. * * Implementations should return this error code when an enumeration * parameter such as a key type, algorithm, etc. is not recognized. * If a combination of parameters is recognized and identified as * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ #define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) /** The requested action is denied by a policy. * * Implementations should return this error code when the parameters * are recognized as valid and supported, and a policy explicitly * denies the requested operation. * * If a subset of the parameters of a function call identify a * forbidden operation, and another subset of the parameters are * not valid or not supported, it is unspecified whether the function * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or * #PSA_ERROR_INVALID_ARGUMENT. */ #define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) /** An output buffer is too small. * * Applications can call the \c PSA_xxx_SIZE macro listed in the function * description to determine a sufficient buffer size. * * Implementations should preferably return this error code only * in cases when performing the operation with a larger output * buffer would succeed. However implementations may return this * error if a function has invalid or unsupported parameters in addition * to the parameters that determine the necessary output buffer size. */ #define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) /** Asking for an item that already exists * * Implementations should return this error, when attempting * to write an item (like a key) that already exists. */ #define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) /** Asking for an item that doesn't exist * * Implementations should return this error, if a requested item (like * a key) does not exist. */ #define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) /** The requested action cannot be performed in the current state. * * Multipart operations return this error when one of the * functions is called out of sequence. Refer to the function * descriptions for permitted sequencing of functions. * * Implementations shall not return this error code to indicate * that a key either exists or not, * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST * as applicable. * * Implementations shall not return this error code to indicate that a * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE * instead. */ #define PSA_ERROR_BAD_STATE ((psa_status_t)-137) /** The parameters passed to the function are invalid. * * Implementations may return this error any time a parameter or * combination of parameters are recognized as invalid. * * Implementations shall not return this error code to indicate that a * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE * instead. */ #define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) /** There is not enough runtime memory. * * If the action is carried out across multiple security realms, this * error can refer to available memory in any of the security realms. */ #define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) /** There is not enough persistent storage. * * Functions that modify the key storage return this error code if * there is insufficient storage space on the host media. In addition, * many functions that do not otherwise access storage may return this * error code if the implementation requires a mandatory log entry for * the requested action and the log storage space is full. */ #define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) /** There was a communication failure inside the implementation. * * This can indicate a communication failure between the application * and an external cryptoprocessor or between the cryptoprocessor and * an external volatile or persistent memory. A communication failure * may be transient or permanent depending on the cause. * * \warning If a function returns this error, it is undetermined * whether the requested action has completed or not. Implementations * should return #PSA_SUCCESS on successful completion whenever * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE * if the requested action was completed successfully in an external * cryptoprocessor but there was a breakdown of communication before * the cryptoprocessor could report the status to the application. */ #define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) /** There was a storage failure that may have led to data loss. * * This error indicates that some persistent storage is corrupted. * It should not be used for a corruption of volatile memory * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error * between the cryptoprocessor and its external storage (use * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). * * Note that a storage failure does not indicate that any data that was * previously read is invalid. However this previously read data may no * longer be readable from storage. * * When a storage failure occurs, it is no longer possible to ensure * the global integrity of the keystore. Depending on the global * integrity guarantees offered by the implementation, access to other * data may or may not fail even if the data is still readable but * its integrity cannot be guaranteed. * * Implementations should only use this error code to report a * permanent storage corruption. However application writers should * keep in mind that transient errors while reading the storage may be * reported using this error code. */ #define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) /** A hardware failure was detected. * * A hardware failure may be transient or permanent depending on the * cause. */ #define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) /** A tampering attempt was detected. * * If an application receives this error code, there is no guarantee * that previously accessed or computed data was correct and remains * confidential. Applications should not perform any security function * and should enter a safe failure state. * * Implementations may return this error code if they detect an invalid * state that cannot happen during normal operation and that indicates * that the implementation's security guarantees no longer hold. Depending * on the implementation architecture and on its security and safety goals, * the implementation may forcibly terminate the application. * * This error code is intended as a last resort when a security breach * is detected and it is unsure whether the keystore data is still * protected. Implementations shall only return this error code * to report an alarm from a tampering detector, to indicate that * the confidentiality of stored data can no longer be guaranteed, * or to indicate that the integrity of previously returned data is now * considered compromised. Implementations shall not use this error code * to indicate a hardware failure that merely makes it impossible to * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code * instead). * * This error indicates an attack against the application. Implementations * shall not return this error code as a consequence of the behavior of * the application itself. */ #define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) /** There is not enough entropy to generate random data needed * for the requested action. * * This error indicates a failure of a hardware random generator. * Application writers should note that this error can be returned not * only by functions whose purpose is to generate random data, such * as key, IV or nonce generation, but also by functions that execute * an algorithm with a randomized result, as well as functions that * use randomization of intermediate computations as a countermeasure * to certain attacks. * * Implementations should avoid returning this error after psa_crypto_init() * has succeeded. Implementations should generate sufficient * entropy during initialization and subsequently use a cryptographically * secure pseudorandom generator (PRNG). However implementations may return * this error at any time if a policy requires the PRNG to be reseeded * during normal operation. */ #define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) /** The signature, MAC or hash is incorrect. * * Verification functions return this error if the verification * calculations completed successfully, and the value to be verified * was determined to be incorrect. * * If the value to verify has an invalid size, implementations may return * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ #define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) /** The decrypted padding is incorrect. * * \warning In some protocols, when decrypting data, it is essential that * the behavior of the application does not depend on whether the padding * is correct, down to precise timing. Applications should prefer * protocols that use authenticated encryption rather than plain * encryption. If the application must perform a decryption of * unauthenticated data, the application writer should take care not * to reveal whether the padding is invalid. * * Implementations should strive to make valid and invalid padding * as close as possible to indistinguishable to an external observer. * In particular, the timing of a decryption operation should not * depend on the validity of the padding. */ #define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) /** Return this error when there's insufficient data when attempting * to read from a resource. */ #define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) /** This can be returned if a function can no longer operate correctly. * For example, if an essential initialization operation failed or * a mutex operation failed. */ #define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) /** The key identifier is not valid. See also :ref:\`key-handles\`. */ #define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) /** Stored data has been corrupted. * * This error indicates that some persistent storage has suffered corruption. * It does not indicate the following situations, which have specific error * codes: * * - A corruption of volatile memory - use #PSA_ERROR_CORRUPTION_DETECTED. * - A communication error between the cryptoprocessor and its external * storage - use #PSA_ERROR_COMMUNICATION_FAILURE. * - When the storage is in a valid state but is full - use * #PSA_ERROR_INSUFFICIENT_STORAGE. * - When the storage fails for other reasons - use * #PSA_ERROR_STORAGE_FAILURE. * - When the stored data is not valid - use #PSA_ERROR_DATA_INVALID. * * \note A storage corruption does not indicate that any data that was * previously read is invalid. However this previously read data might no * longer be readable from storage. * * When a storage failure occurs, it is no longer possible to ensure the * global integrity of the keystore. */ #define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) /** Data read from storage is not valid for the implementation. * * This error indicates that some data read from storage does not have a valid * format. It does not indicate the following situations, which have specific * error codes: * * - When the storage or stored data is corrupted - use #PSA_ERROR_DATA_CORRUPT * - When the storage fails for other reasons - use #PSA_ERROR_STORAGE_FAILURE * - An invalid argument to the API - use #PSA_ERROR_INVALID_ARGUMENT * * This error is typically a result of either storage corruption on a * cleartext storage backend, or an attempt to read data that was * written by an incompatible version of the library. */ #define PSA_ERROR_DATA_INVALID ((psa_status_t)-153) /** The function that returns this status is defined as interruptible and * still has work to do, thus the user should call the function again with the * same operation context until it either returns #PSA_SUCCESS or any other * error. This is not an error per se, more a notification of status. */ #define PSA_OPERATION_INCOMPLETE ((psa_status_t)-248) /* *INDENT-ON* */ /**@}*/ /** \defgroup crypto_types Key and algorithm types * @{ */ /* Note that key type values, including ECC family and DH group values, are * embedded in the persistent key store, as part of key metadata. As a * consequence, they must not be changed (unless the storage format version * changes). */ /** An invalid key type value. * * Zero is not the encoding of any key type. */ #define PSA_KEY_TYPE_NONE ((psa_key_type_t) 0x0000) /** Vendor-defined key type flag. * * Key types defined by this standard will never have the * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should * respect the bitwise structure used by standard encodings whenever practical. */ #define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t) 0x8000) #define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t) 0x7000) #define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t) 0x1000) #define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t) 0x2000) #define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t) 0x4000) #define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t) 0x7000) #define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t) 0x3000) /** Whether a key type is vendor-defined. * * See also #PSA_KEY_TYPE_VENDOR_FLAG. */ #define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) /** Whether a key type is an unstructured array of bytes. * * This encompasses both symmetric keys and non-key data. */ #define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \ ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) /** Whether a key type is asymmetric: either a key pair or a public key. */ #define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) /** Whether a key type is the public part of a key pair. */ #define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) /** Whether a key type is a key pair containing a private part and a public * part. */ #define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) /** The key pair type corresponding to a public key type. * * You may also pass a key pair type as \p type, it will be left unchanged. * * \param type A public key type or key pair type. * * \return The corresponding key pair type. * If \p type is not a public key or a key pair, * the return value is undefined. */ #define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) /** The public key type corresponding to a key pair type. * * You may also pass a public key type as \p type, it will be left unchanged. * * \param type A public key type or key pair type. * * \return The corresponding public key type. * If \p type is not a public key or a key pair, * the return value is undefined. */ #define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) /** Raw data. * * A "key" of this type cannot be used for any cryptographic operation. * Applications may use this type to store arbitrary data in the keystore. */ #define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t) 0x1001) /** HMAC key. * * The key policy determines which underlying hash algorithm the key can be * used for. * * HMAC keys should generally have the same size as the underlying hash. * This size can be calculated with #PSA_HASH_LENGTH(\c alg) where * \c alg is the HMAC algorithm or the underlying hash algorithm. */ #define PSA_KEY_TYPE_HMAC ((psa_key_type_t) 0x1100) /** A secret for key derivation. * * This key type is for high-entropy secrets only. For low-entropy secrets, * #PSA_KEY_TYPE_PASSWORD should be used instead. * * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_SECRET or * #PSA_KEY_DERIVATION_INPUT_PASSWORD input of key derivation algorithms. * * The key policy determines which key derivation algorithm the key * can be used for. */ #define PSA_KEY_TYPE_DERIVE ((psa_key_type_t) 0x1200) /** A low-entropy secret for password hashing or key derivation. * * This key type is suitable for passwords and passphrases which are typically * intended to be memorizable by humans, and have a low entropy relative to * their size. It can be used for randomly generated or derived keys with * maximum or near-maximum entropy, but #PSA_KEY_TYPE_DERIVE is more suitable * for such keys. It is not suitable for passwords with extremely low entropy, * such as numerical PINs. * * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_PASSWORD input of * key derivation algorithms. Algorithms that accept such an input were * designed to accept low-entropy secret and are known as password hashing or * key stretching algorithms. * * These keys cannot be used as the #PSA_KEY_DERIVATION_INPUT_SECRET input of * key derivation algorithms, as the algorithms that take such an input expect * it to be high-entropy. * * The key policy determines which key derivation algorithm the key can be * used for, among the permissible subset defined above. */ #define PSA_KEY_TYPE_PASSWORD ((psa_key_type_t) 0x1203) /** A secret value that can be used to verify a password hash. * * The key policy determines which key derivation algorithm the key * can be used for, among the same permissible subset as for * #PSA_KEY_TYPE_PASSWORD. */ #define PSA_KEY_TYPE_PASSWORD_HASH ((psa_key_type_t) 0x1205) /** A secret value that can be used in when computing a password hash. * * The key policy determines which key derivation algorithm the key * can be used for, among the subset of algorithms that can use pepper. */ #define PSA_KEY_TYPE_PEPPER ((psa_key_type_t) 0x1206) /** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. * * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or * 32 bytes (AES-256). */ #define PSA_KEY_TYPE_AES ((psa_key_type_t) 0x2400) /** Key for a cipher, AEAD or MAC algorithm based on the * ARIA block cipher. */ #define PSA_KEY_TYPE_ARIA ((psa_key_type_t) 0x2406) /** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). * * The size of the key can be 64 bits (single DES), 128 bits (2-key 3DES) or * 192 bits (3-key 3DES). * * Note that single DES and 2-key 3DES are weak and strongly * deprecated and should only be used to decrypt legacy data. 3-key 3DES * is weak and deprecated and should only be used in legacy protocols. */ #define PSA_KEY_TYPE_DES ((psa_key_type_t) 0x2301) /** Key for a cipher, AEAD or MAC algorithm based on the * Camellia block cipher. */ #define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t) 0x2403) /** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. * * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. * * \note For ChaCha20 and ChaCha20_Poly1305, Mbed TLS only supports * 12-byte nonces. * * \note For ChaCha20, the initial counter value is 0. To encrypt or decrypt * with the initial counter value 1, you can process and discard a * 64-byte block before the real data. */ #define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t) 0x2004) /** RSA public key. * * The size of an RSA key is the bit size of the modulus. */ #define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t) 0x4001) /** RSA key pair (private and public key). * * The size of an RSA key is the bit size of the modulus. */ #define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t) 0x7001) /** Whether a key type is an RSA key (pair or public-only). */ #define PSA_KEY_TYPE_IS_RSA(type) \ (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) #define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t) 0x4100) #define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t) 0x7100) #define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t) 0x00ff) /** Elliptic curve key pair. * * The size of an elliptic curve key is the bit size associated with the curve, * i.e. the bit size of *q* for a curve over a field *Fq*. * See the documentation of `PSA_ECC_FAMILY_xxx` curve families for details. * * \param curve A value of type ::psa_ecc_family_t that * identifies the ECC curve to be used. */ #define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) /** Elliptic curve public key. * * The size of an elliptic curve public key is the same as the corresponding * private key (see #PSA_KEY_TYPE_ECC_KEY_PAIR and the documentation of * `PSA_ECC_FAMILY_xxx` curve families). * * \param curve A value of type ::psa_ecc_family_t that * identifies the ECC curve to be used. */ #define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) /** Whether a key type is an elliptic curve key (pair or public-only). */ #define PSA_KEY_TYPE_IS_ECC(type) \ ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) /** Whether a key type is an elliptic curve key pair. */ #define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) /** Whether a key type is an elliptic curve public key. */ #define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) /** Extract the curve from an elliptic curve key type. */ #define PSA_KEY_TYPE_ECC_GET_FAMILY(type) \ ((psa_ecc_family_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ 0)) /** Check if the curve of given family is Weierstrass elliptic curve. */ #define PSA_ECC_FAMILY_IS_WEIERSTRASS(family) ((family & 0xc0) == 0) /** SEC Koblitz curves over prime fields. * * This family comprises the following curves: * secp192k1, secp224k1, secp256k1. * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf * * \note For secp224k1, the bit-size is 225 (size of a private value). * * \note Mbed TLS only supports secp192k1 and secp256k1. */ #define PSA_ECC_FAMILY_SECP_K1 ((psa_ecc_family_t) 0x17) /** SEC random curves over prime fields. * * This family comprises the following curves: * secp192r1, secp224r1, secp256r1, secp384r1, secp521r1. * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf */ #define PSA_ECC_FAMILY_SECP_R1 ((psa_ecc_family_t) 0x12) /* SECP160R2 (SEC2 v1, obsolete, not supported in Mbed TLS) */ #define PSA_ECC_FAMILY_SECP_R2 ((psa_ecc_family_t) 0x1b) /** SEC Koblitz curves over binary fields. * * This family comprises the following curves: * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1. * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf * * \note Mbed TLS does not support any curve in this family. */ #define PSA_ECC_FAMILY_SECT_K1 ((psa_ecc_family_t) 0x27) /** SEC random curves over binary fields. * * This family comprises the following curves: * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1. * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf * * \note Mbed TLS does not support any curve in this family. */ #define PSA_ECC_FAMILY_SECT_R1 ((psa_ecc_family_t) 0x22) /** SEC additional random curves over binary fields. * * This family comprises the following curve: * sect163r2. * It is defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf * * \note Mbed TLS does not support any curve in this family. */ #define PSA_ECC_FAMILY_SECT_R2 ((psa_ecc_family_t) 0x2b) /** Brainpool P random curves. * * This family comprises the following curves: * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. * It is defined in RFC 5639. * * \note Mbed TLS only supports the 256-bit, 384-bit and 512-bit curves * in this family. */ #define PSA_ECC_FAMILY_BRAINPOOL_P_R1 ((psa_ecc_family_t) 0x30) /** Curve25519 and Curve448. * * This family comprises the following Montgomery curves: * - 255-bit: Bernstein et al., * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. * - 448-bit: Hamburg, * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. */ #define PSA_ECC_FAMILY_MONTGOMERY ((psa_ecc_family_t) 0x41) /** The twisted Edwards curves Ed25519 and Ed448. * * These curves are suitable for EdDSA (#PSA_ALG_PURE_EDDSA for both curves, * #PSA_ALG_ED25519PH for the 255-bit curve, * #PSA_ALG_ED448PH for the 448-bit curve). * * This family comprises the following twisted Edwards curves: * - 255-bit: Edwards25519, the twisted Edwards curve birationally equivalent * to Curve25519. * Bernstein et al., _Twisted Edwards curves_, Africacrypt 2008. * - 448-bit: Edwards448, the twisted Edwards curve birationally equivalent * to Curve448. * Hamburg, _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. * * \note Mbed TLS does not support Edwards curves yet. */ #define PSA_ECC_FAMILY_TWISTED_EDWARDS ((psa_ecc_family_t) 0x42) #define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t) 0x4200) #define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t) 0x7200) #define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t) 0x00ff) /** Diffie-Hellman key pair. * * \param group A value of type ::psa_dh_family_t that identifies the * Diffie-Hellman group to be used. */ #define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) /** Diffie-Hellman public key. * * \param group A value of type ::psa_dh_family_t that identifies the * Diffie-Hellman group to be used. */ #define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) /** Whether a key type is a Diffie-Hellman key (pair or public-only). */ #define PSA_KEY_TYPE_IS_DH(type) \ ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) /** Whether a key type is a Diffie-Hellman key pair. */ #define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ PSA_KEY_TYPE_DH_KEY_PAIR_BASE) /** Whether a key type is a Diffie-Hellman public key. */ #define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) /** Extract the group from a Diffie-Hellman key type. */ #define PSA_KEY_TYPE_DH_GET_FAMILY(type) \ ((psa_dh_family_t) (PSA_KEY_TYPE_IS_DH(type) ? \ ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ 0)) /** Diffie-Hellman groups defined in RFC 7919 Appendix A. * * This family includes groups with the following key sizes (in bits): * 2048, 3072, 4096, 6144, 8192. A given implementation may support * all of these sizes or only a subset. */ #define PSA_DH_FAMILY_RFC7919 ((psa_dh_family_t) 0x03) #define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) \ (((type) >> 8) & 7) /** The block size of a block cipher. * * \param type A cipher key type (value of type #psa_key_type_t). * * \return The block size for a block cipher, or 1 for a stream cipher. * The return value is undefined if \p type is not a supported * cipher key type. * * \note It is possible to build stream cipher algorithms on top of a block * cipher, for example CTR mode (#PSA_ALG_CTR). * This macro only takes the key type into account, so it cannot be * used to determine the size of the data that #psa_cipher_update() * might buffer for future processing in general. * * \note This macro returns a compile-time constant if its argument is one. * * \warning This macro may evaluate its argument multiple times. */ #define PSA_BLOCK_CIPHER_BLOCK_LENGTH(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ 1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) : \ 0u) /* Note that algorithm values are embedded in the persistent key store, * as part of key metadata. As a consequence, they must not be changed * (unless the storage format version changes). */ /** Vendor-defined algorithm flag. * * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG * bit set. Vendors who define additional algorithms must use an encoding with * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure * used by standard encodings whenever practical. */ #define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t) 0x80000000) #define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t) 0x7f000000) #define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t) 0x02000000) #define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t) 0x03000000) #define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t) 0x04000000) #define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t) 0x05000000) #define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t) 0x06000000) #define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t) 0x07000000) #define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t) 0x08000000) #define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t) 0x09000000) /** Whether an algorithm is vendor-defined. * * See also #PSA_ALG_VENDOR_FLAG. */ #define PSA_ALG_IS_VENDOR_DEFINED(alg) \ (((alg) & PSA_ALG_VENDOR_FLAG) != 0) /** Whether the specified algorithm is a hash algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a hash algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_HASH(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) /** Whether the specified algorithm is a MAC algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a MAC algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_MAC(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) /** Whether the specified algorithm is a symmetric cipher algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_CIPHER(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) /** Whether the specified algorithm is an authenticated encryption * with associated data (AEAD) algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_AEAD(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) /** Whether the specified algorithm is an asymmetric signature algorithm, * also known as public-key signature algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an asymmetric signature algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_SIGN(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) /** Whether the specified algorithm is an asymmetric encryption algorithm, * also known as public-key encryption algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an asymmetric encryption algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) /** Whether the specified algorithm is a key agreement algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_KEY_AGREEMENT(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) /** Whether the specified algorithm is a key derivation algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_KEY_DERIVATION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) /** Whether the specified algorithm is a key stretching / password hashing * algorithm. * * A key stretching / password hashing algorithm is a key derivation algorithm * that is suitable for use with a low-entropy secret such as a password. * Equivalently, it's a key derivation algorithm that uses a * #PSA_KEY_DERIVATION_INPUT_PASSWORD input step. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a key stretching / password hashing algorithm, 0 * otherwise. This macro may return either 0 or 1 if \p alg is not a * supported algorithm identifier. */ #define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg) \ (PSA_ALG_IS_KEY_DERIVATION(alg) && \ (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG) /** An invalid algorithm identifier value. */ /* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */ #define PSA_ALG_NONE ((psa_algorithm_t)0) /* *INDENT-ON* */ #define PSA_ALG_HASH_MASK ((psa_algorithm_t) 0x000000ff) /** MD5 */ #define PSA_ALG_MD5 ((psa_algorithm_t) 0x02000003) /** PSA_ALG_RIPEMD160 */ #define PSA_ALG_RIPEMD160 ((psa_algorithm_t) 0x02000004) /** SHA1 */ #define PSA_ALG_SHA_1 ((psa_algorithm_t) 0x02000005) /** SHA2-224 */ #define PSA_ALG_SHA_224 ((psa_algorithm_t) 0x02000008) /** SHA2-256 */ #define PSA_ALG_SHA_256 ((psa_algorithm_t) 0x02000009) /** SHA2-384 */ #define PSA_ALG_SHA_384 ((psa_algorithm_t) 0x0200000a) /** SHA2-512 */ #define PSA_ALG_SHA_512 ((psa_algorithm_t) 0x0200000b) /** SHA2-512/224 */ #define PSA_ALG_SHA_512_224 ((psa_algorithm_t) 0x0200000c) /** SHA2-512/256 */ #define PSA_ALG_SHA_512_256 ((psa_algorithm_t) 0x0200000d) /** SHA3-224 */ #define PSA_ALG_SHA3_224 ((psa_algorithm_t) 0x02000010) /** SHA3-256 */ #define PSA_ALG_SHA3_256 ((psa_algorithm_t) 0x02000011) /** SHA3-384 */ #define PSA_ALG_SHA3_384 ((psa_algorithm_t) 0x02000012) /** SHA3-512 */ #define PSA_ALG_SHA3_512 ((psa_algorithm_t) 0x02000013) /** The first 512 bits (64 bytes) of the SHAKE256 output. * * This is the prehashing for Ed448ph (see #PSA_ALG_ED448PH). For other * scenarios where a hash function based on SHA3/SHAKE is desired, SHA3-512 * has the same output size and a (theoretically) higher security strength. */ #define PSA_ALG_SHAKE256_512 ((psa_algorithm_t) 0x02000015) /** In a hash-and-sign algorithm policy, allow any hash algorithm. * * This value may be used to form the algorithm usage field of a policy * for a signature algorithm that is parametrized by a hash. The key * may then be used to perform operations using the same signature * algorithm parametrized with any supported hash. * * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, #PSA_ALG_RSA_PSS_ANY_SALT, * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. * Then you may create and use a key as follows: * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: * ``` * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); * ``` * - Import or generate key material. * - Call psa_sign_hash() or psa_verify_hash(), passing * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each * call to sign or verify a message may use a different hash. * ``` * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); * ``` * * This value may not be used to build other algorithms that are * parametrized over a hash. For any valid use of this macro to build * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. * * This value may not be used to build an algorithm specification to * perform an operation. It is only valid to build policies. */ #define PSA_ALG_ANY_HASH ((psa_algorithm_t) 0x020000ff) #define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t) 0x00c00000) #define PSA_ALG_HMAC_BASE ((psa_algorithm_t) 0x03800000) /** Macro to build an HMAC algorithm. * * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HMAC algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HMAC(hash_alg) \ (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is an HMAC algorithm. * * HMAC is a family of MAC algorithms that are based on a hash function. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_HMAC(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ PSA_ALG_HMAC_BASE) /* In the encoding of a MAC algorithm, the bits corresponding to * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is * truncated. As an exception, the value 0 means the untruncated algorithm, * whatever its length is. The length is encoded in 6 bits, so it can * reach up to 63; the largest MAC is 64 bytes so its trivial truncation * to full length is correctly encoded as 0 and any non-trivial truncation * is correctly encoded as a value between 1 and 63. */ #define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t) 0x003f0000) #define PSA_MAC_TRUNCATION_OFFSET 16 /* In the encoding of a MAC algorithm, the bit corresponding to * #PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm * is a wildcard algorithm. A key with such wildcard algorithm as permitted * algorithm policy can be used with any algorithm corresponding to the * same base class and having a (potentially truncated) MAC length greater or * equal than the one encoded in #PSA_ALG_MAC_TRUNCATION_MASK. */ #define PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ((psa_algorithm_t) 0x00008000) /** Macro to build a truncated MAC algorithm. * * A truncated MAC algorithm is identical to the corresponding MAC * algorithm except that the MAC value for the truncated algorithm * consists of only the first \p mac_length bytes of the MAC value * for the untruncated algorithm. * * \note This macro may allow constructing algorithm identifiers that * are not valid, either because the specified length is larger * than the untruncated MAC or because the specified length is * smaller than permitted by the implementation. * * \note It is implementation-defined whether a truncated MAC that * is truncated to the same length as the MAC of the untruncated * algorithm is considered identical to the untruncated algorithm * for policy comparison purposes. * * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) * is true). This may be a truncated or untruncated * MAC algorithm. * \param mac_length Desired length of the truncated MAC in bytes. * This must be at most the full length of the MAC * and must be at least an implementation-specified * minimum. The implementation-specified minimum * shall not be zero. * * \return The corresponding MAC algorithm with the specified * length. * \return Unspecified if \p mac_alg is not a supported * MAC algorithm or if \p mac_length is too small or * too large for the specified MAC algorithm. */ #define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ (((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | \ PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) | \ ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) /** Macro to build the base MAC algorithm corresponding to a truncated * MAC algorithm. * * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) * is true). This may be a truncated or untruncated * MAC algorithm. * * \return The corresponding base MAC algorithm. * \return Unspecified if \p mac_alg is not a supported * MAC algorithm. */ #define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ ((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | \ PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) /** Length to which a MAC algorithm is truncated. * * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) * is true). * * \return Length of the truncated MAC in bytes. * \return 0 if \p mac_alg is a non-truncated MAC algorithm. * \return Unspecified if \p mac_alg is not a supported * MAC algorithm. */ #define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) /** Macro to build a MAC minimum-MAC-length wildcard algorithm. * * A minimum-MAC-length MAC wildcard algorithm permits all MAC algorithms * sharing the same base algorithm, and where the (potentially truncated) MAC * length of the specific algorithm is equal to or larger then the wildcard * algorithm's minimum MAC length. * * \note When setting the minimum required MAC length to less than the * smallest MAC length allowed by the base algorithm, this effectively * becomes an 'any-MAC-length-allowed' policy for that base algorithm. * * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) * is true). * \param min_mac_length Desired minimum length of the message authentication * code in bytes. This must be at most the untruncated * length of the MAC and must be at least 1. * * \return The corresponding MAC wildcard algorithm with the * specified minimum length. * \return Unspecified if \p mac_alg is not a supported MAC * algorithm or if \p min_mac_length is less than 1 or * too large for the specified MAC algorithm. */ #define PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(mac_alg, min_mac_length) \ (PSA_ALG_TRUNCATED_MAC(mac_alg, min_mac_length) | \ PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) #define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t) 0x03c00000) /** The CBC-MAC construction over a block cipher * * \warning CBC-MAC is insecure in many cases. * A more secure mode, such as #PSA_ALG_CMAC, is recommended. */ #define PSA_ALG_CBC_MAC ((psa_algorithm_t) 0x03c00100) /** The CMAC construction over a block cipher */ #define PSA_ALG_CMAC ((psa_algorithm_t) 0x03c00200) /** Whether the specified algorithm is a MAC algorithm based on a block cipher. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ PSA_ALG_CIPHER_MAC_BASE) #define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t) 0x00800000) #define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t) 0x00400000) /** Whether the specified algorithm is a stream cipher. * * A stream cipher is a symmetric cipher that encrypts or decrypts messages * by applying a bitwise-xor with a stream of bytes that is generated * from a key. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier or if it is not a symmetric cipher algorithm. */ #define PSA_ALG_IS_STREAM_CIPHER(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) /** The stream cipher mode of a stream cipher algorithm. * * The underlying stream cipher is determined by the key type. * - To use ChaCha20, use a key type of #PSA_KEY_TYPE_CHACHA20. */ #define PSA_ALG_STREAM_CIPHER ((psa_algorithm_t) 0x04800100) /** The CTR stream cipher mode. * * CTR is a stream cipher which is built from a block cipher. * The underlying block cipher is determined by the key type. * For example, to use AES-128-CTR, use this algorithm with * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). */ #define PSA_ALG_CTR ((psa_algorithm_t) 0x04c01000) /** The CFB stream cipher mode. * * The underlying block cipher is determined by the key type. */ #define PSA_ALG_CFB ((psa_algorithm_t) 0x04c01100) /** The OFB stream cipher mode. * * The underlying block cipher is determined by the key type. */ #define PSA_ALG_OFB ((psa_algorithm_t) 0x04c01200) /** The XTS cipher mode. * * XTS is a cipher mode which is built from a block cipher. It requires at * least one full block of input, but beyond this minimum the input * does not need to be a whole number of blocks. */ #define PSA_ALG_XTS ((psa_algorithm_t) 0x0440ff00) /** The Electronic Code Book (ECB) mode of a block cipher, with no padding. * * \warning ECB mode does not protect the confidentiality of the encrypted data * except in extremely narrow circumstances. It is recommended that applications * only use ECB if they need to construct an operating mode that the * implementation does not provide. Implementations are encouraged to provide * the modes that applications need in preference to supporting direct access * to ECB. * * The underlying block cipher is determined by the key type. * * This symmetric cipher mode can only be used with messages whose lengths are a * multiple of the block size of the chosen block cipher. * * ECB mode does not accept an initialization vector (IV). When using a * multi-part cipher operation with this algorithm, psa_cipher_generate_iv() * and psa_cipher_set_iv() must not be called. */ #define PSA_ALG_ECB_NO_PADDING ((psa_algorithm_t) 0x04404400) /** The CBC block cipher chaining mode, with no padding. * * The underlying block cipher is determined by the key type. * * This symmetric cipher mode can only be used with messages whose lengths * are whole number of blocks for the chosen block cipher. */ #define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t) 0x04404000) /** The CBC block cipher chaining mode with PKCS#7 padding. * * The underlying block cipher is determined by the key type. * * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. */ #define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t) 0x04404100) #define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t) 0x00400000) /** Whether the specified algorithm is an AEAD mode on a block cipher. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on * a block cipher, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) /** The CCM authenticated encryption algorithm. * * The underlying block cipher is determined by the key type. */ #define PSA_ALG_CCM ((psa_algorithm_t) 0x05500100) /** The CCM* cipher mode without authentication. * * This is CCM* as specified in IEEE 802.15.4 §7, with a tag length of 0. * For CCM* with a nonzero tag length, use the AEAD algorithm #PSA_ALG_CCM. * * The underlying block cipher is determined by the key type. * * Currently only 13-byte long IV's are supported. */ #define PSA_ALG_CCM_STAR_NO_TAG ((psa_algorithm_t) 0x04c01300) /** The GCM authenticated encryption algorithm. * * The underlying block cipher is determined by the key type. */ #define PSA_ALG_GCM ((psa_algorithm_t) 0x05500200) /** The Chacha20-Poly1305 AEAD algorithm. * * The ChaCha20_Poly1305 construction is defined in RFC 7539. * * Implementations must support 12-byte nonces, may support 8-byte nonces, * and should reject other sizes. * * Implementations must support 16-byte tags and should reject other sizes. */ #define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t) 0x05100500) /* In the encoding of an AEAD algorithm, the bits corresponding to * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. * The constants for default lengths follow this encoding. */ #define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t) 0x003f0000) #define PSA_AEAD_TAG_LENGTH_OFFSET 16 /* In the encoding of an AEAD algorithm, the bit corresponding to * #PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm * is a wildcard algorithm. A key with such wildcard algorithm as permitted * algorithm policy can be used with any algorithm corresponding to the * same base class and having a tag length greater than or equal to the one * encoded in #PSA_ALG_AEAD_TAG_LENGTH_MASK. */ #define PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ((psa_algorithm_t) 0x00008000) /** Macro to build a shortened AEAD algorithm. * * A shortened AEAD algorithm is similar to the corresponding AEAD * algorithm, but has an authentication tag that consists of fewer bytes. * Depending on the algorithm, the tag length may affect the calculation * of the ciphertext. * * \param aead_alg An AEAD algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg) * is true). * \param tag_length Desired length of the authentication tag in bytes. * * \return The corresponding AEAD algorithm with the specified * length. * \return Unspecified if \p aead_alg is not a supported * AEAD algorithm or if \p tag_length is not valid * for the specified AEAD algorithm. */ #define PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length) \ (((aead_alg) & ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | \ PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG)) | \ ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ PSA_ALG_AEAD_TAG_LENGTH_MASK)) /** Retrieve the tag length of a specified AEAD algorithm * * \param aead_alg An AEAD algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg) * is true). * * \return The tag length specified by the input algorithm. * \return Unspecified if \p aead_alg is not a supported * AEAD algorithm. */ #define PSA_ALG_AEAD_GET_TAG_LENGTH(aead_alg) \ (((aead_alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> \ PSA_AEAD_TAG_LENGTH_OFFSET) /** Calculate the corresponding AEAD algorithm with the default tag length. * * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p aead_alg) is true). * * \return The corresponding AEAD algorithm with the default * tag length for that algorithm. */ #define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg) \ ( \ PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CCM) \ PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_GCM) \ PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ 0) #define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, ref) \ PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, 0) == \ PSA_ALG_AEAD_WITH_SHORTENED_TAG(ref, 0) ? \ ref : /** Macro to build an AEAD minimum-tag-length wildcard algorithm. * * A minimum-tag-length AEAD wildcard algorithm permits all AEAD algorithms * sharing the same base algorithm, and where the tag length of the specific * algorithm is equal to or larger then the minimum tag length specified by the * wildcard algorithm. * * \note When setting the minimum required tag length to less than the * smallest tag length allowed by the base algorithm, this effectively * becomes an 'any-tag-length-allowed' policy for that base algorithm. * * \param aead_alg An AEAD algorithm identifier (value of type * #psa_algorithm_t such that * #PSA_ALG_IS_AEAD(\p aead_alg) is true). * \param min_tag_length Desired minimum length of the authentication tag in * bytes. This must be at least 1 and at most the largest * allowed tag length of the algorithm. * * \return The corresponding AEAD wildcard algorithm with the * specified minimum length. * \return Unspecified if \p aead_alg is not a supported * AEAD algorithm or if \p min_tag_length is less than 1 * or too large for the specified AEAD algorithm. */ #define PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(aead_alg, min_tag_length) \ (PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, min_tag_length) | \ PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) #define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t) 0x06000200) /** RSA PKCS#1 v1.5 signature with hashing. * * This is the signature scheme defined by RFC 8017 * (PKCS#1: RSA Cryptography Specifications) under the name * RSASSA-PKCS1-v1_5. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Raw PKCS#1 v1.5 signature. * * The input to this algorithm is the DigestInfo structure used by * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 * steps 3–6. */ #define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE #define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) #define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t) 0x06000300) #define PSA_ALG_RSA_PSS_ANY_SALT_BASE ((psa_algorithm_t) 0x06001300) /** RSA PSS signature with hashing. * * This is the signature scheme defined by RFC 8017 * (PKCS#1: RSA Cryptography Specifications) under the name * RSASSA-PSS, with the message generation function MGF1, and with * a salt length equal to the length of the hash, or the largest * possible salt length for the algorithm and key size if that is * smaller than the hash length. The specified hash algorithm is * used to hash the input message, to create the salted hash, and * for the mask generation. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding RSA PSS signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_PSS(hash_alg) \ (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** RSA PSS signature with hashing with relaxed verification. * * This algorithm has the same behavior as #PSA_ALG_RSA_PSS when signing, * but allows an arbitrary salt length (including \c 0) when verifying a * signature. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding RSA PSS signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_PSS_ANY_SALT(hash_alg) \ (PSA_ALG_RSA_PSS_ANY_SALT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is RSA PSS with standard salt. * * \param alg An algorithm value or an algorithm policy wildcard. * * \return 1 if \p alg is of the form * #PSA_ALG_RSA_PSS(\c hash_alg), * where \c hash_alg is a hash algorithm or * #PSA_ALG_ANY_HASH. 0 otherwise. * This macro may return either 0 or 1 if \p alg is not * a supported algorithm identifier or policy. */ #define PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) /** Whether the specified algorithm is RSA PSS with any salt. * * \param alg An algorithm value or an algorithm policy wildcard. * * \return 1 if \p alg is of the form * #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg), * where \c hash_alg is a hash algorithm or * #PSA_ALG_ANY_HASH. 0 otherwise. * This macro may return either 0 or 1 if \p alg is not * a supported algorithm identifier or policy. */ #define PSA_ALG_IS_RSA_PSS_ANY_SALT(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_ANY_SALT_BASE) /** Whether the specified algorithm is RSA PSS. * * This includes any of the RSA PSS algorithm variants, regardless of the * constraints on salt length. * * \param alg An algorithm value or an algorithm policy wildcard. * * \return 1 if \p alg is of the form * #PSA_ALG_RSA_PSS(\c hash_alg) or * #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg), * where \c hash_alg is a hash algorithm or * #PSA_ALG_ANY_HASH. 0 otherwise. * This macro may return either 0 or 1 if \p alg is not * a supported algorithm identifier or policy. */ #define PSA_ALG_IS_RSA_PSS(alg) \ (PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) || \ PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) #define PSA_ALG_ECDSA_BASE ((psa_algorithm_t) 0x06000600) /** ECDSA signature with hashing. * * This is the ECDSA signature scheme defined by ANSI X9.62, * with a random per-message secret number (*k*). * * The representation of the signature as a byte string consists of * the concatenation of the signature values *r* and *s*. Each of * *r* and *s* is encoded as an *N*-octet string, where *N* is the length * of the base point of the curve in octets. Each value is represented * in big-endian order (most significant octet first). * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding ECDSA signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_ECDSA(hash_alg) \ (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** ECDSA signature without hashing. * * This is the same signature scheme as #PSA_ALG_ECDSA(), but * without specifying a hash algorithm. This algorithm may only be * used to sign or verify a sequence of bytes that should be an * already-calculated hash. Note that the input is padded with * zeros on the left or truncated on the left as required to fit * the curve size. */ #define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE #define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t) 0x06000700) /** Deterministic ECDSA signature with hashing. * * This is the deterministic ECDSA signature scheme defined by RFC 6979. * * The representation of a signature is the same as with #PSA_ALG_ECDSA(). * * Note that when this algorithm is used for verification, signatures * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the * same private key are accepted. In other words, * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding deterministic ECDSA signature * algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t) 0x00000100) #define PSA_ALG_IS_ECDSA(alg) \ (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ PSA_ALG_ECDSA_BASE) #define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) #define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) /** Edwards-curve digital signature algorithm without prehashing (PureEdDSA), * using standard parameters. * * Contexts are not supported in the current version of this specification * because there is no suitable signature interface that can take the * context as a parameter. A future version of this specification may add * suitable functions and extend this algorithm to support contexts. * * PureEdDSA requires an elliptic curve key on a twisted Edwards curve. * In this specification, the following curves are supported: * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 255-bit: Ed25519 as specified * in RFC 8032. * The curve is Edwards25519. * The hash function used internally is SHA-512. * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 448-bit: Ed448 as specified * in RFC 8032. * The curve is Edwards448. * The hash function used internally is the first 114 bytes of the * SHAKE256 output. * * This algorithm can be used with psa_sign_message() and * psa_verify_message(). Since there is no prehashing, it cannot be used * with psa_sign_hash() or psa_verify_hash(). * * The signature format is the concatenation of R and S as defined by * RFC 8032 §5.1.6 and §5.2.6 (a 64-byte string for Ed25519, a 114-byte * string for Ed448). */ #define PSA_ALG_PURE_EDDSA ((psa_algorithm_t) 0x06000800) #define PSA_ALG_HASH_EDDSA_BASE ((psa_algorithm_t) 0x06000900) #define PSA_ALG_IS_HASH_EDDSA(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HASH_EDDSA_BASE) /** Edwards-curve digital signature algorithm with prehashing (HashEdDSA), * using SHA-512 and the Edwards25519 curve. * * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format. * * This algorithm is Ed25519 as specified in RFC 8032. * The curve is Edwards25519. * The prehash is SHA-512. * The hash function used internally is SHA-512. * * This is a hash-and-sign algorithm: to calculate a signature, * you can either: * - call psa_sign_message() on the message; * - or calculate the SHA-512 hash of the message * with psa_hash_compute() * or with a multi-part hash operation started with psa_hash_setup(), * using the hash algorithm #PSA_ALG_SHA_512, * then sign the calculated hash with psa_sign_hash(). * Verifying a signature is similar, using psa_verify_message() or * psa_verify_hash() instead of the signature function. */ #define PSA_ALG_ED25519PH \ (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHA_512 & PSA_ALG_HASH_MASK)) /** Edwards-curve digital signature algorithm with prehashing (HashEdDSA), * using SHAKE256 and the Edwards448 curve. * * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format. * * This algorithm is Ed448 as specified in RFC 8032. * The curve is Edwards448. * The prehash is the first 64 bytes of the SHAKE256 output. * The hash function used internally is the first 114 bytes of the * SHAKE256 output. * * This is a hash-and-sign algorithm: to calculate a signature, * you can either: * - call psa_sign_message() on the message; * - or calculate the first 64 bytes of the SHAKE256 output of the message * with psa_hash_compute() * or with a multi-part hash operation started with psa_hash_setup(), * using the hash algorithm #PSA_ALG_SHAKE256_512, * then sign the calculated hash with psa_sign_hash(). * Verifying a signature is similar, using psa_verify_message() or * psa_verify_hash() instead of the signature function. */ #define PSA_ALG_ED448PH \ (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHAKE256_512 & PSA_ALG_HASH_MASK)) /* Default definition, to be overridden if the library is extended with * more hash-and-sign algorithms that we want to keep out of this header * file. */ #define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) 0 /** Whether the specified algorithm is a signature algorithm that can be used * with psa_sign_hash() and psa_verify_hash(). * * This encompasses all strict hash-and-sign algorithms categorized by * PSA_ALG_IS_HASH_AND_SIGN(), as well as algorithms that follow the * paradigm more loosely: * - #PSA_ALG_RSA_PKCS1V15_SIGN_RAW (expects its input to be an encoded hash) * - #PSA_ALG_ECDSA_ANY (doesn't specify what kind of hash the input is) * * \param alg An algorithm identifier (value of type psa_algorithm_t). * * \return 1 if alg is a signature algorithm that can be used to sign a * hash. 0 if alg is a signature algorithm that can only be used * to sign a message. 0 if alg is not a signature algorithm. * This macro can return either 0 or 1 if alg is not a * supported algorithm identifier. */ #define PSA_ALG_IS_SIGN_HASH(alg) \ (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \ PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)) /** Whether the specified algorithm is a signature algorithm that can be used * with psa_sign_message() and psa_verify_message(). * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if alg is a signature algorithm that can be used to sign a * message. 0 if \p alg is a signature algorithm that can only be used * to sign an already-calculated hash. 0 if \p alg is not a signature * algorithm. This macro can return either 0 or 1 if \p alg is not a * supported algorithm identifier. */ #define PSA_ALG_IS_SIGN_MESSAGE(alg) \ (PSA_ALG_IS_SIGN_HASH(alg) || (alg) == PSA_ALG_PURE_EDDSA) /** Whether the specified algorithm is a hash-and-sign algorithm. * * Hash-and-sign algorithms are asymmetric (public-key) signature algorithms * structured in two parts: first the calculation of a hash in a way that * does not depend on the key, then the calculation of a signature from the * hash value and the key. Hash-and-sign algorithms encode the hash * used for the hashing step, and you can call #PSA_ALG_SIGN_GET_HASH * to extract this algorithm. * * Thus, for a hash-and-sign algorithm, * `psa_sign_message(key, alg, input, ...)` is equivalent to * ``` * psa_hash_compute(PSA_ALG_SIGN_GET_HASH(alg), input, ..., hash, ...); * psa_sign_hash(key, alg, hash, ..., signature, ...); * ``` * Most usefully, separating the hash from the signature allows the hash * to be calculated in multiple steps with psa_hash_setup(), psa_hash_update() * and psa_hash_finish(). Likewise psa_verify_message() is equivalent to * calculating the hash and then calling psa_verify_hash(). * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_HASH_AND_SIGN(alg) \ (PSA_ALG_IS_SIGN_HASH(alg) && \ ((alg) & PSA_ALG_HASH_MASK) != 0) /** Get the hash used by a hash-and-sign signature algorithm. * * A hash-and-sign algorithm is a signature algorithm which is * composed of two phases: first a hashing phase which does not use * the key and produces a hash of the input message, then a signing * phase which only uses the hash and the key and not the message * itself. * * \param alg A signature algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_SIGN(\p alg) is true). * * \return The underlying hash algorithm if \p alg is a hash-and-sign * algorithm. * \return 0 if \p alg is a signature algorithm that does not * follow the hash-and-sign structure. * \return Unspecified if \p alg is not a signature algorithm or * if it is not supported by the implementation. */ #define PSA_ALG_SIGN_GET_HASH(alg) \ (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ 0) /** RSA PKCS#1 v1.5 encryption. * * \warning Calling psa_asymmetric_decrypt() with this algorithm as a * parameter is considered an inherently dangerous function * (CWE-242). Unless it is used in a side channel free and safe * way (eg. implementing the TLS protocol as per 7.4.7.1 of * RFC 5246), the calling code is vulnerable. * */ #define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t) 0x07000200) #define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t) 0x07000300) /** RSA OAEP encryption. * * This is the encryption scheme defined by RFC 8017 * (PKCS#1: RSA Cryptography Specifications) under the name * RSAES-OAEP, with the message generation function MGF1. * * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use * for MGF1. * * \return The corresponding RSA OAEP encryption algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_OAEP(hash_alg) \ (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_IS_RSA_OAEP(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) #define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ (PSA_ALG_IS_RSA_OAEP(alg) ? \ ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ 0) #define PSA_ALG_HKDF_BASE ((psa_algorithm_t) 0x08000100) /** Macro to build an HKDF algorithm. * * For example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)` is HKDF using HMAC-SHA-256. * * This key derivation algorithm uses the following inputs: * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. * It is optional; if omitted, the derivation uses an empty salt. * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before * starting to generate output. * * \warning HKDF processes the salt as follows: first hash it with hash_alg * if the salt is longer than the block size of the hash algorithm; then * pad with null bytes up to the block size. As a result, it is possible * for distinct salt inputs to result in the same outputs. To ensure * unique outputs, it is recommended to use a fixed length for salt values. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HKDF algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HKDF(hash_alg) \ (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is an HKDF algorithm. * * HKDF is a family of key derivation algorithms that are based on a hash * function and the HMAC construction. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_HKDF(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) #define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_HKDF_EXTRACT_BASE ((psa_algorithm_t) 0x08000400) /** Macro to build an HKDF-Extract algorithm. * * For example, `PSA_ALG_HKDF_EXTRACT(PSA_ALG_SHA_256)` is * HKDF-Extract using HMAC-SHA-256. * * This key derivation algorithm uses the following inputs: * - PSA_KEY_DERIVATION_INPUT_SALT is the salt. * - PSA_KEY_DERIVATION_INPUT_SECRET is the input keying material used in the * "extract" step. * The inputs are mandatory and must be passed in the order above. * Each input may only be passed once. * * \warning HKDF-Extract is not meant to be used on its own. PSA_ALG_HKDF * should be used instead if possible. PSA_ALG_HKDF_EXTRACT is provided * as a separate algorithm for the sake of protocols that use it as a * building block. It may also be a slight performance optimization * in applications that use HKDF with the same salt and key but many * different info strings. * * \warning HKDF processes the salt as follows: first hash it with hash_alg * if the salt is longer than the block size of the hash algorithm; then * pad with null bytes up to the block size. As a result, it is possible * for distinct salt inputs to result in the same outputs. To ensure * unique outputs, it is recommended to use a fixed length for salt values. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HKDF-Extract algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HKDF_EXTRACT(hash_alg) \ (PSA_ALG_HKDF_EXTRACT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is an HKDF-Extract algorithm. * * HKDF-Extract is a family of key derivation algorithms that are based * on a hash function and the HMAC construction. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is an HKDF-Extract algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_HKDF_EXTRACT(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE) #define PSA_ALG_HKDF_EXPAND_BASE ((psa_algorithm_t) 0x08000500) /** Macro to build an HKDF-Expand algorithm. * * For example, `PSA_ALG_HKDF_EXPAND(PSA_ALG_SHA_256)` is * HKDF-Expand using HMAC-SHA-256. * * This key derivation algorithm uses the following inputs: * - PSA_KEY_DERIVATION_INPUT_SECRET is the pseudorandom key (PRK). * - PSA_KEY_DERIVATION_INPUT_INFO is the info string. * * The inputs are mandatory and must be passed in the order above. * Each input may only be passed once. * * \warning HKDF-Expand is not meant to be used on its own. `PSA_ALG_HKDF` * should be used instead if possible. `PSA_ALG_HKDF_EXPAND` is provided as * a separate algorithm for the sake of protocols that use it as a building * block. It may also be a slight performance optimization in applications * that use HKDF with the same salt and key but many different info strings. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HKDF-Expand algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HKDF_EXPAND(hash_alg) \ (PSA_ALG_HKDF_EXPAND_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is an HKDF-Expand algorithm. * * HKDF-Expand is a family of key derivation algorithms that are based * on a hash function and the HMAC construction. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is an HKDF-Expand algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_HKDF_EXPAND(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE) /** Whether the specified algorithm is an HKDF or HKDF-Extract or * HKDF-Expand algorithm. * * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is any HKDF type algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_ANY_HKDF(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE || \ ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE || \ ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE) #define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t) 0x08000200) /** Macro to build a TLS-1.2 PRF algorithm. * * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, * specified in Section 5 of RFC 5246. It is based on HMAC and can be * used with either SHA-256 or SHA-384. * * This key derivation algorithm uses the following inputs, which must be * passed in the order given here: * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. * * For the application to TLS-1.2 key expansion, the seed is the * concatenation of ServerHello.Random + ClientHello.Random, * and the label is "key expansion". * * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)` represents the * TLS 1.2 PRF using HMAC-SHA-256. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding TLS-1.2 PRF algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_TLS12_PRF(hash_alg) \ (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is a TLS-1.2 PRF algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_TLS12_PRF(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) #define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t) 0x08000300) /** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. * * In a pure-PSK handshake in TLS 1.2, the master secret is derived * from the PreSharedKey (PSK) through the application of padding * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). * The latter is based on HMAC and can be used with either SHA-256 * or SHA-384. * * This key derivation algorithm uses the following inputs, which must be * passed in the order given here: * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. * - #PSA_KEY_DERIVATION_INPUT_OTHER_SECRET is the other secret for the * computation of the premaster secret. This input is optional; * if omitted, it defaults to a string of null bytes with the same length * as the secret (PSK) input. * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. * * For the application to TLS-1.2, the seed (which is * forwarded to the TLS-1.2 PRF) is the concatenation of the * ClientHello.Random + ServerHello.Random, * the label is "master secret" or "extended master secret" and * the other secret depends on the key exchange specified in the cipher suite: * - for a plain PSK cipher suite (RFC 4279, Section 2), omit * PSA_KEY_DERIVATION_INPUT_OTHER_SECRET * - for a DHE-PSK (RFC 4279, Section 3) or ECDHE-PSK cipher suite * (RFC 5489, Section 2), the other secret should be the output of the * PSA_ALG_FFDH or PSA_ALG_ECDH key agreement performed with the peer. * The recommended way to pass this input is to use a key derivation * algorithm constructed as * PSA_ALG_KEY_AGREEMENT(ka_alg, PSA_ALG_TLS12_PSK_TO_MS(hash_alg)) * and to call psa_key_derivation_key_agreement(). Alternatively, * this input may be an output of `psa_raw_key_agreement()` passed with * psa_key_derivation_input_bytes(), or an equivalent input passed with * psa_key_derivation_input_bytes() or psa_key_derivation_input_key(). * - for a RSA-PSK cipher suite (RFC 4279, Section 4), the other secret * should be the 48-byte client challenge (the PreMasterSecret of * (RFC 5246, Section 7.4.7.1)) concatenation of the TLS version and * a 46-byte random string chosen by the client. On the server, this is * typically an output of psa_asymmetric_decrypt() using * PSA_ALG_RSA_PKCS1V15_CRYPT, passed to the key derivation operation * with `psa_key_derivation_input_bytes()`. * * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)` represents the * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding TLS-1.2 PSK to MS algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) #define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) /* The TLS 1.2 ECJPAKE-to-PMS KDF. It takes the shared secret K (an EC point * in case of EC J-PAKE) and calculates SHA256(K.X) that the rest of TLS 1.2 * will use to derive the session secret, as defined by step 2 of * https://datatracker.ietf.org/doc/html/draft-cragie-tls-ecjpake-01#section-8.7. * Uses PSA_ALG_SHA_256. * This function takes a single input: * #PSA_KEY_DERIVATION_INPUT_SECRET is the shared secret K from EC J-PAKE. * The only supported curve is secp256r1 (the 256-bit curve in * #PSA_ECC_FAMILY_SECP_R1), so the input must be exactly 65 bytes. * The output has to be read as a single chunk of 32 bytes, defined as * PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE. */ #define PSA_ALG_TLS12_ECJPAKE_TO_PMS ((psa_algorithm_t) 0x08000609) /* This flag indicates whether the key derivation algorithm is suitable for * use on low-entropy secrets such as password - these algorithms are also * known as key stretching or password hashing schemes. These are also the * algorithms that accepts inputs of type #PSA_KEY_DERIVATION_INPUT_PASSWORD. * * Those algorithms cannot be combined with a key agreement algorithm. */ #define PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG ((psa_algorithm_t) 0x00800000) #define PSA_ALG_PBKDF2_HMAC_BASE ((psa_algorithm_t) 0x08800100) /** Macro to build a PBKDF2-HMAC password hashing / key stretching algorithm. * * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). * This macro specifies the PBKDF2 algorithm constructed using a PRF based on * HMAC with the specified hash. * For example, `PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)` specifies PBKDF2 * using the PRF HMAC-SHA-256. * * This key derivation algorithm uses the following inputs, which must be * provided in the following order: * - #PSA_KEY_DERIVATION_INPUT_COST is the iteration count. * This input step must be used exactly once. * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt. * This input step must be used one or more times; if used several times, the * inputs will be concatenated. This can be used to build the final salt * from multiple sources, both public and secret (also known as pepper). * - #PSA_KEY_DERIVATION_INPUT_PASSWORD is the password to be hashed. * This input step must be used exactly once. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding PBKDF2-HMAC-XXX algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_PBKDF2_HMAC(hash_alg) \ (PSA_ALG_PBKDF2_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is a PBKDF2-HMAC algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a PBKDF2-HMAC algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_PBKDF2_HMAC(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_PBKDF2_HMAC_BASE) #define PSA_ALG_PBKDF2_HMAC_GET_HASH(pbkdf2_alg) \ (PSA_ALG_CATEGORY_HASH | ((pbkdf2_alg) & PSA_ALG_HASH_MASK)) /** The PBKDF2-AES-CMAC-PRF-128 password hashing / key stretching algorithm. * * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). * This macro specifies the PBKDF2 algorithm constructed using the * AES-CMAC-PRF-128 PRF specified by RFC 4615. * * This key derivation algorithm uses the same inputs as * #PSA_ALG_PBKDF2_HMAC() with the same constraints. */ #define PSA_ALG_PBKDF2_AES_CMAC_PRF_128 ((psa_algorithm_t) 0x08800200) #define PSA_ALG_IS_PBKDF2(kdf_alg) \ (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg) || \ ((kdf_alg) == PSA_ALG_PBKDF2_AES_CMAC_PRF_128)) #define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t) 0xfe00ffff) #define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t) 0xffff0000) /** Macro to build a combined algorithm that chains a key agreement with * a key derivation. * * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). * * \return The corresponding key agreement and derivation * algorithm. * \return Unspecified if \p ka_alg is not a supported * key agreement algorithm or \p kdf_alg is not a * supported key derivation algorithm. */ #define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ ((ka_alg) | (kdf_alg)) #define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) #define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) /** Whether the specified algorithm is a raw key agreement algorithm. * * A raw key agreement algorithm is one that does not specify * a key derivation function. * Usually, raw key agreement algorithms are constructed directly with * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are * constructed with #PSA_ALG_KEY_AGREEMENT(). * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) #define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) /** The finite-field Diffie-Hellman (DH) key agreement algorithm. * * The shared secret produced by key agreement is * `g^{ab}` in big-endian format. * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` * in bits. */ #define PSA_ALG_FFDH ((psa_algorithm_t) 0x09010000) /** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. * * This includes the raw finite field Diffie-Hellman algorithm as well as * finite-field Diffie-Hellman followed by any supporter key derivation * algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key agreement algorithm identifier. */ #define PSA_ALG_IS_FFDH(alg) \ (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) /** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. * * The shared secret produced by key agreement is the x-coordinate of * the shared secret point. It is always `ceiling(m / 8)` bytes long where * `m` is the bit size associated with the curve, i.e. the bit size of the * order of the curve's coordinate field. When `m` is not a multiple of 8, * the byte containing the most significant bit of the shared secret * is padded with zero bits. The byte order is either little-endian * or big-endian depending on the curve type. * * - For Montgomery curves (curve types `PSA_ECC_FAMILY_CURVEXXX`), * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` * in little-endian byte order. * The bit size is 448 for Curve448 and 255 for Curve25519. * - For Weierstrass curves over prime fields (curve types * `PSA_ECC_FAMILY_SECPXXX` and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`), * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` * in big-endian byte order. * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. * - For Weierstrass curves over binary fields (curve types * `PSA_ECC_FAMILY_SECTXXX`), * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` * in big-endian byte order. * The bit size is `m` for the field `F_{2^m}`. */ #define PSA_ALG_ECDH ((psa_algorithm_t) 0x09020000) /** Whether the specified algorithm is an elliptic curve Diffie-Hellman * algorithm. * * This includes the raw elliptic curve Diffie-Hellman algorithm as well as * elliptic curve Diffie-Hellman followed by any supporter key derivation * algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, * 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key agreement algorithm identifier. */ #define PSA_ALG_IS_ECDH(alg) \ (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) /** Whether the specified algorithm encoding is a wildcard. * * Wildcard values may only be used to set the usage algorithm field in * a policy, not to perform an operation. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a wildcard algorithm encoding. * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for * an operation). * \return This macro may return either 0 or 1 if \c alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_WILDCARD(alg) \ (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ PSA_ALG_IS_MAC(alg) ? \ (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0 : \ PSA_ALG_IS_AEAD(alg) ? \ (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0 : \ (alg) == PSA_ALG_ANY_HASH) /** Get the hash used by a composite algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return The underlying hash algorithm if alg is a composite algorithm that * uses a hash algorithm. * * \return \c 0 if alg is not a composite algorithm that uses a hash. */ #define PSA_ALG_GET_HASH(alg) \ (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t) 0) : 0x02000000 | ((alg) & 0x000000ff)) /**@}*/ /** \defgroup key_lifetimes Key lifetimes * @{ */ /* Note that location and persistence level values are embedded in the * persistent key store, as part of key metadata. As a consequence, they * must not be changed (unless the storage format version changes). */ /** The default lifetime for volatile keys. * * A volatile key only exists as long as the identifier to it is not destroyed. * The key material is guaranteed to be erased on a power reset. * * A key with this lifetime is typically stored in the RAM area of the * PSA Crypto subsystem. However this is an implementation choice. * If an implementation stores data about the key in a non-volatile memory, * it must release all the resources associated with the key and erase the * key material if the calling application terminates. */ #define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t) 0x00000000) /** The default lifetime for persistent keys. * * A persistent key remains in storage until it is explicitly destroyed or * until the corresponding storage area is wiped. This specification does * not define any mechanism to wipe a storage area, but integrations may * provide their own mechanism (for example to perform a factory reset, * to prepare for device refurbishment, or to uninstall an application). * * This lifetime value is the default storage area for the calling * application. Integrations of Mbed TLS may support other persistent lifetimes. * See ::psa_key_lifetime_t for more information. */ #define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t) 0x00000001) /** The persistence level of volatile keys. * * See ::psa_key_persistence_t for more information. */ #define PSA_KEY_PERSISTENCE_VOLATILE ((psa_key_persistence_t) 0x00) /** The default persistence level for persistent keys. * * See ::psa_key_persistence_t for more information. */ #define PSA_KEY_PERSISTENCE_DEFAULT ((psa_key_persistence_t) 0x01) /** A persistence level indicating that a key is never destroyed. * * See ::psa_key_persistence_t for more information. */ #define PSA_KEY_PERSISTENCE_READ_ONLY ((psa_key_persistence_t) 0xff) #define PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) \ ((psa_key_persistence_t) ((lifetime) & 0x000000ff)) #define PSA_KEY_LIFETIME_GET_LOCATION(lifetime) \ ((psa_key_location_t) ((lifetime) >> 8)) /** Whether a key lifetime indicates that the key is volatile. * * A volatile key is automatically destroyed by the implementation when * the application instance terminates. In particular, a volatile key * is automatically destroyed on a power reset of the device. * * A key that is not volatile is persistent. Persistent keys are * preserved until the application explicitly destroys them or until an * implementation-specific device management event occurs (for example, * a factory reset). * * \param lifetime The lifetime value to query (value of type * ::psa_key_lifetime_t). * * \return \c 1 if the key is volatile, otherwise \c 0. */ #define PSA_KEY_LIFETIME_IS_VOLATILE(lifetime) \ (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \ PSA_KEY_PERSISTENCE_VOLATILE) /** Whether a key lifetime indicates that the key is read-only. * * Read-only keys cannot be created or destroyed through the PSA Crypto API. * They must be created through platform-specific means that bypass the API. * * Some platforms may offer ways to destroy read-only keys. For example, * consider a platform with multiple levels of privilege, where a * low-privilege application can use a key but is not allowed to destroy * it, and the platform exposes the key to the application with a read-only * lifetime. High-privilege code can destroy the key even though the * application sees the key as read-only. * * \param lifetime The lifetime value to query (value of type * ::psa_key_lifetime_t). * * \return \c 1 if the key is read-only, otherwise \c 0. */ #define PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime) \ (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \ PSA_KEY_PERSISTENCE_READ_ONLY) /** Construct a lifetime from a persistence level and a location. * * \param persistence The persistence level * (value of type ::psa_key_persistence_t). * \param location The location indicator * (value of type ::psa_key_location_t). * * \return The constructed lifetime value. */ #define PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(persistence, location) \ ((location) << 8 | (persistence)) /** The local storage area for persistent keys. * * This storage area is available on all systems that can store persistent * keys without delegating the storage to a third-party cryptoprocessor. * * See ::psa_key_location_t for more information. */ #define PSA_KEY_LOCATION_LOCAL_STORAGE ((psa_key_location_t) 0x000000) #define PSA_KEY_LOCATION_VENDOR_FLAG ((psa_key_location_t) 0x800000) /* Note that key identifier values are embedded in the * persistent key store, as part of key metadata. As a consequence, they * must not be changed (unless the storage format version changes). */ /** The null key identifier. */ /* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */ #define PSA_KEY_ID_NULL ((psa_key_id_t)0) /* *INDENT-ON* */ /** The minimum value for a key identifier chosen by the application. */ #define PSA_KEY_ID_USER_MIN ((psa_key_id_t) 0x00000001) /** The maximum value for a key identifier chosen by the application. */ #define PSA_KEY_ID_USER_MAX ((psa_key_id_t) 0x3fffffff) /** The minimum value for a key identifier chosen by the implementation. */ #define PSA_KEY_ID_VENDOR_MIN ((psa_key_id_t) 0x40000000) /** The maximum value for a key identifier chosen by the implementation. */ #define PSA_KEY_ID_VENDOR_MAX ((psa_key_id_t) 0x7fffffff) #if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) #define MBEDTLS_SVC_KEY_ID_INIT ((psa_key_id_t) 0) #define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) (id) #define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) (0) /** Utility to initialize a key identifier at runtime. * * \param unused Unused parameter. * \param key_id Identifier of the key. */ static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( unsigned int unused, psa_key_id_t key_id) { (void) unused; return key_id; } /** Compare two key identifiers. * * \param id1 First key identifier. * \param id2 Second key identifier. * * \return Non-zero if the two key identifier are equal, zero otherwise. */ static inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1, mbedtls_svc_key_id_t id2) { return id1 == id2; } /** Check whether a key identifier is null. * * \param key Key identifier. * * \return Non-zero if the key identifier is null, zero otherwise. */ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) { return key == 0; } #else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ #define MBEDTLS_SVC_KEY_ID_INIT ((mbedtls_svc_key_id_t){ 0, 0 }) #define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) ((id).MBEDTLS_PRIVATE(key_id)) #define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) ((id).MBEDTLS_PRIVATE(owner)) /** Utility to initialize a key identifier at runtime. * * \param owner_id Identifier of the key owner. * \param key_id Identifier of the key. */ static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( mbedtls_key_owner_id_t owner_id, psa_key_id_t key_id) { return (mbedtls_svc_key_id_t){ .MBEDTLS_PRIVATE(key_id) = key_id, .MBEDTLS_PRIVATE(owner) = owner_id }; } /** Compare two key identifiers. * * \param id1 First key identifier. * \param id2 Second key identifier. * * \return Non-zero if the two key identifier are equal, zero otherwise. */ static inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1, mbedtls_svc_key_id_t id2) { return (id1.MBEDTLS_PRIVATE(key_id) == id2.MBEDTLS_PRIVATE(key_id)) && mbedtls_key_owner_id_equal(id1.MBEDTLS_PRIVATE(owner), id2.MBEDTLS_PRIVATE(owner)); } /** Check whether a key identifier is null. * * \param key Key identifier. * * \return Non-zero if the key identifier is null, zero otherwise. */ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) { return key.MBEDTLS_PRIVATE(key_id) == 0; } #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ /**@}*/ /** \defgroup policy Key policies * @{ */ /* Note that key usage flags are embedded in the * persistent key store, as part of key metadata. As a consequence, they * must not be changed (unless the storage format version changes). */ /** Whether the key may be exported. * * A public key or the public part of a key pair may always be exported * regardless of the value of this permission flag. * * If a key does not have export permission, implementations shall not * allow the key to be exported in plain form from the cryptoprocessor, * whether through psa_export_key() or through a proprietary interface. * The key may however be exportable in a wrapped form, i.e. in a form * where it is encrypted by another key. */ #define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t) 0x00000001) /** Whether the key may be copied. * * This flag allows the use of psa_copy_key() to make a copy of the key * with the same policy or a more restrictive policy. * * For lifetimes for which the key is located in a secure element which * enforce the non-exportability of keys, copying a key outside the secure * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. * Copying the key inside the secure element is permitted with just * #PSA_KEY_USAGE_COPY if the secure element supports it. * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY * is sufficient to permit the copy. */ #define PSA_KEY_USAGE_COPY ((psa_key_usage_t) 0x00000002) /** Whether the key may be used to encrypt a message. * * This flag allows the key to be used for a symmetric encryption operation, * for an AEAD encryption-and-authentication operation, * or for an asymmetric encryption operation, * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the public key. */ #define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t) 0x00000100) /** Whether the key may be used to decrypt a message. * * This flag allows the key to be used for a symmetric decryption operation, * for an AEAD decryption-and-verification operation, * or for an asymmetric decryption operation, * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the private key. */ #define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t) 0x00000200) /** Whether the key may be used to sign a message. * * This flag allows the key to be used for a MAC calculation operation or for * an asymmetric message signature operation, if otherwise permitted by the * key’s type and policy. * * For a key pair, this concerns the private key. */ #define PSA_KEY_USAGE_SIGN_MESSAGE ((psa_key_usage_t) 0x00000400) /** Whether the key may be used to verify a message. * * This flag allows the key to be used for a MAC verification operation or for * an asymmetric message signature verification operation, if otherwise * permitted by the key’s type and policy. * * For a key pair, this concerns the public key. */ #define PSA_KEY_USAGE_VERIFY_MESSAGE ((psa_key_usage_t) 0x00000800) /** Whether the key may be used to sign a message. * * This flag allows the key to be used for a MAC calculation operation * or for an asymmetric signature operation, * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the private key. */ #define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t) 0x00001000) /** Whether the key may be used to verify a message signature. * * This flag allows the key to be used for a MAC verification operation * or for an asymmetric signature verification operation, * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the public key. */ #define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t) 0x00002000) /** Whether the key may be used to derive other keys or produce a password * hash. * * This flag allows the key to be used for a key derivation operation or for * a key agreement operation, if otherwise permitted by the key's type and * policy. * * If this flag is present on all keys used in calls to * psa_key_derivation_input_key() for a key derivation operation, then it * permits calling psa_key_derivation_output_bytes() or * psa_key_derivation_output_key() at the end of the operation. */ #define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t) 0x00004000) /** Whether the key may be used to verify the result of a key derivation, * including password hashing. * * This flag allows the key to be used: * * This flag allows the key to be used in a key derivation operation, if * otherwise permitted by the key's type and policy. * * If this flag is present on all keys used in calls to * psa_key_derivation_input_key() for a key derivation operation, then it * permits calling psa_key_derivation_verify_bytes() or * psa_key_derivation_verify_key() at the end of the operation. */ #define PSA_KEY_USAGE_VERIFY_DERIVATION ((psa_key_usage_t) 0x00008000) /**@}*/ /** \defgroup derivation Key derivation * @{ */ /* Key input steps are not embedded in the persistent storage, so you can * change them if needed: it's only an ABI change. */ /** A secret input for key derivation. * * This should be a key of type #PSA_KEY_TYPE_DERIVE * (passed to psa_key_derivation_input_key()) * or the shared secret resulting from a key agreement * (obtained via psa_key_derivation_key_agreement()). * * The secret can also be a direct input (passed to * key_derivation_input_bytes()). In this case, the derivation operation * may not be used to derive keys: the operation will only allow * psa_key_derivation_output_bytes(), * psa_key_derivation_verify_bytes(), or * psa_key_derivation_verify_key(), but not * psa_key_derivation_output_key(). */ #define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t) 0x0101) /** A low-entropy secret input for password hashing / key stretching. * * This is usually a key of type #PSA_KEY_TYPE_PASSWORD (passed to * psa_key_derivation_input_key()) or a direct input (passed to * psa_key_derivation_input_bytes()) that is a password or passphrase. It can * also be high-entropy secret such as a key of type #PSA_KEY_TYPE_DERIVE or * the shared secret resulting from a key agreement. * * The secret can also be a direct input (passed to * key_derivation_input_bytes()). In this case, the derivation operation * may not be used to derive keys: the operation will only allow * psa_key_derivation_output_bytes(), * psa_key_derivation_verify_bytes(), or * psa_key_derivation_verify_key(), but not * psa_key_derivation_output_key(). */ #define PSA_KEY_DERIVATION_INPUT_PASSWORD ((psa_key_derivation_step_t) 0x0102) /** A high-entropy additional secret input for key derivation. * * This is typically the shared secret resulting from a key agreement obtained * via `psa_key_derivation_key_agreement()`. It may alternatively be a key of * type `PSA_KEY_TYPE_DERIVE` passed to `psa_key_derivation_input_key()`, or * a direct input passed to `psa_key_derivation_input_bytes()`. */ #define PSA_KEY_DERIVATION_INPUT_OTHER_SECRET \ ((psa_key_derivation_step_t) 0x0103) /** A label for key derivation. * * This should be a direct input. * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. */ #define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t) 0x0201) /** A salt for key derivation. * * This should be a direct input. * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA or * #PSA_KEY_TYPE_PEPPER. */ #define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t) 0x0202) /** An information string for key derivation. * * This should be a direct input. * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. */ #define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t) 0x0203) /** A seed for key derivation. * * This should be a direct input. * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. */ #define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t) 0x0204) /** A cost parameter for password hashing / key stretching. * * This must be a direct input, passed to psa_key_derivation_input_integer(). */ #define PSA_KEY_DERIVATION_INPUT_COST ((psa_key_derivation_step_t) 0x0205) /**@}*/ /** \defgroup helper_macros Helper macros * @{ */ /* Helper macros */ /** Check if two AEAD algorithm identifiers refer to the same AEAD algorithm * regardless of the tag length they encode. * * \param aead_alg_1 An AEAD algorithm identifier. * \param aead_alg_2 An AEAD algorithm identifier. * * \return 1 if both identifiers refer to the same AEAD algorithm, * 0 otherwise. * Unspecified if neither \p aead_alg_1 nor \p aead_alg_2 are * a supported AEAD algorithm. */ #define MBEDTLS_PSA_ALG_AEAD_EQUAL(aead_alg_1, aead_alg_2) \ (!(((aead_alg_1) ^ (aead_alg_2)) & \ ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG))) /**@}*/ /**@}*/ /** \defgroup interruptible Interruptible operations * @{ */ /** Maximum value for use with \c psa_interruptible_set_max_ops() to determine * the maximum number of ops allowed to be executed by an interruptible * function in a single call. */ #define PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED UINT32_MAX /**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ webfakes/src/mbedtls/include/psa/crypto_adjust_auto_enabled.h0000644000176200001440000000214514740737024024247 0ustar liggesusers/** * \file psa/crypto_adjust_auto_enabled.h * \brief Adjust PSA configuration: enable always-on features * * This is an internal header. Do not include it directly. * * Always enable certain features which require a negligible amount of code * to implement, to avoid some edge cases in the configuration combinatorics. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ADJUST_AUTO_ENABLED_H #define PSA_CRYPTO_ADJUST_AUTO_ENABLED_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ #define PSA_WANT_KEY_TYPE_DERIVE 1 #define PSA_WANT_KEY_TYPE_PASSWORD 1 #define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 #define PSA_WANT_KEY_TYPE_RAW_DATA 1 #endif /* PSA_CRYPTO_ADJUST_AUTO_ENABLED_H */ webfakes/src/mbedtls/include/psa/crypto_adjust_config_dependencies.h0000644000176200001440000000374014740737024025602 0ustar liggesusers/** * \file psa/crypto_adjust_config_dependencies.h * \brief Adjust PSA configuration by resolving some dependencies. * * This is an internal header. Do not include it directly. * * See docs/proposed/psa-conditional-inclusion-c.md. * If the Mbed TLS implementation of a cryptographic mechanism A depends on a * cryptographic mechanism B then if the cryptographic mechanism A is enabled * and not accelerated enable B. Note that if A is enabled and accelerated, it * is not necessary to enable B for A support. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H #define PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ #if (defined(PSA_WANT_ALG_TLS12_PRF) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)) || \ (defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)) || \ (defined(PSA_WANT_ALG_HKDF) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)) || \ (defined(PSA_WANT_ALG_HKDF_EXTRACT) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT)) || \ (defined(PSA_WANT_ALG_HKDF_EXPAND) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND)) || \ (defined(PSA_WANT_ALG_PBKDF2_HMAC) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC)) #define PSA_WANT_ALG_HMAC 1 #define PSA_WANT_KEY_TYPE_HMAC 1 #endif #if (defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128)) #define PSA_WANT_KEY_TYPE_AES 1 #define PSA_WANT_ALG_CMAC 1 #endif #endif /* PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H */ webfakes/src/mbedtls/include/psa/crypto_platform.h0000644000176200001440000000674214740737024022106 0ustar liggesusers/** * \file psa/crypto_platform.h * * \brief PSA cryptography module: Mbed TLS platform definitions * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * This file contains platform-dependent type definitions. * * In implementations with isolation between the application and the * cryptography module, implementers should take care to ensure that * the definitions that are exposed to applications match what the * module implements. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_PLATFORM_H #define PSA_CRYPTO_PLATFORM_H #include "mbedtls/private_access.h" /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" /* PSA requires several types which C99 provides in stdint.h. */ #include #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) /* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA * partition identifier. * * The function psa_its_identifier_of_slot() in psa_crypto_storage.c that * translates a key identifier to a key storage file name assumes that * mbedtls_key_owner_id_t is a 32-bit integer. This function thus needs * reworking if mbedtls_key_owner_id_t is not defined as a 32-bit integer * here anymore. */ typedef int32_t mbedtls_key_owner_id_t; /** Compare two key owner identifiers. * * \param id1 First key owner identifier. * \param id2 Second key owner identifier. * * \return Non-zero if the two key owner identifiers are equal, zero otherwise. */ static inline int mbedtls_key_owner_id_equal(mbedtls_key_owner_id_t id1, mbedtls_key_owner_id_t id2) { return id1 == id2; } #endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ /* * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM * (Secure Partition Manager) integration which separates the code into two * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing * Environment). When building for the SPE, an additional header file should be * included. */ #if defined(MBEDTLS_PSA_CRYPTO_SPM) #define PSA_CRYPTO_SECURE 1 #include "crypto_spe.h" #endif // MBEDTLS_PSA_CRYPTO_SPM #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) /** The type of the context passed to mbedtls_psa_external_get_random(). * * Mbed TLS initializes the context to all-bits-zero before calling * mbedtls_psa_external_get_random() for the first time. * * The definition of this type in the Mbed TLS source code is for * demonstration purposes. Implementers of mbedtls_psa_external_get_random() * are expected to replace it with a custom definition. */ typedef struct { uintptr_t MBEDTLS_PRIVATE(opaque)[2]; } mbedtls_psa_external_random_context_t; #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) /** The type of the client handle used in context structures * * When a client view of the multipart context structures is required, * this handle is used to keep a mapping with the service side of the * context which contains the actual data. */ typedef uint32_t mbedtls_psa_client_handle_t; #endif #endif /* PSA_CRYPTO_PLATFORM_H */ webfakes/src/mbedtls/include/psa/crypto_sizes.h0000644000176200001440000015617014740737024021420 0ustar liggesusers/** * \file psa/crypto_sizes.h * * \brief PSA cryptography module: Mbed TLS buffer size macros * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * This file contains the definitions of macros that are useful to * compute buffer sizes. The signatures and semantics of these macros * are standardized, but the definitions are not, because they depend on * the available algorithms and, in some cases, on permitted tolerances * on buffer sizes. * * In implementations with isolation between the application and the * cryptography module, implementers should take care to ensure that * the definitions that are exposed to applications match what the * module implements. * * Macros that compute sizes whose values do not depend on the * implementation are in crypto.h. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SIZES_H #define PSA_CRYPTO_SIZES_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" #define PSA_BITS_TO_BYTES(bits) (((bits) + 7u) / 8u) #define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8u) #define PSA_MAX_OF_THREE(a, b, c) ((a) <= (b) ? (b) <= (c) ? \ (c) : (b) : (a) <= (c) ? (c) : (a)) #define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ (((length) + (block_size) - 1) / (block_size) * (block_size)) /** The size of the output of psa_hash_finish(), in bytes. * * This is also the hash size that psa_hash_verify() expects. * * \param alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a * hash algorithm). * * \return The hash size for the specified hash algorithm. * If the hash algorithm is not recognized, return 0. */ #define PSA_HASH_LENGTH(alg) \ ( \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64u : \ 0u) /** The input block size of a hash algorithm, in bytes. * * Hash algorithms process their input data in blocks. Hash operations will * retain any partial blocks until they have enough input to fill the block or * until the operation is finished. * This affects the output from psa_hash_suspend(). * * \param alg A hash algorithm (\c PSA_ALG_XXX value such that * PSA_ALG_IS_HASH(\p alg) is true). * * \return The block size in bytes for the specified hash algorithm. * If the hash algorithm is not recognized, return 0. * An implementation can return either 0 or the correct size for a * hash algorithm that it recognizes, but does not support. */ #define PSA_HASH_BLOCK_LENGTH(alg) \ ( \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72u : \ 0u) /** \def PSA_HASH_MAX_SIZE * * Maximum size of a hash. * * This macro expands to a compile-time constant integer. This value * is the maximum size of a hash in bytes. */ /* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-224, * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for * HMAC-SHA3-512. */ /* Note: PSA_HASH_MAX_SIZE should be kept in sync with MBEDTLS_MD_MAX_SIZE, * see the note on MBEDTLS_MD_MAX_SIZE for details. */ #if defined(PSA_WANT_ALG_SHA3_224) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 144u #elif defined(PSA_WANT_ALG_SHA3_256) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 136u #elif defined(PSA_WANT_ALG_SHA_512) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u #elif defined(PSA_WANT_ALG_SHA_384) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u #elif defined(PSA_WANT_ALG_SHA3_384) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 104u #elif defined(PSA_WANT_ALG_SHA3_512) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 72u #elif defined(PSA_WANT_ALG_SHA_256) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u #elif defined(PSA_WANT_ALG_SHA_224) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u #else /* SHA-1 or smaller */ #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u #endif #if defined(PSA_WANT_ALG_SHA_512) || defined(PSA_WANT_ALG_SHA3_512) #define PSA_HASH_MAX_SIZE 64u #elif defined(PSA_WANT_ALG_SHA_384) || defined(PSA_WANT_ALG_SHA3_384) #define PSA_HASH_MAX_SIZE 48u #elif defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA3_256) #define PSA_HASH_MAX_SIZE 32u #elif defined(PSA_WANT_ALG_SHA_224) || defined(PSA_WANT_ALG_SHA3_224) #define PSA_HASH_MAX_SIZE 28u #else /* SHA-1 or smaller */ #define PSA_HASH_MAX_SIZE 20u #endif /** \def PSA_MAC_MAX_SIZE * * Maximum size of a MAC. * * This macro expands to a compile-time constant integer. This value * is the maximum size of a MAC in bytes. */ /* All non-HMAC MACs have a maximum size that's smaller than the * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ /* Note that the encoding of truncated MAC algorithms limits this value * to 64 bytes. */ #define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE /** The length of a tag for an AEAD algorithm, in bytes. * * This macro can be used to allocate a buffer of sufficient size to store the * tag output from psa_aead_finish(). * * See also #PSA_AEAD_TAG_MAX_SIZE. * * \param key_type The type of the AEAD key. * \param key_bits The size of the AEAD key in bits. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \return The tag length for the specified algorithm and key. * If the AEAD algorithm does not have an identified * tag that can be distinguished from the rest of * the ciphertext, return 0. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ ((void) (key_bits), 0u)) /** The maximum tag size for all supported AEAD algorithms, in bytes. * * See also #PSA_AEAD_TAG_LENGTH(\p key_type, \p key_bits, \p alg). */ #define PSA_AEAD_TAG_MAX_SIZE 16u /* The maximum size of an RSA key on this implementation, in bits. * This is a vendor-specific macro. * * Mbed TLS does not set a hard limit on the size of RSA keys: any key * whose parameters fit in a bignum is accepted. However large keys can * induce a large memory usage and long computation times. Unlike other * auxiliary macros in this file and in crypto.h, which reflect how the * library is configured, this macro defines how the library is * configured. This implementation refuses to import or generate an * RSA key whose size is larger than the value defined here. * * Note that an implementation may set different size limits for different * operations, and does not need to accept all key sizes up to the limit. */ #define PSA_VENDOR_RSA_MAX_KEY_BITS 4096u /* The minimum size of an RSA key on this implementation, in bits. * This is a vendor-specific macro. * * Limits RSA key generation to a minimum due to avoid accidental misuse. * This value cannot be less than 128 bits. */ #if defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS) #define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS MBEDTLS_RSA_GEN_KEY_MIN_BITS #else #define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS 1024 #endif /* The maximum size of an DH key on this implementation, in bits. * This is a vendor-specific macro.*/ #if defined(PSA_WANT_DH_RFC7919_8192) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 8192u #elif defined(PSA_WANT_DH_RFC7919_6144) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 6144u #elif defined(PSA_WANT_DH_RFC7919_4096) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 4096u #elif defined(PSA_WANT_DH_RFC7919_3072) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 3072u #elif defined(PSA_WANT_DH_RFC7919_2048) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 2048u #else #define PSA_VENDOR_FFDH_MAX_KEY_BITS 0u #endif /* The maximum size of an ECC key on this implementation, in bits. * This is a vendor-specific macro. */ #if defined(PSA_WANT_ECC_SECP_R1_521) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 521u #elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 512u #elif defined(PSA_WANT_ECC_MONTGOMERY_448) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 448u #elif defined(PSA_WANT_ECC_SECP_R1_384) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u #elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u #elif defined(PSA_WANT_ECC_SECP_R1_256) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u #elif defined(PSA_WANT_ECC_SECP_K1_256) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u #elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u #elif defined(PSA_WANT_ECC_MONTGOMERY_255) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 255u #elif defined(PSA_WANT_ECC_SECP_R1_224) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u #elif defined(PSA_WANT_ECC_SECP_K1_224) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u #elif defined(PSA_WANT_ECC_SECP_R1_192) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u #elif defined(PSA_WANT_ECC_SECP_K1_192) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u #else #define PSA_VENDOR_ECC_MAX_CURVE_BITS 0u #endif /** This macro returns the maximum supported length of the PSK for the * TLS-1.2 PSK-to-MS key derivation * (#PSA_ALG_TLS12_PSK_TO_MS(\c hash_alg)). * * The maximum supported length does not depend on the chosen hash algorithm. * * Quoting RFC 4279, Sect 5.3: * TLS implementations supporting these ciphersuites MUST support * arbitrary PSK identities up to 128 octets in length, and arbitrary * PSKs up to 64 octets in length. Supporting longer identities and * keys is RECOMMENDED. * * Therefore, no implementation should define a value smaller than 64 * for #PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE. */ #define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128u /* The expected size of input passed to psa_tls12_ecjpake_to_pms_input, * which is expected to work with P-256 curve only. */ #define PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE 65u /* The size of a serialized K.X coordinate to be used in * psa_tls12_ecjpake_to_pms_input. This function only accepts the P-256 * curve. */ #define PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE 32u /* The maximum number of iterations for PBKDF2 on this implementation, in bits. * This is a vendor-specific macro. This can be configured if necessary */ #define PSA_VENDOR_PBKDF2_MAX_ITERATIONS 0xffffffffU /** The maximum size of a block cipher. */ #define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16u /** The size of the output of psa_mac_sign_finish(), in bytes. * * This is also the MAC size that psa_mac_verify_finish() expects. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type The type of the MAC key. * \param key_bits The size of the MAC key in bits. * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_MAC(\p alg) is true). * * \return The MAC size for the specified algorithm with * the specified key parameters. * \return 0 if the MAC algorithm is not recognized. * \return Either 0 or the correct size for a MAC algorithm that * the implementation recognizes, but does not support. * \return Unspecified if the key parameters are not consistent * with the algorithm. */ #define PSA_MAC_LENGTH(key_type, key_bits, alg) \ ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ PSA_ALG_IS_HMAC(alg) ? PSA_HASH_LENGTH(PSA_ALG_HMAC_GET_HASH(alg)) : \ PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ ((void) (key_type), (void) (key_bits), 0u)) /** The maximum size of the output of psa_aead_encrypt(), in bytes. * * If the size of the ciphertext buffer is at least this large, it is * guaranteed that psa_aead_encrypt() will not fail due to an * insufficient buffer size. Depending on the algorithm, the actual size of * the ciphertext may be smaller. * * See also #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is * compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param plaintext_length Size of the plaintext in bytes. * * \return The AEAD ciphertext size for the specified * algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext_length) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ (plaintext_length) + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ 0u) /** A sufficient output buffer size for psa_aead_encrypt(), for any of the * supported key types and AEAD algorithms. * * If the size of the ciphertext buffer is at least this large, it is guaranteed * that psa_aead_encrypt() will not fail due to an insufficient buffer size. * * \note This macro returns a compile-time constant if its arguments are * compile-time constants. * * See also #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg, * \p plaintext_length). * * \param plaintext_length Size of the plaintext in bytes. * * \return A sufficient output buffer size for any of the * supported key types and AEAD algorithms. * */ #define PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(plaintext_length) \ ((plaintext_length) + PSA_AEAD_TAG_MAX_SIZE) /** The maximum size of the output of psa_aead_decrypt(), in bytes. * * If the size of the plaintext buffer is at least this large, it is * guaranteed that psa_aead_decrypt() will not fail due to an * insufficient buffer size. Depending on the algorithm, the actual size of * the plaintext may be smaller. * * See also #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is * compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param ciphertext_length Size of the plaintext in bytes. * * \return The AEAD ciphertext size for the specified * algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext_length) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ (ciphertext_length) > PSA_ALG_AEAD_GET_TAG_LENGTH(alg) ? \ (ciphertext_length) - PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ 0u) /** A sufficient output buffer size for psa_aead_decrypt(), for any of the * supported key types and AEAD algorithms. * * If the size of the plaintext buffer is at least this large, it is guaranteed * that psa_aead_decrypt() will not fail due to an insufficient buffer size. * * \note This macro returns a compile-time constant if its arguments are * compile-time constants. * * See also #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg, * \p ciphertext_length). * * \param ciphertext_length Size of the ciphertext in bytes. * * \return A sufficient output buffer size for any of the * supported key types and AEAD algorithms. * */ #define PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(ciphertext_length) \ (ciphertext_length) /** The default nonce size for an AEAD algorithm, in bytes. * * This macro can be used to allocate a buffer of sufficient size to * store the nonce output from #psa_aead_generate_nonce(). * * See also #PSA_AEAD_NONCE_MAX_SIZE. * * \note This is not the maximum size of nonce supported as input to * #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(), * just the default size that is generated by #psa_aead_generate_nonce(). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is compatible with * algorithm \p alg. * * \param alg An AEAD algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \return The default nonce size for the specified key type and algorithm. * If the key type or AEAD algorithm is not recognized, * or the parameters are incompatible, return 0. */ #define PSA_AEAD_NONCE_LENGTH(key_type, alg) \ (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) == 16 ? \ MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) ? 13u : \ MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) ? 12u : \ 0u : \ (key_type) == PSA_KEY_TYPE_CHACHA20 && \ MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12u : \ 0u) /** The maximum default nonce size among all supported pairs of key types and * AEAD algorithms, in bytes. * * This is equal to or greater than any value that #PSA_AEAD_NONCE_LENGTH() * may return. * * \note This is not the maximum size of nonce supported as input to * #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(), * just the largest size that may be generated by * #psa_aead_generate_nonce(). */ #define PSA_AEAD_NONCE_MAX_SIZE 13u /** A sufficient output buffer size for psa_aead_update(). * * If the size of the output buffer is at least this large, it is * guaranteed that psa_aead_update() will not fail due to an * insufficient buffer size. The actual size of the output may be smaller * in any given call. * * See also #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is * compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param input_length Size of the input in bytes. * * \return A sufficient output buffer size for the specified * algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ /* For all the AEAD modes defined in this specification, it is possible * to emit output without delay. However, hardware may not always be * capable of this. So for modes based on a block cipher, allow the * implementation to delay the output until it has a full block. */ #define PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), (input_length)) : \ (input_length) : \ 0u) /** A sufficient output buffer size for psa_aead_update(), for any of the * supported key types and AEAD algorithms. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_aead_update() will not fail due to an insufficient buffer size. * * See also #PSA_AEAD_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). * * \param input_length Size of the input in bytes. */ #define PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(input_length) \ (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, (input_length))) /** A sufficient ciphertext buffer size for psa_aead_finish(). * * If the size of the ciphertext buffer is at least this large, it is * guaranteed that psa_aead_finish() will not fail due to an * insufficient ciphertext buffer size. The actual size of the output may * be smaller in any given call. * * See also #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE. * * \param key_type A symmetric key type that is compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \return A sufficient ciphertext buffer size for the * specified algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ 0u) /** A sufficient ciphertext buffer size for psa_aead_finish(), for any of the * supported key types and AEAD algorithms. * * See also #PSA_AEAD_FINISH_OUTPUT_SIZE(\p key_type, \p alg). */ #define PSA_AEAD_FINISH_OUTPUT_MAX_SIZE (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) /** A sufficient plaintext buffer size for psa_aead_verify(). * * If the size of the plaintext buffer is at least this large, it is * guaranteed that psa_aead_verify() will not fail due to an * insufficient plaintext buffer size. The actual size of the output may * be smaller in any given call. * * See also #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE. * * \param key_type A symmetric key type that is * compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \return A sufficient plaintext buffer size for the * specified algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ 0u) /** A sufficient plaintext buffer size for psa_aead_verify(), for any of the * supported key types and AEAD algorithms. * * See also #PSA_AEAD_VERIFY_OUTPUT_SIZE(\p key_type, \p alg). */ #define PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) #define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ (PSA_ALG_IS_RSA_OAEP(alg) ? \ 2u * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1u : \ 11u /*PKCS#1v1.5*/) /** * \brief ECDSA signature size for a given curve bit size * * \param curve_bits Curve size in bits. * \return Signature size in bytes. * * \note This macro returns a compile-time constant if its argument is one. */ #define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ (PSA_BITS_TO_BYTES(curve_bits) * 2u) /** Sufficient signature buffer size for psa_sign_hash(). * * This macro returns a sufficient buffer size for a signature using a key * of the specified type and size, with the specified algorithm. * Note that the actual size of the signature may be smaller * (some algorithms produce a variable-size signature). * * \warning This function may call its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type An asymmetric key type (this may indifferently be a * key pair type or a public key type). * \param key_bits The size of the key in bits. * \param alg The signature algorithm. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_sign_hash() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported, * return either a sensible size or 0. * If the parameters are not valid, the * return value is unspecified. */ #define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ ((void) alg, 0u)) #define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) /** \def PSA_SIGNATURE_MAX_SIZE * * Maximum size of an asymmetric signature. * * This macro expands to a compile-time constant integer. This value * is the maximum size of a signature in bytes. */ #define PSA_SIGNATURE_MAX_SIZE 1 #if (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)) && \ (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE > PSA_SIGNATURE_MAX_SIZE) #undef PSA_SIGNATURE_MAX_SIZE #define PSA_SIGNATURE_MAX_SIZE PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE #endif #if (defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) || defined(PSA_WANT_ALG_RSA_PSS)) && \ (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_SIGNATURE_MAX_SIZE) #undef PSA_SIGNATURE_MAX_SIZE #define PSA_SIGNATURE_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) #endif /** Sufficient output buffer size for psa_asymmetric_encrypt(). * * This macro returns a sufficient buffer size for a ciphertext produced using * a key of the specified type and size, with the specified algorithm. * Note that the actual size of the ciphertext may be smaller, depending * on the algorithm. * * \warning This function may call its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type An asymmetric key type (this may indifferently be a * key pair type or a public key type). * \param key_bits The size of the key in bits. * \param alg The asymmetric encryption algorithm. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_asymmetric_encrypt() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported, * return either a sensible size or 0. * If the parameters are not valid, the * return value is unspecified. */ #define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? \ ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \ 0u) /** A sufficient output buffer size for psa_asymmetric_encrypt(), for any * supported asymmetric encryption. * * See also #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg). */ /* This macro assumes that RSA is the only supported asymmetric encryption. */ #define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE \ (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)) /** Sufficient output buffer size for psa_asymmetric_decrypt(). * * This macro returns a sufficient buffer size for a plaintext produced using * a key of the specified type and size, with the specified algorithm. * Note that the actual size of the plaintext may be smaller, depending * on the algorithm. * * \warning This function may call its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type An asymmetric key type (this may indifferently be a * key pair type or a public key type). * \param key_bits The size of the key in bits. * \param alg The asymmetric encryption algorithm. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_asymmetric_decrypt() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported, * return either a sensible size or 0. * If the parameters are not valid, the * return value is unspecified. */ #define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? \ PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ 0u) /** A sufficient output buffer size for psa_asymmetric_decrypt(), for any * supported asymmetric decryption. * * This macro assumes that RSA is the only supported asymmetric encryption. * * See also #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg). */ #define PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE \ (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)) /* Maximum size of the ASN.1 encoding of an INTEGER with the specified * number of bits. * * This definition assumes that bits <= 2^19 - 9 so that the length field * is at most 3 bytes. The length of the encoding is the length of the * bit string padded to a whole number of bytes plus: * - 1 type byte; * - 1 to 3 length bytes; * - 0 to 1 bytes of leading 0 due to the sign bit. */ #define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ ((bits) / 8u + 5u) /* Maximum size of the export encoding of an RSA public key. * Assumes that the public exponent is less than 2^32. * * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER } -- e * * - 4 bytes of SEQUENCE overhead; * - n : INTEGER; * - 7 bytes for the public exponent. */ #define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11u) /* Maximum size of the export encoding of an RSA key pair. * Assumes that the public exponent is less than 2^32 and that the size * difference between the two primes is at most 1 bit. * * RSAPrivateKey ::= SEQUENCE { * version Version, -- 0 * modulus INTEGER, -- N-bit * publicExponent INTEGER, -- 32-bit * privateExponent INTEGER, -- N-bit * prime1 INTEGER, -- N/2-bit * prime2 INTEGER, -- N/2-bit * exponent1 INTEGER, -- N/2-bit * exponent2 INTEGER, -- N/2-bit * coefficient INTEGER, -- N/2-bit * } * * - 4 bytes of SEQUENCE overhead; * - 3 bytes of version; * - 7 half-size INTEGERs plus 2 full-size INTEGERs, * overapproximated as 9 half-size INTEGERS; * - 7 bytes for the public exponent. */ #define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ (9u * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2u + 1u) + 14u) /* Maximum size of the export encoding of a DSA public key. * * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } -- contains DSAPublicKey * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters Dss-Params } -- SEQUENCE of 3 INTEGERs * DSAPublicKey ::= INTEGER -- public key, Y * * - 3 * 4 bytes of SEQUENCE overhead; * - 1 + 1 + 7 bytes of algorithm (DSA OID); * - 4 bytes of BIT STRING overhead; * - 3 full-size INTEGERs (p, g, y); * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). */ #define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 59u) /* Maximum size of the export encoding of a DSA key pair. * * DSAPrivateKey ::= SEQUENCE { * version Version, -- 0 * prime INTEGER, -- p * subprime INTEGER, -- q * generator INTEGER, -- g * public INTEGER, -- y * private INTEGER, -- x * } * * - 4 bytes of SEQUENCE overhead; * - 3 bytes of version; * - 3 full-size INTEGERs (p, g, y); * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). */ #define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 75u) /* Maximum size of the export encoding of an ECC public key. * * The representation of an ECC public key is: * - The byte 0x04; * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; * - where m is the bit size associated with the curve. * * - 1 byte + 2 * point size. */ #define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ (2u * PSA_BITS_TO_BYTES(key_bits) + 1u) /* Maximum size of the export encoding of an ECC key pair. * * An ECC key pair is represented by the secret value. */ #define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_BITS_TO_BYTES(key_bits)) /* Maximum size of the export encoding of an DH key pair. * * An DH key pair is represented by the secret value. */ #define PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_BITS_TO_BYTES(key_bits)) /* Maximum size of the export encoding of an DH public key. */ #define PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(key_bits) \ (PSA_BITS_TO_BYTES(key_bits)) /** Sufficient output buffer size for psa_export_key() or * psa_export_public_key(). * * This macro returns a compile-time constant if its arguments are * compile-time constants. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * The following code illustrates how to allocate enough memory to export * a key by querying the key type and size at runtime. * \code{c} * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * psa_status_t status; * status = psa_get_key_attributes(key, &attributes); * if (status != PSA_SUCCESS) handle_error(...); * psa_key_type_t key_type = psa_get_key_type(&attributes); * size_t key_bits = psa_get_key_bits(&attributes); * size_t buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits); * psa_reset_key_attributes(&attributes); * uint8_t *buffer = malloc(buffer_size); * if (buffer == NULL) handle_error(...); * size_t buffer_length; * status = psa_export_key(key, buffer, buffer_size, &buffer_length); * if (status != PSA_SUCCESS) handle_error(...); * \endcode * * \param key_type A supported key type. * \param key_bits The size of the key in bits. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_export_key() or psa_export_public_key() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported, * return either a sensible size or 0. * If the parameters are not valid, the return value is unspecified. */ #define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits) \ (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ 0u) /** Sufficient output buffer size for psa_export_public_key(). * * This macro returns a compile-time constant if its arguments are * compile-time constants. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * The following code illustrates how to allocate enough memory to export * a public key by querying the key type and size at runtime. * \code{c} * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * psa_status_t status; * status = psa_get_key_attributes(key, &attributes); * if (status != PSA_SUCCESS) handle_error(...); * psa_key_type_t key_type = psa_get_key_type(&attributes); * size_t key_bits = psa_get_key_bits(&attributes); * size_t buffer_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits); * psa_reset_key_attributes(&attributes); * uint8_t *buffer = malloc(buffer_size); * if (buffer == NULL) handle_error(...); * size_t buffer_length; * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); * if (status != PSA_SUCCESS) handle_error(...); * \endcode * * \param key_type A public key or key pair key type. * \param key_bits The size of the key in bits. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_export_public_key() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not * supported, return either a sensible size or 0. * If the parameters are not valid, * the return value is unspecified. * * If the parameters are valid and supported, * return the same result as * #PSA_EXPORT_KEY_OUTPUT_SIZE( * \p #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\p key_type), * \p key_bits). */ #define PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ 0u) /** Sufficient buffer size for exporting any asymmetric key pair. * * This macro expands to a compile-time constant integer. This value is * a sufficient buffer size when calling psa_export_key() to export any * asymmetric key pair, regardless of the exact key type and key size. * * See also #PSA_EXPORT_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). */ #define PSA_EXPORT_KEY_PAIR_MAX_SIZE 1 #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \ (PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \ PSA_EXPORT_KEY_PAIR_MAX_SIZE) #undef PSA_EXPORT_KEY_PAIR_MAX_SIZE #define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) && \ (PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ PSA_EXPORT_KEY_PAIR_MAX_SIZE) #undef PSA_EXPORT_KEY_PAIR_MAX_SIZE #define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \ (PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \ PSA_EXPORT_KEY_PAIR_MAX_SIZE) #undef PSA_EXPORT_KEY_PAIR_MAX_SIZE #define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) #endif /** Sufficient buffer size for exporting any asymmetric public key. * * This macro expands to a compile-time constant integer. This value is * a sufficient buffer size when calling psa_export_key() or * psa_export_public_key() to export any asymmetric public key, * regardless of the exact key type and key size. * * See also #PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). */ #define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE 1 #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ (PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \ PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) #undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) #endif #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) && \ (PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) #undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) #endif #if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \ (PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \ PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) #undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) #endif /** Sufficient output buffer size for psa_raw_key_agreement(). * * This macro returns a compile-time constant if its arguments are * compile-time constants. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE. * * \param key_type A supported key type. * \param key_bits The size of the key in bits. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_raw_key_agreement() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that * is not supported, return either a sensible size or 0. * If the parameters are not valid, * the return value is unspecified. */ #define PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, key_bits) \ ((PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) || \ PSA_KEY_TYPE_IS_DH_KEY_PAIR(key_type)) ? PSA_BITS_TO_BYTES(key_bits) : 0u) /** Maximum size of the output from psa_raw_key_agreement(). * * This macro expands to a compile-time constant integer. This value is the * maximum size of the output any raw key agreement algorithm, in bytes. * * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\p key_type, \p key_bits). */ #define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE 1 #if defined(PSA_WANT_ALG_ECDH) && \ (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE) #undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE #define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) #endif #if defined(PSA_WANT_ALG_FFDH) && \ (PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE) #undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE #define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) #endif /** The default IV size for a cipher algorithm, in bytes. * * The IV that is generated as part of a call to #psa_cipher_encrypt() is always * the default IV length for the algorithm. * * This macro can be used to allocate a buffer of sufficient size to * store the IV output from #psa_cipher_generate_iv() when using * a multi-part cipher operation. * * See also #PSA_CIPHER_IV_MAX_SIZE. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is compatible with algorithm \p alg. * * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that #PSA_ALG_IS_CIPHER(\p alg) is true). * * \return The default IV size for the specified key type and algorithm. * If the algorithm does not use an IV, return 0. * If the key type or cipher algorithm is not recognized, * or the parameters are incompatible, return 0. */ #define PSA_CIPHER_IV_LENGTH(key_type, alg) \ (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1 && \ ((alg) == PSA_ALG_CTR || \ (alg) == PSA_ALG_CFB || \ (alg) == PSA_ALG_OFB || \ (alg) == PSA_ALG_XTS || \ (alg) == PSA_ALG_CBC_NO_PADDING || \ (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ (key_type) == PSA_KEY_TYPE_CHACHA20 && \ (alg) == PSA_ALG_STREAM_CIPHER ? 12u : \ (alg) == PSA_ALG_CCM_STAR_NO_TAG ? 13u : \ 0u) /** The maximum IV size for all supported cipher algorithms, in bytes. * * See also #PSA_CIPHER_IV_LENGTH(). */ #define PSA_CIPHER_IV_MAX_SIZE 16u /** The maximum size of the output of psa_cipher_encrypt(), in bytes. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_encrypt() will not fail due to an insufficient buffer size. * Depending on the algorithm, the actual size of the output might be smaller. * * See also #PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(\p input_length). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is compatible with algorithm * alg. * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param input_length Size of the input in bytes. * * \return A sufficient output size for the specified key type and * algorithm. If the key type or cipher algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ (alg == PSA_ALG_CBC_PKCS7 ? \ (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ (input_length) + 1u) + \ PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0u) : \ (PSA_ALG_IS_CIPHER(alg) ? \ (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) : \ 0u)) /** A sufficient output buffer size for psa_cipher_encrypt(), for any of the * supported key types and cipher algorithms. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_encrypt() will not fail due to an insufficient buffer size. * * See also #PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). * * \param input_length Size of the input in bytes. * */ #define PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length) \ (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, \ (input_length) + 1u) + \ PSA_CIPHER_IV_MAX_SIZE) /** The maximum size of the output of psa_cipher_decrypt(), in bytes. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_decrypt() will not fail due to an insufficient buffer size. * Depending on the algorithm, the actual size of the output might be smaller. * * See also #PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(\p input_length). * * \param key_type A symmetric key type that is compatible with algorithm * alg. * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param input_length Size of the input in bytes. * * \return A sufficient output size for the specified key type and * algorithm. If the key type or cipher algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ (PSA_ALG_IS_CIPHER(alg) && \ ((key_type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ (input_length) : \ 0u) /** A sufficient output buffer size for psa_cipher_decrypt(), for any of the * supported key types and cipher algorithms. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_decrypt() will not fail due to an insufficient buffer size. * * See also #PSA_CIPHER_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). * * \param input_length Size of the input in bytes. */ #define PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(input_length) \ (input_length) /** A sufficient output buffer size for psa_cipher_update(). * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_update() will not fail due to an insufficient buffer size. * The actual size of the output might be smaller in any given call. * * See also #PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(\p input_length). * * \param key_type A symmetric key type that is compatible with algorithm * alg. * \param alg A cipher algorithm (PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param input_length Size of the input in bytes. * * \return A sufficient output size for the specified key type and * algorithm. If the key type or cipher algorithm is not * recognized, or the parameters are incompatible, return 0. */ #define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ (PSA_ALG_IS_CIPHER(alg) ? \ (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ (((alg) == PSA_ALG_CBC_PKCS7 || \ (alg) == PSA_ALG_CBC_NO_PADDING || \ (alg) == PSA_ALG_ECB_NO_PADDING) ? \ PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ input_length) : \ (input_length)) : 0u) : \ 0u) /** A sufficient output buffer size for psa_cipher_update(), for any of the * supported key types and cipher algorithms. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_update() will not fail due to an insufficient buffer size. * * See also #PSA_CIPHER_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). * * \param input_length Size of the input in bytes. */ #define PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input_length) \ (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, input_length)) /** A sufficient ciphertext buffer size for psa_cipher_finish(). * * If the size of the ciphertext buffer is at least this large, it is * guaranteed that psa_cipher_finish() will not fail due to an insufficient * ciphertext buffer size. The actual size of the output might be smaller in * any given call. * * See also #PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE(). * * \param key_type A symmetric key type that is compatible with algorithm * alg. * \param alg A cipher algorithm (PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \return A sufficient output size for the specified key type and * algorithm. If the key type or cipher algorithm is not * recognized, or the parameters are incompatible, return 0. */ #define PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg) \ (PSA_ALG_IS_CIPHER(alg) ? \ (alg == PSA_ALG_CBC_PKCS7 ? \ PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ 0u) : \ 0u) /** A sufficient ciphertext buffer size for psa_cipher_finish(), for any of the * supported key types and cipher algorithms. * * See also #PSA_CIPHER_FINISH_OUTPUT_SIZE(\p key_type, \p alg). */ #define PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE \ (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) #endif /* PSA_CRYPTO_SIZES_H */ webfakes/src/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h0000644000176200001440000000401514740737024026567 0ustar liggesusers/* * Declaration of context structures for use with the PSA driver wrapper * interface. This file contains the context structures for key derivation * operations. * * Warning: This file will be auto-generated in the future. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the PSA drivers included in the cryptographic * library. The definitions of these objects are then used by crypto_struct.h * to define the implementation-defined types of PSA multi-part state objects. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H #define PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H #include "psa/crypto_driver_common.h" /* Include the context structure definitions for the Mbed TLS software drivers */ #include "psa/crypto_builtin_key_derivation.h" /* Include the context structure definitions for those drivers that were * declared during the autogeneration process. */ typedef union { unsigned dummy; /* Make sure this union is always non-empty */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) psa_hkdf_key_derivation_t MBEDTLS_PRIVATE(hkdf); #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf); #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms); #endif #if defined(PSA_HAVE_SOFT_PBKDF2) psa_pbkdf2_key_derivation_t MBEDTLS_PRIVATE(pbkdf2); #endif } psa_driver_key_derivation_context_t; #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H */ /* End of automatically generated file. */ webfakes/src/mbedtls/include/psa/crypto_config.h0000644000176200001440000001537114740737024021525 0ustar liggesusers/** * \file psa/crypto_config.h * \brief PSA crypto configuration options (set of defines) * */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /** * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in mbedtls_config.h, * this file determines which cryptographic mechanisms are enabled * through the PSA Cryptography API (\c psa_xxx() functions). * * To enable a cryptographic mechanism, uncomment the definition of * the corresponding \c PSA_WANT_xxx preprocessor symbol. * To disable a cryptographic mechanism, comment out the definition of * the corresponding \c PSA_WANT_xxx preprocessor symbol. * The names of cryptographic mechanisms correspond to values * defined in psa/crypto_values.h, with the prefix \c PSA_WANT_ instead * of \c PSA_. * * Note that many cryptographic mechanisms involve two symbols: one for * the key type (\c PSA_WANT_KEY_TYPE_xxx) and one for the algorithm * (\c PSA_WANT_ALG_xxx). Mechanisms with additional parameters may involve * additional symbols. */ #else /** * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in mbedtls_config.h, * this file is not used, and cryptographic mechanisms are supported * through the PSA API if and only if they are supported through the * mbedtls_xxx API. */ #endif /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CONFIG_H #define PSA_CRYPTO_CONFIG_H /* * CBC-MAC is not yet supported via the PSA API in Mbed TLS. */ //#define PSA_WANT_ALG_CBC_MAC 1 #define PSA_WANT_ALG_CBC_NO_PADDING 1 #define PSA_WANT_ALG_CBC_PKCS7 1 #define PSA_WANT_ALG_CCM 1 #define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 #define PSA_WANT_ALG_CMAC 1 #define PSA_WANT_ALG_CFB 1 #define PSA_WANT_ALG_CHACHA20_POLY1305 1 #define PSA_WANT_ALG_CTR 1 #define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 #define PSA_WANT_ALG_ECB_NO_PADDING 1 #define PSA_WANT_ALG_ECDH 1 #define PSA_WANT_ALG_FFDH 1 #define PSA_WANT_ALG_ECDSA 1 #define PSA_WANT_ALG_JPAKE 1 #define PSA_WANT_ALG_GCM 1 #define PSA_WANT_ALG_HKDF 1 #define PSA_WANT_ALG_HKDF_EXTRACT 1 #define PSA_WANT_ALG_HKDF_EXPAND 1 #define PSA_WANT_ALG_HMAC 1 #define PSA_WANT_ALG_MD5 1 #define PSA_WANT_ALG_OFB 1 #define PSA_WANT_ALG_PBKDF2_HMAC 1 #define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 1 #define PSA_WANT_ALG_RIPEMD160 1 #define PSA_WANT_ALG_RSA_OAEP 1 #define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 #define PSA_WANT_ALG_RSA_PSS 1 #define PSA_WANT_ALG_SHA_1 1 #define PSA_WANT_ALG_SHA_224 1 #define PSA_WANT_ALG_SHA_256 1 #define PSA_WANT_ALG_SHA_384 1 #define PSA_WANT_ALG_SHA_512 1 #define PSA_WANT_ALG_SHA3_224 1 #define PSA_WANT_ALG_SHA3_256 1 #define PSA_WANT_ALG_SHA3_384 1 #define PSA_WANT_ALG_SHA3_512 1 #define PSA_WANT_ALG_STREAM_CIPHER 1 #define PSA_WANT_ALG_TLS12_PRF 1 #define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 #define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 /* XTS is not yet supported via the PSA API in Mbed TLS. * Note: when adding support, also adjust include/mbedtls/config_psa.h */ //#define PSA_WANT_ALG_XTS 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 #define PSA_WANT_ECC_MONTGOMERY_255 1 #define PSA_WANT_ECC_MONTGOMERY_448 1 #define PSA_WANT_ECC_SECP_K1_192 1 /* * SECP224K1 is buggy via the PSA API in Mbed TLS * (https://github.com/Mbed-TLS/mbedtls/issues/3541). Thus, do not enable it by * default. */ //#define PSA_WANT_ECC_SECP_K1_224 1 #define PSA_WANT_ECC_SECP_K1_256 1 #define PSA_WANT_ECC_SECP_R1_192 1 #define PSA_WANT_ECC_SECP_R1_224 1 /* For secp256r1, consider enabling #MBEDTLS_PSA_P256M_DRIVER_ENABLED * (see the description in mbedtls/mbedtls_config.h for details). */ #define PSA_WANT_ECC_SECP_R1_256 1 #define PSA_WANT_ECC_SECP_R1_384 1 #define PSA_WANT_ECC_SECP_R1_521 1 #define PSA_WANT_DH_RFC7919_2048 1 #define PSA_WANT_DH_RFC7919_3072 1 #define PSA_WANT_DH_RFC7919_4096 1 #define PSA_WANT_DH_RFC7919_6144 1 #define PSA_WANT_DH_RFC7919_8192 1 #define PSA_WANT_KEY_TYPE_DERIVE 1 #define PSA_WANT_KEY_TYPE_PASSWORD 1 #define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 #define PSA_WANT_KEY_TYPE_HMAC 1 #define PSA_WANT_KEY_TYPE_AES 1 #define PSA_WANT_KEY_TYPE_ARIA 1 #define PSA_WANT_KEY_TYPE_CAMELLIA 1 #define PSA_WANT_KEY_TYPE_CHACHA20 1 #define PSA_WANT_KEY_TYPE_DES 1 //#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1 /* Deprecated */ #define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 #define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 #define PSA_WANT_KEY_TYPE_RAW_DATA 1 //#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1 /* Deprecated */ #define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 /* * The following symbols extend and deprecate the legacy * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR ones. They include the usage of that key in * the name's suffix. "_USE" is the most generic and it can be used to describe * a generic suport, whereas other ones add more features on top of that and * they are more specific. */ #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 //#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE 1 /* Not supported */ #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 //#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE 1 /* Not supported */ #endif /* PSA_CRYPTO_CONFIG_H */ webfakes/src/mbedtls/include/psa/crypto_builtin_primitives.h0000644000176200001440000000753414740737024024203 0ustar liggesusers/* * Context structure declaration of the Mbed TLS software-based PSA drivers * called through the PSA Crypto driver dispatch layer. * This file contains the context structures of those algorithms which do not * rely on other algorithms, i.e. are 'primitive' algorithms. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the Mbed TLS software-based PSA drivers. The * definitions of these objects are then used by crypto_struct.h to define the * implementation-defined types of PSA multi-part state objects. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILTIN_PRIMITIVES_H #define PSA_CRYPTO_BUILTIN_PRIMITIVES_H #include "mbedtls/private_access.h" #include /* * Hash multi-part operation definitions. */ #include "mbedtls/md5.h" #include "mbedtls/ripemd160.h" #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" #include "mbedtls/sha3.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) #define MBEDTLS_PSA_BUILTIN_HASH #endif typedef struct { psa_algorithm_t MBEDTLS_PRIVATE(alg); union { unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) mbedtls_md5_context md5; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) mbedtls_ripemd160_context ripemd160; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) mbedtls_sha1_context sha1; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) mbedtls_sha256_context sha256; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) mbedtls_sha512_context sha512; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) mbedtls_sha3_context sha3; #endif } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_hash_operation_t; #define MBEDTLS_PSA_HASH_OPERATION_INIT { 0, { 0 } } /* * Cipher multi-part operation definitions. */ #include "mbedtls/cipher.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) #define MBEDTLS_PSA_BUILTIN_CIPHER 1 #endif typedef struct { /* Context structure for the Mbed TLS cipher implementation. */ psa_algorithm_t MBEDTLS_PRIVATE(alg); uint8_t MBEDTLS_PRIVATE(iv_length); uint8_t MBEDTLS_PRIVATE(block_length); union { unsigned int MBEDTLS_PRIVATE(dummy); mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher); } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_cipher_operation_t; #define MBEDTLS_PSA_CIPHER_OPERATION_INIT { 0, 0, 0, { 0 } } #endif /* PSA_CRYPTO_BUILTIN_PRIMITIVES_H */ webfakes/src/mbedtls/include/psa/crypto_adjust_config_synonyms.h0000644000176200001440000000375414740737024025060 0ustar liggesusers/** * \file psa/crypto_adjust_config_synonyms.h * \brief Adjust PSA configuration: enable quasi-synonyms * * This is an internal header. Do not include it directly. * * When two features require almost the same code, we automatically enable * both when either one is requested, to reduce the combinatorics of * possible configurations. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H #define PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ /****************************************************************/ /* De facto synonyms */ /****************************************************************/ #if defined(PSA_WANT_ALG_ECDSA_ANY) && !defined(PSA_WANT_ALG_ECDSA) #define PSA_WANT_ALG_ECDSA PSA_WANT_ALG_ECDSA_ANY #elif !defined(PSA_WANT_ALG_ECDSA_ANY) && defined(PSA_WANT_ALG_ECDSA) #define PSA_WANT_ALG_ECDSA_ANY PSA_WANT_ALG_ECDSA #endif #if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW #elif !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW PSA_WANT_ALG_RSA_PKCS1V15_SIGN #endif #if defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && !defined(PSA_WANT_ALG_RSA_PSS) #define PSA_WANT_ALG_RSA_PSS PSA_WANT_ALG_RSA_PSS_ANY_SALT #elif !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && defined(PSA_WANT_ALG_RSA_PSS) #define PSA_WANT_ALG_RSA_PSS_ANY_SALT PSA_WANT_ALG_RSA_PSS #endif #endif /* PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H */ webfakes/src/mbedtls/include/psa/crypto_builtin_key_derivation.h0000644000176200001440000001137714740737024025024 0ustar liggesusers/* * Context structure declaration of the Mbed TLS software-based PSA drivers * called through the PSA Crypto driver dispatch layer. * This file contains the context structures of key derivation algorithms * which need to rely on other algorithms. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the Mbed TLS software-based PSA drivers. The * definitions of these objects are then used by crypto_struct.h to define the * implementation-defined types of PSA multi-part state objects. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H #define PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H #include "mbedtls/private_access.h" #include #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) typedef struct { uint8_t *MBEDTLS_PRIVATE(info); size_t MBEDTLS_PRIVATE(info_length); #if PSA_HASH_MAX_SIZE > 0xff #error "PSA_HASH_MAX_SIZE does not fit in uint8_t" #endif uint8_t MBEDTLS_PRIVATE(offset_in_block); uint8_t MBEDTLS_PRIVATE(block_number); unsigned int MBEDTLS_PRIVATE(state) : 2; unsigned int MBEDTLS_PRIVATE(info_set) : 1; uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; uint8_t MBEDTLS_PRIVATE(prk)[PSA_HASH_MAX_SIZE]; struct psa_mac_operation_s MBEDTLS_PRIVATE(hmac); } psa_hkdf_key_derivation_t; #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF || MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT || MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) typedef struct { uint8_t MBEDTLS_PRIVATE(data)[PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE]; } psa_tls12_ecjpake_to_pms_t; #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) typedef enum { PSA_TLS12_PRF_STATE_INIT, /* no input provided */ PSA_TLS12_PRF_STATE_SEED_SET, /* seed has been set */ PSA_TLS12_PRF_STATE_OTHER_KEY_SET, /* other key has been set - optional */ PSA_TLS12_PRF_STATE_KEY_SET, /* key has been set */ PSA_TLS12_PRF_STATE_LABEL_SET, /* label has been set */ PSA_TLS12_PRF_STATE_OUTPUT /* output has been started */ } psa_tls12_prf_key_derivation_state_t; typedef struct psa_tls12_prf_key_derivation_s { #if PSA_HASH_MAX_SIZE > 0xff #error "PSA_HASH_MAX_SIZE does not fit in uint8_t" #endif /* Indicates how many bytes in the current HMAC block have * not yet been read by the user. */ uint8_t MBEDTLS_PRIVATE(left_in_block); /* The 1-based number of the block. */ uint8_t MBEDTLS_PRIVATE(block_number); psa_tls12_prf_key_derivation_state_t MBEDTLS_PRIVATE(state); uint8_t *MBEDTLS_PRIVATE(secret); size_t MBEDTLS_PRIVATE(secret_length); uint8_t *MBEDTLS_PRIVATE(seed); size_t MBEDTLS_PRIVATE(seed_length); uint8_t *MBEDTLS_PRIVATE(label); size_t MBEDTLS_PRIVATE(label_length); #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) uint8_t *MBEDTLS_PRIVATE(other_secret); size_t MBEDTLS_PRIVATE(other_secret_length); #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ uint8_t MBEDTLS_PRIVATE(Ai)[PSA_HASH_MAX_SIZE]; /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */ uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; } psa_tls12_prf_key_derivation_t; #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(PSA_HAVE_SOFT_PBKDF2) typedef enum { PSA_PBKDF2_STATE_INIT, /* no input provided */ PSA_PBKDF2_STATE_INPUT_COST_SET, /* input cost has been set */ PSA_PBKDF2_STATE_SALT_SET, /* salt has been set */ PSA_PBKDF2_STATE_PASSWORD_SET, /* password has been set */ PSA_PBKDF2_STATE_OUTPUT /* output has been started */ } psa_pbkdf2_key_derivation_state_t; typedef struct { psa_pbkdf2_key_derivation_state_t MBEDTLS_PRIVATE(state); uint64_t MBEDTLS_PRIVATE(input_cost); uint8_t *MBEDTLS_PRIVATE(salt); size_t MBEDTLS_PRIVATE(salt_length); uint8_t MBEDTLS_PRIVATE(password)[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; size_t MBEDTLS_PRIVATE(password_length); uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; uint8_t MBEDTLS_PRIVATE(bytes_used); uint32_t MBEDTLS_PRIVATE(block_number); } psa_pbkdf2_key_derivation_t; #endif /* PSA_HAVE_SOFT_PBKDF2 */ #endif /* PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H */ webfakes/src/mbedtls/include/psa/crypto_legacy.h0000644000176200001440000000605714740737024021525 0ustar liggesusers/** * \file psa/crypto_legacy.h * * \brief Add temporary suppport for deprecated symbols before they are * removed from the library. * * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR and MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR * symbols are deprecated. * New symols add a suffix to that base name in order to clearly state what is * the expected use for the key (use, import, export, generate, derive). * Here we define some backward compatibility support for uses stil using * the legacy symbols. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PSA_CRYPTO_LEGACY_H #define MBEDTLS_PSA_CRYPTO_LEGACY_H #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) //no-check-names #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #endif #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #endif #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #endif #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 #endif #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #endif #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) //no-check-names #if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #endif #if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #endif #if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #endif #if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 #endif #endif #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) //no-check-names #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE #endif #endif #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) //no-check-names #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE #endif #endif #endif /* MBEDTLS_PSA_CRYPTO_LEGACY_H */ webfakes/src/mbedtls/include/psa/crypto.h0000644000176200001440000073641014740737024020204 0ustar liggesusers/** * \file psa/crypto.h * \brief Platform Security Architecture cryptography module */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_H #define PSA_CRYPTO_H #if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE) #include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE #else #include "crypto_platform.h" #endif #include #ifdef __DOXYGEN_ONLY__ /* This __DOXYGEN_ONLY__ block contains mock definitions for things that * must be defined in the crypto_platform.h header. These mock definitions * are present in this file as a convenience to generate pretty-printed * documentation that includes those definitions. */ /** \defgroup platform Implementation-specific definitions * @{ */ /**@}*/ #endif /* __DOXYGEN_ONLY__ */ #ifdef __cplusplus extern "C" { #endif /* The file "crypto_types.h" declares types that encode errors, * algorithms, key types, policies, etc. */ #include "crypto_types.h" /** \defgroup version API version * @{ */ /** * The major version of this implementation of the PSA Crypto API */ #define PSA_CRYPTO_API_VERSION_MAJOR 1 /** * The minor version of this implementation of the PSA Crypto API */ #define PSA_CRYPTO_API_VERSION_MINOR 0 /**@}*/ /* The file "crypto_values.h" declares macros to build and analyze values * of integral types defined in "crypto_types.h". */ #include "crypto_values.h" /** \defgroup initialization Library initialization * @{ */ /** * \brief Library initialization. * * Applications must call this function before calling any other * function in this module. * * Applications may call this function more than once. Once a call * succeeds, subsequent calls are guaranteed to succeed. * * If the application calls other functions before calling psa_crypto_init(), * the behavior is undefined. Implementations are encouraged to either perform * the operation as if the library had been initialized or to return * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, * implementations should not return a success status if the lack of * initialization may have security implications, for example due to improper * seeding of the random number generator. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ psa_status_t psa_crypto_init(void); /**@}*/ /** \addtogroup attributes * @{ */ /** \def PSA_KEY_ATTRIBUTES_INIT * * This macro returns a suitable initializer for a key attribute structure * of type #psa_key_attributes_t. */ /** Return an initial value for a key attributes structure. */ static psa_key_attributes_t psa_key_attributes_init(void); /** Declare a key as persistent and set its key identifier. * * If the attribute structure currently declares the key as volatile (which * is the default content of an attribute structure), this function sets * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. * * This function does not access storage, it merely stores the given * value in the structure. * The persistent key will be written to storage when the attribute * structure is passed to a key creation function such as * psa_import_key(), psa_generate_key(), psa_generate_key_custom(), * psa_key_derivation_output_key(), psa_key_derivation_output_key_custom() * or psa_copy_key(). * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param key The persistent identifier for the key. * This can be any value in the range from * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX * inclusive. */ static void psa_set_key_id(psa_key_attributes_t *attributes, mbedtls_svc_key_id_t key); #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER /** Set the owner identifier of a key. * * When key identifiers encode key owner identifiers, psa_set_key_id() does * not allow to define in key attributes the owner of volatile keys as * psa_set_key_id() enforces the key to be persistent. * * This function allows to set in key attributes the owner identifier of a * key. It is intended to be used for volatile keys. For persistent keys, * it is recommended to use the PSA Cryptography API psa_set_key_id() to define * the owner of a key. * * \param[out] attributes The attribute structure to write to. * \param owner The key owner identifier. */ static void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes, mbedtls_key_owner_id_t owner); #endif /** Set the location of a persistent key. * * To make a key persistent, you must give it a persistent key identifier * with psa_set_key_id(). By default, a key that has a persistent identifier * is stored in the default storage area identifier by * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage * area, or to explicitly declare the key as volatile. * * This function does not access storage, it merely stores the given * value in the structure. * The persistent key will be written to storage when the attribute * structure is passed to a key creation function such as * psa_import_key(), psa_generate_key(), psa_generate_key_custom(), * psa_key_derivation_output_key(), psa_key_derivation_output_key_custom() * or psa_copy_key(). * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param lifetime The lifetime for the key. * If this is #PSA_KEY_LIFETIME_VOLATILE, the * key will be volatile, and the key identifier * attribute is reset to 0. */ static void psa_set_key_lifetime(psa_key_attributes_t *attributes, psa_key_lifetime_t lifetime); /** Retrieve the key identifier from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The persistent identifier stored in the attribute structure. * This value is unspecified if the attribute structure declares * the key as volatile. */ static mbedtls_svc_key_id_t psa_get_key_id( const psa_key_attributes_t *attributes); /** Retrieve the lifetime from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The lifetime value stored in the attribute structure. */ static psa_key_lifetime_t psa_get_key_lifetime( const psa_key_attributes_t *attributes); /** Declare usage flags for a key. * * Usage flags are part of a key's usage policy. They encode what * kind of operations are permitted on the key. For more details, * refer to the documentation of the type #psa_key_usage_t. * * This function overwrites any usage flags * previously set in \p attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param usage_flags The usage flags to write. */ static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, psa_key_usage_t usage_flags); /** Retrieve the usage flags from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The usage flags stored in the attribute structure. */ static psa_key_usage_t psa_get_key_usage_flags( const psa_key_attributes_t *attributes); /** Declare the permitted algorithm policy for a key. * * The permitted algorithm policy of a key encodes which algorithm or * algorithms are permitted to be used with this key. The following * algorithm policies are supported: * - 0 does not allow any cryptographic operation with the key. The key * may be used for non-cryptographic actions such as exporting (if * permitted by the usage flags). * - An algorithm value permits this particular algorithm. * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified * signature scheme with any hash algorithm. * - An algorithm built from #PSA_ALG_AT_LEAST_THIS_LENGTH_MAC allows * any MAC algorithm from the same base class (e.g. CMAC) which * generates/verifies a MAC length greater than or equal to the length * encoded in the wildcard algorithm. * - An algorithm built from #PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG * allows any AEAD algorithm from the same base class (e.g. CCM) which * generates/verifies a tag length greater than or equal to the length * encoded in the wildcard algorithm. * * This function overwrites any algorithm policy * previously set in \p attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param alg The permitted algorithm policy to write. */ static void psa_set_key_algorithm(psa_key_attributes_t *attributes, psa_algorithm_t alg); /** Retrieve the algorithm policy from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The algorithm stored in the attribute structure. */ static psa_algorithm_t psa_get_key_algorithm( const psa_key_attributes_t *attributes); /** Declare the type of a key. * * This function overwrites any key type * previously set in \p attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param type The key type to write. * If this is 0, the key type in \p attributes * becomes unspecified. */ static void psa_set_key_type(psa_key_attributes_t *attributes, psa_key_type_t type); /** Declare the size of a key. * * This function overwrites any key size previously set in \p attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param bits The key size in bits. * If this is 0, the key size in \p attributes * becomes unspecified. Keys of size 0 are * not supported. */ static void psa_set_key_bits(psa_key_attributes_t *attributes, size_t bits); /** Retrieve the key type from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The key type stored in the attribute structure. */ static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); /** Retrieve the key size from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The key size stored in the attribute structure, in bits. */ static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); /** Retrieve the attributes of a key. * * This function first resets the attribute structure as with * psa_reset_key_attributes(). It then copies the attributes of * the given key into the given attribute structure. * * \note This function may allocate memory or other resources. * Once you have called this function on an attribute structure, * you must call psa_reset_key_attributes() to free these resources. * * \param[in] key Identifier of the key to query. * \param[in,out] attributes On success, the attributes of the key. * On failure, equivalent to a * freshly-initialized structure. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, psa_key_attributes_t *attributes); /** Reset a key attribute structure to a freshly initialized state. * * You must initialize the attribute structure as described in the * documentation of the type #psa_key_attributes_t before calling this * function. Once the structure has been initialized, you may call this * function at any time. * * This function frees any auxiliary resources that the structure * may contain. * * \param[in,out] attributes The attribute structure to reset. */ void psa_reset_key_attributes(psa_key_attributes_t *attributes); /**@}*/ /** \defgroup key_management Key management * @{ */ /** Remove non-essential copies of key material from memory. * * If the key identifier designates a volatile key, this functions does not do * anything and returns successfully. * * If the key identifier designates a persistent key, then this function will * free all resources associated with the key in volatile memory. The key * data in persistent storage is not affected and the key can still be used. * * \param key Identifier of the key to purge. * * \retval #PSA_SUCCESS * The key material will have been removed from memory if it is not * currently required. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not a valid key identifier. * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_purge_key(mbedtls_svc_key_id_t key); /** Make a copy of a key. * * Copy key material from one location to another. * * This function is primarily useful to copy a key from one location * to another, since it populates a key using the material from * another key which may have a different lifetime. * * This function may be used to share a key with a different party, * subject to implementation-defined restrictions on key sharing. * * The policy on the source key must have the usage flag * #PSA_KEY_USAGE_COPY set. * This flag is sufficient to permit the copy if the key has the lifetime * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. * Some secure elements do not provide a way to copy a key without * making it extractable from the secure element. If a key is located * in such a secure element, then the key must have both usage flags * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make * a copy of the key outside the secure element. * * The resulting key may only be used in a way that conforms to * both the policy of the original key and the policy specified in * the \p attributes parameter: * - The usage flags on the resulting key are the bitwise-and of the * usage flags on the source policy and the usage flags in \p attributes. * - If both allow the same algorithm or wildcard-based * algorithm policy, the resulting key has the same algorithm policy. * - If either of the policies allows an algorithm and the other policy * allows a wildcard-based algorithm policy that includes this algorithm, * the resulting key allows the same algorithm. * - If the policies do not allow any algorithm in common, this function * fails with the status #PSA_ERROR_INVALID_ARGUMENT. * * The effect of this function on implementation-defined attributes is * implementation-defined. * * \param source_key The key to copy. It must allow the usage * #PSA_KEY_USAGE_COPY. If a private or secret key is * being copied outside of a secure element it must * also allow #PSA_KEY_USAGE_EXPORT. * \param[in] attributes The attributes for the new key. * They are used as follows: * - The key type and size may be 0. If either is * nonzero, it must match the corresponding * attribute of the source key. * - The key location (the lifetime and, for * persistent keys, the key identifier) is * used directly. * - The policy constraints (usage flags and * algorithm policy) are combined from * the source key and \p attributes so that * both sets of restrictions apply, as * described in the documentation of this function. * \param[out] target_key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE * \p source_key is invalid. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_INVALID_ARGUMENT * The lifetime or identifier in \p attributes are invalid, or * the policy constraints on the source and specified in * \p attributes are incompatible, or * \p attributes specifies a key type or key size * which does not match the attributes of the source key. * \retval #PSA_ERROR_NOT_PERMITTED * The source key does not have the #PSA_KEY_USAGE_COPY usage flag, or * the source key is not exportable and its lifetime does not * allow copying it to the target's lifetime. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *target_key); /** * \brief Destroy a key. * * This function destroys a key from both volatile * memory and, if applicable, non-volatile storage. Implementations shall * make a best effort to ensure that the key material cannot be recovered. * * This function also erases any metadata such as policies and frees * resources associated with the key. * * If a key is currently in use in a multipart operation, then destroying the * key will cause the multipart operation to fail. * * \warning We can only guarantee that the the key material will * eventually be wiped from memory. With threading enabled * and during concurrent execution, copies of the key material may * still exist until all threads have finished using the key. * * \param key Identifier of the key to erase. If this is \c 0, do nothing and * return #PSA_SUCCESS. * * \retval #PSA_SUCCESS * \p key was a valid identifier and the key material that it * referred to has been erased. Alternatively, \p key is \c 0. * \retval #PSA_ERROR_NOT_PERMITTED * The key cannot be erased because it is * read-only, either due to a policy or due to physical restrictions. * \retval #PSA_ERROR_INVALID_HANDLE * \p key is not a valid identifier nor \c 0. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * There was a failure in communication with the cryptoprocessor. * The key material may still be present in the cryptoprocessor. * \retval #PSA_ERROR_DATA_INVALID * This error is typically a result of either storage corruption on a * cleartext storage backend, or an attempt to read data that was * written by an incompatible version of the library. * \retval #PSA_ERROR_STORAGE_FAILURE * The storage is corrupted. Implementations shall make a best effort * to erase key material even in this stage, however applications * should be aware that it may be impossible to guarantee that the * key material is not recoverable in such cases. * \retval #PSA_ERROR_CORRUPTION_DETECTED * An unexpected condition which is not a storage corruption or * a communication failure occurred. The cryptoprocessor may have * been compromised. * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key); /**@}*/ /** \defgroup import_export Key import and export * @{ */ /** * \brief Import a key in binary format. * * This function supports any output from psa_export_key(). Refer to the * documentation of psa_export_public_key() for the format of public keys * and to the documentation of psa_export_key() for the format for * other key types. * * The key data determines the key size. The attributes may optionally * specify a key size; in this case it must match the size determined * from the key data. A key size of 0 in \p attributes indicates that * the key size is solely determined by the key data. * * Implementations must reject an attempt to import a key of size 0. * * This specification supports a single format for each key type. * Implementations may support other formats as long as the standard * format is supported. Implementations that support other formats * should ensure that the formats are clearly unambiguous so as to * minimize the risk that an invalid input is accidentally interpreted * according to a different format. * * \param[in] attributes The attributes for the new key. * The key size is always determined from the * \p data buffer. * If the key size in \p attributes is nonzero, * it must be equal to the size from \p data. * \param[out] key On success, an identifier to the newly created key. * For persistent keys, this is the key identifier * defined in \p attributes. * \c 0 on failure. * \param[in] data Buffer containing the key data. The content of this * buffer is interpreted according to the type declared * in \p attributes. * All implementations must support at least the format * described in the documentation * of psa_export_key() or psa_export_public_key() for * the chosen type. Implementations may allow other * formats, but should be conservative: implementations * should err on the side of rejecting content if it * may be erroneous (e.g. wrong type or truncated data). * \param data_length Size of the \p data buffer in bytes. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular persistent location. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key attributes, as a whole, are invalid, or * the key data is not correctly formatted, or * the size in \p attributes is nonzero and does not match the size * of the key data. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_import_key(const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, mbedtls_svc_key_id_t *key); /** * \brief Export a key in binary format. * * The output of this function can be passed to psa_import_key() to * create an equivalent object. * * If the implementation of psa_import_key() supports other formats * beyond the format specified here, the output from psa_export_key() * must use the representation specified here, not the original * representation. * * For standard key types, the output format is as follows: * * - For symmetric keys (including MAC keys), the format is the * raw bytes of the key. * - For DES, the key data consists of 8 bytes. The parity bits must be * correct. * - For Triple-DES, the format is the concatenation of the * two or three DES keys. * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format * is the non-encrypted DER encoding of the representation defined by * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. * ``` * RSAPrivateKey ::= SEQUENCE { * version INTEGER, -- must be 0 * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER, -- (inverse of q) mod p * } * ``` * - For elliptic curve key pairs (key types for which * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is * a representation of the private value as a `ceiling(m/8)`-byte string * where `m` is the bit size associated with the curve, i.e. the bit size * of the order of the curve's coordinate field. This byte string is * in little-endian order for Montgomery curves (curve types * `PSA_ECC_FAMILY_CURVEXXX`), and in big-endian order for Weierstrass * curves (curve types `PSA_ECC_FAMILY_SECTXXX`, `PSA_ECC_FAMILY_SECPXXX` * and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`). * For Weierstrass curves, this is the content of the `privateKey` field of * the `ECPrivateKey` format defined by RFC 5915. For Montgomery curves, * the format is defined by RFC 7748, and output is masked according to §5. * For twisted Edwards curves, the private key is as defined by RFC 8032 * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). * - For Diffie-Hellman key exchange key pairs (key types for which * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the * format is the representation of the private key `x` as a big-endian byte * string. The length of the byte string is the private key size in bytes * (leading zeroes are not stripped). * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is * true), the format is the same as for psa_export_public_key(). * * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. * * \param key Identifier of the key to export. It must allow the * usage #PSA_KEY_USAGE_EXPORT, unless it is a public * key. * \param[out] data Buffer where the key data is to be written. * \param data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes * that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_EXPORT flag. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p data buffer is too small. You can determine a * sufficient buffer size by calling * #PSA_EXPORT_KEY_OUTPUT_SIZE(\c type, \c bits) * where \c type is the key type * and \c bits is the key size in bits. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_export_key(mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size, size_t *data_length); /** * \brief Export a public key or the public part of a key pair in binary format. * * The output of this function can be passed to psa_import_key() to * create an object that is equivalent to the public key. * * This specification supports a single format for each key type. * Implementations may support other formats as long as the standard * format is supported. Implementations that support other formats * should ensure that the formats are clearly unambiguous so as to * minimize the risk that an invalid input is accidentally interpreted * according to a different format. * * For standard key types, the output format is as follows: * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. * ``` * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER } -- e * ``` * - For elliptic curve keys on a twisted Edwards curve (key types for which * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_ECC_GET_FAMILY * returns #PSA_ECC_FAMILY_TWISTED_EDWARDS), the public key is as defined * by RFC 8032 * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). * - For other elliptic curve public keys (key types for which * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed * representation defined by SEC1 §2.3.3 as the content of an ECPoint. * Let `m` be the bit size associated with the curve, i.e. the bit size of * `q` for a curve over `F_q`. The representation consists of: * - The byte 0x04; * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. * - For Diffie-Hellman key exchange public keys (key types for which * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), * the format is the representation of the public key `y = g^x mod p` as a * big-endian byte string. The length of the byte string is the length of the * base prime `p` in bytes. * * Exporting a public key object or the public part of a key pair is * always permitted, regardless of the key's usage flags. * * \param key Identifier of the key to export. * \param[out] data Buffer where the key data is to be written. * \param data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes * that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * The key is neither a public key nor a key pair. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p data buffer is too small. You can determine a * sufficient buffer size by calling * #PSA_EXPORT_KEY_OUTPUT_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) * where \c type is the key type * and \c bits is the key size in bits. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size, size_t *data_length); /**@}*/ /** \defgroup hash Message digests * @{ */ /** Calculate the hash (digest) of a message. * * \note To verify the hash of a message against an * expected value, use psa_hash_compare() instead. * * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * \param[in] input Buffer containing the message to hash. * \param input_length Size of the \p input buffer in bytes. * \param[out] hash Buffer where the hash is to be written. * \param hash_size Size of the \p hash buffer in bytes. * \param[out] hash_length On success, the number of bytes * that make up the hash value. This is always * #PSA_HASH_LENGTH(\p alg). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a hash algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p hash_size is too small * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_compute(psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length); /** Calculate the hash (digest) of a message and compare it with a * reference value. * * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * \param[in] input Buffer containing the message to hash. * \param input_length Size of the \p input buffer in bytes. * \param[in] hash Buffer containing the expected hash value. * \param hash_length Size of the \p hash buffer in bytes. * * \retval #PSA_SUCCESS * The expected hash is identical to the actual hash of the input. * \retval #PSA_ERROR_INVALID_SIGNATURE * The hash of the message was calculated successfully, but it * differs from the expected hash. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a hash algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p input_length or \p hash_length do not match the hash size for \p alg * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_compare(psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *hash, size_t hash_length); /** The type of the state data structure for multipart hash operations. * * Before calling any function on a hash operation object, the application must * initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_hash_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_hash_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, * for example: * \code * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; * \endcode * - Assign the result of the function psa_hash_operation_init() * to the structure, for example: * \code * psa_hash_operation_t operation; * operation = psa_hash_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_hash_operation_s psa_hash_operation_t; /** \def PSA_HASH_OPERATION_INIT * * This macro returns a suitable initializer for a hash operation object * of type #psa_hash_operation_t. */ /** Return an initial value for a hash operation object. */ static psa_hash_operation_t psa_hash_operation_init(void); /** Set up a multipart hash operation. * * The sequence of operations to calculate a hash (message digest) * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. * -# Call psa_hash_setup() to specify the algorithm. * -# Call psa_hash_update() zero, one or more times, passing a fragment * of the message each time. The hash that is calculated is the hash * of the concatenation of these messages in order. * -# To calculate the hash, call psa_hash_finish(). * To compare the hash with an expected value, call psa_hash_verify(). * * If an error occurs at any step after a call to psa_hash_setup(), the * operation will need to be reset by a call to psa_hash_abort(). The * application may call psa_hash_abort() at any time after the operation * has been initialized. * * After a successful call to psa_hash_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_hash_finish() or psa_hash_verify(). * - A call to psa_hash_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_hash_operation_t and not yet in use. * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not a supported hash algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p alg is not a hash algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_setup(psa_hash_operation_t *operation, psa_algorithm_t alg); /** Add a message fragment to a multipart hash operation. * * The application must call psa_hash_setup() before calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_hash_abort(). * * \param[in,out] operation Active hash operation. * \param[in] input Buffer containing the message fragment to hash. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_update(psa_hash_operation_t *operation, const uint8_t *input, size_t input_length); /** Finish the calculation of the hash of a message. * * The application must call psa_hash_setup() before calling this function. * This function calculates the hash of the message formed by concatenating * the inputs passed to preceding calls to psa_hash_update(). * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_hash_abort(). * * \warning Applications should not call this function if they expect * a specific value for the hash. Call psa_hash_verify() instead. * Beware that comparing integrity or authenticity data such as * hash values with a function such as \c memcmp is risky * because the time taken by the comparison may leak information * about the hashed data which could allow an attacker to guess * a valid hash and thereby bypass security controls. * * \param[in,out] operation Active hash operation. * \param[out] hash Buffer where the hash is to be written. * \param hash_size Size of the \p hash buffer in bytes. * \param[out] hash_length On success, the number of bytes * that make up the hash value. This is always * #PSA_HASH_LENGTH(\c alg) where \c alg is the * hash algorithm that is calculated. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p hash buffer is too small. You can determine a * sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg) * where \c alg is the hash algorithm that is calculated. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_finish(psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length); /** Finish the calculation of the hash of a message and compare it with * an expected value. * * The application must call psa_hash_setup() before calling this function. * This function calculates the hash of the message formed by concatenating * the inputs passed to preceding calls to psa_hash_update(). It then * compares the calculated hash with the expected hash passed as a * parameter to this function. * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_hash_abort(). * * \note Implementations shall make the best effort to ensure that the * comparison between the actual hash and the expected hash is performed * in constant time. * * \param[in,out] operation Active hash operation. * \param[in] hash Buffer containing the expected hash value. * \param hash_length Size of the \p hash buffer in bytes. * * \retval #PSA_SUCCESS * The expected hash is identical to the actual hash of the message. * \retval #PSA_ERROR_INVALID_SIGNATURE * The hash of the message was calculated successfully, but it * differs from the expected hash. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, const uint8_t *hash, size_t hash_length); /** Abort a hash operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * psa_hash_setup() again. * * You may call this function any time after the operation object has * been initialized by one of the methods described in #psa_hash_operation_t. * * In particular, calling psa_hash_abort() after the operation has been * terminated by a call to psa_hash_abort(), psa_hash_finish() or * psa_hash_verify() is safe and has no effect. * * \param[in,out] operation Initialized hash operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_abort(psa_hash_operation_t *operation); /** Clone a hash operation. * * This function copies the state of an ongoing hash operation to * a new operation object. In other words, this function is equivalent * to calling psa_hash_setup() on \p target_operation with the same * algorithm that \p source_operation was set up for, then * psa_hash_update() on \p target_operation with the same input that * that was passed to \p source_operation. After this function returns, the * two objects are independent, i.e. subsequent calls involving one of * the objects do not affect the other object. * * \param[in] source_operation The active hash operation to clone. * \param[in,out] target_operation The operation object to set up. * It must be initialized but not active. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The \p source_operation state is not valid (it must be active), or * the \p target_operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, psa_hash_operation_t *target_operation); /**@}*/ /** \defgroup MAC Message authentication codes * @{ */ /** Calculate the MAC (message authentication code) of a message. * * \note To verify the MAC of a message against an * expected value, use psa_mac_verify() instead. * Beware that comparing integrity or authenticity data such as * MAC values with a function such as \c memcmp is risky * because the time taken by the comparison may leak information * about the MAC value which could allow an attacker to guess * a valid MAC and thereby bypass security controls. * * \param key Identifier of the key to use for the operation. It * must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * \param[in] input Buffer containing the input message. * \param input_length Size of the \p input buffer in bytes. * \param[out] mac Buffer where the MAC value is to be written. * \param mac_size Size of the \p mac buffer in bytes. * \param[out] mac_length On success, the number of bytes * that make up the MAC value. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a MAC algorithm. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p mac_size is too small * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The key could not be retrieved from storage. * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length); /** Calculate the MAC of a message and compare it with a reference value. * * \param key Identifier of the key to use for the operation. It * must allow the usage PSA_KEY_USAGE_VERIFY_MESSAGE. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * \param[in] input Buffer containing the input message. * \param input_length Size of the \p input buffer in bytes. * \param[in] mac Buffer containing the expected MAC value. * \param mac_length Size of the \p mac buffer in bytes. * * \retval #PSA_SUCCESS * The expected MAC is identical to the actual MAC of the input. * \retval #PSA_ERROR_INVALID_SIGNATURE * The MAC of the message was calculated successfully, but it * differs from the expected value. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a MAC algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The key could not be retrieved from storage. * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *mac, size_t mac_length); /** The type of the state data structure for multipart MAC operations. * * Before calling any function on a MAC operation object, the application must * initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_mac_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_mac_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, * for example: * \code * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; * \endcode * - Assign the result of the function psa_mac_operation_init() * to the structure, for example: * \code * psa_mac_operation_t operation; * operation = psa_mac_operation_init(); * \endcode * * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_mac_operation_s psa_mac_operation_t; /** \def PSA_MAC_OPERATION_INIT * * This macro returns a suitable initializer for a MAC operation object of type * #psa_mac_operation_t. */ /** Return an initial value for a MAC operation object. */ static psa_mac_operation_t psa_mac_operation_init(void); /** Set up a multipart MAC calculation operation. * * This function sets up the calculation of the MAC * (message authentication code) of a byte string. * To verify the MAC of a message against an * expected value, use psa_mac_verify_setup() instead. * * The sequence of operations to calculate a MAC is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. * -# Call psa_mac_sign_setup() to specify the algorithm and key. * -# Call psa_mac_update() zero, one or more times, passing a fragment * of the message each time. The MAC that is calculated is the MAC * of the concatenation of these messages in order. * -# At the end of the message, call psa_mac_sign_finish() to finish * calculating the MAC value and retrieve it. * * If an error occurs at any step after a call to psa_mac_sign_setup(), the * operation will need to be reset by a call to psa_mac_abort(). The * application may call psa_mac_abort() at any time after the operation * has been initialized. * * After a successful call to psa_mac_sign_setup(), the application must * eventually terminate the operation through one of the following methods: * - A successful call to psa_mac_sign_finish(). * - A call to psa_mac_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_mac_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. It * must remain valid until the operation terminates. * It must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a MAC algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The key could not be retrieved from storage. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Set up a multipart MAC verification operation. * * This function sets up the verification of the MAC * (message authentication code) of a byte string against an expected value. * * The sequence of operations to verify a MAC is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. * -# Call psa_mac_verify_setup() to specify the algorithm and key. * -# Call psa_mac_update() zero, one or more times, passing a fragment * of the message each time. The MAC that is calculated is the MAC * of the concatenation of these messages in order. * -# At the end of the message, call psa_mac_verify_finish() to finish * calculating the actual MAC of the message and verify it against * the expected value. * * If an error occurs at any step after a call to psa_mac_verify_setup(), the * operation will need to be reset by a call to psa_mac_abort(). The * application may call psa_mac_abort() at any time after the operation * has been initialized. * * After a successful call to psa_mac_verify_setup(), the application must * eventually terminate the operation through one of the following methods: * - A successful call to psa_mac_verify_finish(). * - A call to psa_mac_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_mac_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. It * must remain valid until the operation terminates. * It must allow the usage * PSA_KEY_USAGE_VERIFY_MESSAGE. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \c key is not compatible with \c alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \c alg is not supported or is not a MAC algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The key could not be retrieved from storage. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Add a message fragment to a multipart MAC operation. * * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() * before calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_mac_abort(). * * \param[in,out] operation Active MAC operation. * \param[in] input Buffer containing the message fragment to add to * the MAC calculation. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_update(psa_mac_operation_t *operation, const uint8_t *input, size_t input_length); /** Finish the calculation of the MAC of a message. * * The application must call psa_mac_sign_setup() before calling this function. * This function calculates the MAC of the message formed by concatenating * the inputs passed to preceding calls to psa_mac_update(). * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_mac_abort(). * * \warning Applications should not call this function if they expect * a specific value for the MAC. Call psa_mac_verify_finish() instead. * Beware that comparing integrity or authenticity data such as * MAC values with a function such as \c memcmp is risky * because the time taken by the comparison may leak information * about the MAC value which could allow an attacker to guess * a valid MAC and thereby bypass security controls. * * \param[in,out] operation Active MAC operation. * \param[out] mac Buffer where the MAC value is to be written. * \param mac_size Size of the \p mac buffer in bytes. * \param[out] mac_length On success, the number of bytes * that make up the MAC value. This is always * #PSA_MAC_LENGTH(\c key_type, \c key_bits, \c alg) * where \c key_type and \c key_bits are the type and * bit-size respectively of the key and \c alg is the * MAC algorithm that is calculated. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p mac buffer is too small. You can determine a * sufficient buffer size by calling PSA_MAC_LENGTH(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active mac sign * operation), or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length); /** Finish the calculation of the MAC of a message and compare it with * an expected value. * * The application must call psa_mac_verify_setup() before calling this function. * This function calculates the MAC of the message formed by concatenating * the inputs passed to preceding calls to psa_mac_update(). It then * compares the calculated MAC with the expected MAC passed as a * parameter to this function. * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_mac_abort(). * * \note Implementations shall make the best effort to ensure that the * comparison between the actual MAC and the expected MAC is performed * in constant time. * * \param[in,out] operation Active MAC operation. * \param[in] mac Buffer containing the expected MAC value. * \param mac_length Size of the \p mac buffer in bytes. * * \retval #PSA_SUCCESS * The expected MAC is identical to the actual MAC of the message. * \retval #PSA_ERROR_INVALID_SIGNATURE * The MAC of the message was calculated successfully, but it * differs from the expected MAC. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active mac verify * operation), or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length); /** Abort a MAC operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * psa_mac_sign_setup() or psa_mac_verify_setup() again. * * You may call this function any time after the operation object has * been initialized by one of the methods described in #psa_mac_operation_t. * * In particular, calling psa_mac_abort() after the operation has been * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or * psa_mac_verify_finish() is safe and has no effect. * * \param[in,out] operation Initialized MAC operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_abort(psa_mac_operation_t *operation); /**@}*/ /** \defgroup cipher Symmetric ciphers * @{ */ /** Encrypt a message using a symmetric cipher. * * This function encrypts a message with a random IV (initialization * vector). Use the multipart operation interface with a * #psa_cipher_operation_t object to provide other forms of IV. * * \param key Identifier of the key to use for the operation. * It must allow the usage #PSA_KEY_USAGE_ENCRYPT. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param[in] input Buffer containing the message to encrypt. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * The output contains the IV followed by * the ciphertext proper. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Decrypt a message using a symmetric cipher. * * This function decrypts a message encrypted with a symmetric cipher. * * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_DECRYPT. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param[in] input Buffer containing the message to decrypt. * This consists of the IV followed by the * ciphertext proper. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the plaintext is to be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** The type of the state data structure for multipart cipher operations. * * Before calling any function on a cipher operation object, the application * must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_cipher_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_cipher_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, * for example: * \code * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; * \endcode * - Assign the result of the function psa_cipher_operation_init() * to the structure, for example: * \code * psa_cipher_operation_t operation; * operation = psa_cipher_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_cipher_operation_s psa_cipher_operation_t; /** \def PSA_CIPHER_OPERATION_INIT * * This macro returns a suitable initializer for a cipher operation object of * type #psa_cipher_operation_t. */ /** Return an initial value for a cipher operation object. */ static psa_cipher_operation_t psa_cipher_operation_init(void); /** Set the key for a multipart symmetric encryption operation. * * The sequence of operations to encrypt a message with a symmetric cipher * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_cipher_operation_t, e.g. * #PSA_CIPHER_OPERATION_INIT. * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to * generate or set the IV (initialization vector). You should use * psa_cipher_generate_iv() unless the protocol you are implementing * requires a specific IV value. * -# Call psa_cipher_update() zero, one or more times, passing a fragment * of the message each time. * -# Call psa_cipher_finish(). * * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), * the operation will need to be reset by a call to psa_cipher_abort(). The * application may call psa_cipher_abort() at any time after the operation * has been initialized. * * After a successful call to psa_cipher_encrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_cipher_finish(). * - A call to psa_cipher_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_ENCRYPT. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Set the key for a multipart symmetric decryption operation. * * The sequence of operations to decrypt a message with a symmetric cipher * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_cipher_operation_t, e.g. * #PSA_CIPHER_OPERATION_INIT. * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the * decryption. If the IV is prepended to the ciphertext, you can call * psa_cipher_update() on a buffer containing the IV followed by the * beginning of the message. * -# Call psa_cipher_update() zero, one or more times, passing a fragment * of the message each time. * -# Call psa_cipher_finish(). * * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), * the operation will need to be reset by a call to psa_cipher_abort(). The * application may call psa_cipher_abort() at any time after the operation * has been initialized. * * After a successful call to psa_cipher_decrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_cipher_finish(). * - A call to psa_cipher_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_DECRYPT. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Generate an IV for a symmetric encryption operation. * * This function generates a random IV (initialization vector), nonce * or initial counter value for the encryption operation as appropriate * for the chosen algorithm, key type and key size. * * The application must call psa_cipher_encrypt_setup() before * calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_cipher_abort(). * * \param[in,out] operation Active cipher operation. * \param[out] iv Buffer where the generated IV is to be written. * \param iv_size Size of the \p iv buffer in bytes. * \param[out] iv_length On success, the number of bytes of the * generated IV. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p iv buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, with no IV set), * or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, uint8_t *iv, size_t iv_size, size_t *iv_length); /** Set the IV for a symmetric encryption or decryption operation. * * This function sets the IV (initialization vector), nonce * or initial counter value for the encryption or decryption operation. * * The application must call psa_cipher_encrypt_setup() before * calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_cipher_abort(). * * \note When encrypting, applications should use psa_cipher_generate_iv() * instead of this function, unless implementing a protocol that requires * a non-random IV. * * \param[in,out] operation Active cipher operation. * \param[in] iv Buffer containing the IV to use. * \param iv_length Size of the IV in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p iv is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active cipher * encrypt operation, with no IV set), or the library has not been * previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length); /** Encrypt or decrypt a message fragment in an active cipher operation. * * Before calling this function, you must: * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). * The choice of setup function determines whether this function * encrypts or decrypts its input. * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() * (recommended when encrypting) or psa_cipher_set_iv(). * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_cipher_abort(). * * \param[in,out] operation Active cipher operation. * \param[in] input Buffer containing the message fragment to * encrypt or decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, with an IV set * if required for the algorithm), or the library has not been * previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Finish encrypting or decrypting a message in a cipher operation. * * The application must call psa_cipher_encrypt_setup() or * psa_cipher_decrypt_setup() before calling this function. The choice * of setup function determines whether this function encrypts or * decrypts its input. * * This function finishes the encryption or decryption of the message * formed by concatenating the inputs passed to preceding calls to * psa_cipher_update(). * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_cipher_abort(). * * \param[in,out] operation Active cipher operation. * \param[out] output Buffer where the output is to be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total input size passed to this operation is not valid for * this particular algorithm. For example, the algorithm is a based * on block cipher and requires a whole number of blocks, but the * total input size is not a multiple of the block size. * \retval #PSA_ERROR_INVALID_PADDING * This is a decryption operation for an algorithm that includes * padding, and the ciphertext does not contain valid padding. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, with an IV set * if required for the algorithm), or the library has not been * previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length); /** Abort a cipher operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. * * You may call this function any time after the operation object has * been initialized as described in #psa_cipher_operation_t. * * In particular, calling psa_cipher_abort() after the operation has been * terminated by a call to psa_cipher_abort() or psa_cipher_finish() * is safe and has no effect. * * \param[in,out] operation Initialized cipher operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); /**@}*/ /** \defgroup aead Authenticated encryption with associated data (AEAD) * @{ */ /** Process an authenticated encryption operation. * * \param key Identifier of the key to use for the * operation. It must allow the usage * #PSA_KEY_USAGE_ENCRYPT. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param[in] nonce Nonce or IV to use. * \param nonce_length Size of the \p nonce buffer in bytes. * \param[in] additional_data Additional data that will be authenticated * but not encrypted. * \param additional_data_length Size of \p additional_data in bytes. * \param[in] plaintext Data that will be authenticated and * encrypted. * \param plaintext_length Size of \p plaintext in bytes. * \param[out] ciphertext Output buffer for the authenticated and * encrypted data. The additional data is not * part of this output. For algorithms where the * encrypted data and the authentication tag * are defined as separate outputs, the * authentication tag is appended to the * encrypted data. * \param ciphertext_size Size of the \p ciphertext buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, * \p alg, \p plaintext_length) where * \c key_type is the type of \p key. * - #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p * plaintext_length) evaluates to the maximum * ciphertext size of any supported AEAD * encryption. * \param[out] ciphertext_length On success, the size of the output * in the \p ciphertext buffer. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p ciphertext_size is too small. * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, \p alg, * \p plaintext_length) or * #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length) can be used to * determine the required buffer size. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length); /** Process an authenticated decryption operation. * * \param key Identifier of the key to use for the * operation. It must allow the usage * #PSA_KEY_USAGE_DECRYPT. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param[in] nonce Nonce or IV to use. * \param nonce_length Size of the \p nonce buffer in bytes. * \param[in] additional_data Additional data that has been authenticated * but not encrypted. * \param additional_data_length Size of \p additional_data in bytes. * \param[in] ciphertext Data that has been authenticated and * encrypted. For algorithms where the * encrypted data and the authentication tag * are defined as separate inputs, the buffer * must contain the encrypted data followed * by the authentication tag. * \param ciphertext_length Size of \p ciphertext in bytes. * \param[out] plaintext Output buffer for the decrypted data. * \param plaintext_size Size of the \p plaintext buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, * \p alg, \p ciphertext_length) where * \c key_type is the type of \p key. * - #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p * ciphertext_length) evaluates to the maximum * plaintext size of any supported AEAD * decryption. * \param[out] plaintext_length On success, the size of the output * in the \p plaintext buffer. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The ciphertext is not authentic. * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p plaintext_size is too small. * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, \p alg, * \p ciphertext_length) or * #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length) can be used * to determine the required buffer size. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length); /** The type of the state data structure for multipart AEAD operations. * * Before calling any function on an AEAD operation object, the application * must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_aead_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_aead_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, * for example: * \code * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; * \endcode * - Assign the result of the function psa_aead_operation_init() * to the structure, for example: * \code * psa_aead_operation_t operation; * operation = psa_aead_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_aead_operation_s psa_aead_operation_t; /** \def PSA_AEAD_OPERATION_INIT * * This macro returns a suitable initializer for an AEAD operation object of * type #psa_aead_operation_t. */ /** Return an initial value for an AEAD operation object. */ static psa_aead_operation_t psa_aead_operation_init(void); /** Set the key for a multipart authenticated encryption operation. * * The sequence of operations to encrypt a message with authentication * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_aead_operation_t, e.g. * #PSA_AEAD_OPERATION_INIT. * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. * -# If needed, call psa_aead_set_lengths() to specify the length of the * inputs to the subsequent calls to psa_aead_update_ad() and * psa_aead_update(). See the documentation of psa_aead_set_lengths() * for details. * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to * generate or set the nonce. You should use * psa_aead_generate_nonce() unless the protocol you are implementing * requires a specific nonce value. * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment * of the non-encrypted additional authenticated data each time. * -# Call psa_aead_update() zero, one or more times, passing a fragment * of the message to encrypt each time. * -# Call psa_aead_finish(). * * If an error occurs at any step after a call to psa_aead_encrypt_setup(), * the operation will need to be reset by a call to psa_aead_abort(). The * application may call psa_aead_abort() at any time after the operation * has been initialized. * * After a successful call to psa_aead_encrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_aead_finish(). * - A call to psa_aead_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_aead_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_ENCRYPT. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Set the key for a multipart authenticated decryption operation. * * The sequence of operations to decrypt a message with authentication * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_aead_operation_t, e.g. * #PSA_AEAD_OPERATION_INIT. * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. * -# If needed, call psa_aead_set_lengths() to specify the length of the * inputs to the subsequent calls to psa_aead_update_ad() and * psa_aead_update(). See the documentation of psa_aead_set_lengths() * for details. * -# Call psa_aead_set_nonce() with the nonce for the decryption. * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment * of the non-encrypted additional authenticated data each time. * -# Call psa_aead_update() zero, one or more times, passing a fragment * of the ciphertext to decrypt each time. * -# Call psa_aead_verify(). * * If an error occurs at any step after a call to psa_aead_decrypt_setup(), * the operation will need to be reset by a call to psa_aead_abort(). The * application may call psa_aead_abort() at any time after the operation * has been initialized. * * After a successful call to psa_aead_decrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_aead_verify(). * - A call to psa_aead_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_aead_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_DECRYPT. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or the * library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Generate a random nonce for an authenticated encryption operation. * * This function generates a random nonce for the authenticated encryption * operation with an appropriate size for the chosen algorithm, key type * and key size. * * The application must call psa_aead_encrypt_setup() before * calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param[out] nonce Buffer where the generated nonce is to be * written. * \param nonce_size Size of the \p nonce buffer in bytes. * \param[out] nonce_length On success, the number of bytes of the * generated nonce. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p nonce buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active aead encrypt * operation, with no nonce set), or the library has not been * previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, uint8_t *nonce, size_t nonce_size, size_t *nonce_length); /** Set the nonce for an authenticated encryption or decryption operation. * * This function sets the nonce for the authenticated * encryption or decryption operation. * * The application must call psa_aead_encrypt_setup() or * psa_aead_decrypt_setup() before calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \note When encrypting, applications should use psa_aead_generate_nonce() * instead of this function, unless implementing a protocol that requires * a non-random IV. * * \param[in,out] operation Active AEAD operation. * \param[in] nonce Buffer containing the nonce to use. * \param nonce_length Size of the nonce in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p nonce is not acceptable for the chosen algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, with no nonce * set), or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length); /** Declare the lengths of the message and additional data for AEAD. * * The application must call this function before calling * psa_aead_update_ad() or psa_aead_update() if the algorithm for * the operation requires it. If the algorithm does not require it, * calling this function is optional, but if this function is called * then the implementation must enforce the lengths. * * You may call this function before or after setting the nonce with * psa_aead_set_nonce() or psa_aead_generate_nonce(). * * - For #PSA_ALG_CCM, calling this function is required. * - For the other AEAD algorithms defined in this specification, calling * this function is not required. * - For vendor-defined algorithm, refer to the vendor documentation. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param ad_length Size of the non-encrypted additional * authenticated data in bytes. * \param plaintext_length Size of the plaintext to encrypt in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * At least one of the lengths is not acceptable for the chosen * algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, and * psa_aead_update_ad() and psa_aead_update() must not have been * called yet), or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length); /** Pass additional data to an active AEAD operation. * * Additional data is authenticated, but not encrypted. * * You may call this function multiple times to pass successive fragments * of the additional data. You may not call this function after passing * data to encrypt or decrypt with psa_aead_update(). * * Before calling this function, you must: * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, * there is no guarantee that the input is valid. Therefore, until * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, * treat the input as untrusted and prepare to undo any action that * depends on the input if psa_aead_verify() returns an error status. * * \param[in,out] operation Active AEAD operation. * \param[in] input Buffer containing the fragment of * additional data. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total input length overflows the additional data length that * was previously specified with psa_aead_set_lengths(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, have a nonce * set, have lengths set if required by the algorithm, and * psa_aead_update() must not have been called yet), or the library * has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, const uint8_t *input, size_t input_length); /** Encrypt or decrypt a message fragment in an active AEAD operation. * * Before calling this function, you must: * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). * The choice of setup function determines whether this function * encrypts or decrypts its input. * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). * 3. Call psa_aead_update_ad() to pass all the additional data. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, * there is no guarantee that the input is valid. Therefore, until * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: * - Do not use the output in any way other than storing it in a * confidential location. If you take any action that depends * on the tentative decrypted data, this action will need to be * undone if the input turns out not to be valid. Furthermore, * if an adversary can observe that this action took place * (for example through timing), they may be able to use this * fact as an oracle to decrypt any message encrypted with the * same key. * - In particular, do not copy the output anywhere but to a * memory or storage space that you have exclusive access to. * * This function does not require the input to be aligned to any * particular block boundary. If the implementation can only process * a whole block at a time, it must consume all the input provided, but * it may delay the end of the corresponding output until a subsequent * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() * provides sufficient input. The amount of data that can be delayed * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. * * \param[in,out] operation Active AEAD operation. * \param[in] input Buffer containing the message fragment to * encrypt or decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param output_size Size of the \p output buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, * \c alg, \p input_length) where * \c key_type is the type of key and \c alg is * the algorithm that were used to set up the * operation. * - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p * input_length) evaluates to the maximum * output size of any supported AEAD * algorithm. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or * #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to * determine the required buffer size. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total length of input to psa_aead_update_ad() so far is * less than the additional data length that was previously * specified with psa_aead_set_lengths(), or * the total input length overflows the plaintext length that * was previously specified with psa_aead_set_lengths(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, have a nonce * set, and have lengths set if required by the algorithm), or the * library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_update(psa_aead_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Finish encrypting a message in an AEAD operation. * * The operation must have been set up with psa_aead_encrypt_setup(). * * This function finishes the authentication of the additional data * formed by concatenating the inputs passed to preceding calls to * psa_aead_update_ad() with the plaintext formed by concatenating the * inputs passed to preceding calls to psa_aead_update(). * * This function has two output buffers: * - \p ciphertext contains trailing ciphertext that was buffered from * preceding calls to psa_aead_update(). * - \p tag contains the authentication tag. * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param[out] ciphertext Buffer where the last part of the ciphertext * is to be written. * \param ciphertext_size Size of the \p ciphertext buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, * \c alg) where \c key_type is the type of key * and \c alg is the algorithm that were used to * set up the operation. * - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to * the maximum output size of any supported AEAD * algorithm. * \param[out] ciphertext_length On success, the number of bytes of * returned ciphertext. * \param[out] tag Buffer where the authentication tag is * to be written. * \param tag_size Size of the \p tag buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c * key_type, \c key_bits, \c alg) where * \c key_type and \c key_bits are the type and * bit-size of the key, and \c alg is the * algorithm that were used in the call to * psa_aead_encrypt_setup(). * - #PSA_AEAD_TAG_MAX_SIZE evaluates to the * maximum tag size of any supported AEAD * algorithm. * \param[out] tag_length On success, the number of bytes * that make up the returned tag. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p ciphertext or \p tag buffer is too small. * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, \c alg) or * #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE can be used to determine the * required \p ciphertext buffer size. #PSA_AEAD_TAG_LENGTH(\c key_type, * \c key_bits, \c alg) or #PSA_AEAD_TAG_MAX_SIZE can be used to * determine the required \p tag buffer size. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total length of input to psa_aead_update_ad() so far is * less than the additional data length that was previously * specified with psa_aead_set_lengths(), or * the total length of input to psa_aead_update() so far is * less than the plaintext length that was previously * specified with psa_aead_set_lengths(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active encryption * operation with a nonce set), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_finish(psa_aead_operation_t *operation, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag, size_t tag_size, size_t *tag_length); /** Finish authenticating and decrypting a message in an AEAD operation. * * The operation must have been set up with psa_aead_decrypt_setup(). * * This function finishes the authenticated decryption of the message * components: * * - The additional data consisting of the concatenation of the inputs * passed to preceding calls to psa_aead_update_ad(). * - The ciphertext consisting of the concatenation of the inputs passed to * preceding calls to psa_aead_update(). * - The tag passed to this function call. * * If the authentication tag is correct, this function outputs any remaining * plaintext and reports success. If the authentication tag is not correct, * this function returns #PSA_ERROR_INVALID_SIGNATURE. * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \note Implementations shall make the best effort to ensure that the * comparison between the actual tag and the expected tag is performed * in constant time. * * \param[in,out] operation Active AEAD operation. * \param[out] plaintext Buffer where the last part of the plaintext * is to be written. This is the remaining data * from previous calls to psa_aead_update() * that could not be processed until the end * of the input. * \param plaintext_size Size of the \p plaintext buffer in bytes. * This must be appropriate for the selected algorithm and key: * - A sufficient output size is * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, * \c alg) where \c key_type is the type of key * and \c alg is the algorithm that were used to * set up the operation. * - #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE evaluates to * the maximum output size of any supported AEAD * algorithm. * \param[out] plaintext_length On success, the number of bytes of * returned plaintext. * \param[in] tag Buffer containing the authentication tag. * \param tag_length Size of the \p tag buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculations were successful, but the authentication tag is * not correct. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p plaintext buffer is too small. * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, \c alg) or * #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE can be used to determine the * required buffer size. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total length of input to psa_aead_update_ad() so far is * less than the additional data length that was previously * specified with psa_aead_set_lengths(), or * the total length of input to psa_aead_update() so far is * less than the plaintext length that was previously * specified with psa_aead_set_lengths(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active decryption * operation with a nonce set), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_verify(psa_aead_operation_t *operation, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length, const uint8_t *tag, size_t tag_length); /** Abort an AEAD operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. * * You may call this function any time after the operation object has * been initialized as described in #psa_aead_operation_t. * * In particular, calling psa_aead_abort() after the operation has been * terminated by a call to psa_aead_abort(), psa_aead_finish() or * psa_aead_verify() is safe and has no effect. * * \param[in,out] operation Initialized AEAD operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_abort(psa_aead_operation_t *operation); /**@}*/ /** \defgroup asymmetric Asymmetric cryptography * @{ */ /** * \brief Sign a message with a private key. For hash-and-sign algorithms, * this includes the hashing step. * * \note To perform a multi-part hash-and-sign signature algorithm, first use * a multi-part hash operation and then pass the resulting hash to * psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the * hash algorithm to use. * * \param[in] key Identifier of the key to use for the operation. * It must be an asymmetric key pair. The key must * allow the usage #PSA_KEY_USAGE_SIGN_MESSAGE. * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) * is true), that is compatible with the type of * \p key. * \param[in] input The input message to sign. * \param[in] input_length Size of the \p input buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. This * must be appropriate for the selected * algorithm and key: * - The required signature size is * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and * bit-size respectively of key. * - #PSA_SIGNATURE_MAX_SIZE evaluates to the * maximum signature size of any supported * signature algorithm. * \param[out] signature_length On success, the number of bytes that make up * the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, * or it does not permit the requested algorithm. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** \brief Verify the signature of a message with a public key, using * a hash-and-sign verification algorithm. * * \note To perform a multi-part hash-and-sign signature verification * algorithm, first use a multi-part hash operation to hash the message * and then pass the resulting hash to psa_verify_hash(). * PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm * to use. * * \param[in] key Identifier of the key to use for the operation. * It must be a public key or an asymmetric key * pair. The key must allow the usage * #PSA_KEY_USAGE_VERIFY_MESSAGE. * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) * is true), that is compatible with the type of * \p key. * \param[in] input The message whose signature is to be verified. * \param[in] input_length Size of the \p input buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, * or it does not permit the requested algorithm. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed signature * is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_verify_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length); /** * \brief Sign a hash or short message with a private key. * * Note that to perform a hash-and-sign signature algorithm, you must * first calculate the hash by calling psa_hash_setup(), psa_hash_update() * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). * Then pass the resulting hash as the \p hash * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) * to determine the hash algorithm to use. * * \param key Identifier of the key to use for the operation. * It must be an asymmetric key pair. The key must * allow the usage #PSA_KEY_USAGE_SIGN_HASH. * \param alg A signature algorithm (PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) * is true), that is compatible with * the type of \p key. * \param[in] hash The hash or message to sign. * \param hash_length Size of the \p hash buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Verify the signature of a hash or short message using a public key. * * Note that to perform a hash-and-sign signature algorithm, you must * first calculate the hash by calling psa_hash_setup(), psa_hash_update() * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). * Then pass the resulting hash as the \p hash * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) * to determine the hash algorithm to use. * * \param key Identifier of the key to use for the operation. It * must be a public key or an asymmetric key pair. The * key must allow the usage * #PSA_KEY_USAGE_VERIFY_HASH. * \param alg A signature algorithm (PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) * is true), that is compatible with * the type of \p key. * \param[in] hash The hash or message whose signature is to be * verified. * \param hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Encrypt a short message with a public key. * * \param key Identifier of the key to use for the operation. * It must be a public key or an asymmetric key * pair. It must allow the usage * #PSA_KEY_USAGE_ENCRYPT. * \param alg An asymmetric encryption algorithm that is * compatible with the type of \p key. * \param[in] input The message to encrypt. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the * encryption algorithm. * If the algorithm does not support a * salt, pass \c NULL. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass \c NULL. * * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param salt_length Size of the \p salt buffer in bytes. * If \p salt is \c NULL, pass 0. * \param[out] output Buffer where the encrypted message is to * be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length); /** * \brief Decrypt a short message with a private key. * * \param key Identifier of the key to use for the operation. * It must be an asymmetric key pair. It must * allow the usage #PSA_KEY_USAGE_DECRYPT. * \param alg An asymmetric encryption algorithm that is * compatible with the type of \p key. * \param[in] input The message to decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the * encryption algorithm. * If the algorithm does not support a * salt, pass \c NULL. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass \c NULL. * * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param salt_length Size of the \p salt buffer in bytes. * If \p salt is \c NULL, pass 0. * \param[out] output Buffer where the decrypted message is to * be written. * \param output_size Size of the \c output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_INVALID_PADDING \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length); /**@}*/ /** \defgroup key_derivation Key derivation and pseudorandom generation * @{ */ /** The type of the state data structure for key derivation operations. * * Before calling any function on a key derivation operation object, the * application must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_key_derivation_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_key_derivation_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, * for example: * \code * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; * \endcode * - Assign the result of the function psa_key_derivation_operation_init() * to the structure, for example: * \code * psa_key_derivation_operation_t operation; * operation = psa_key_derivation_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_key_derivation_s psa_key_derivation_operation_t; /** \def PSA_KEY_DERIVATION_OPERATION_INIT * * This macro returns a suitable initializer for a key derivation operation * object of type #psa_key_derivation_operation_t. */ /** Return an initial value for a key derivation operation object. */ static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); /** Set up a key derivation operation. * * A key derivation algorithm takes some inputs and uses them to generate * a byte stream in a deterministic way. * This byte stream can be used to produce keys and other * cryptographic material. * * To derive a key: * -# Start with an initialized object of type #psa_key_derivation_operation_t. * -# Call psa_key_derivation_setup() to select the algorithm. * -# Provide the inputs for the key derivation by calling * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() * as appropriate. Which inputs are needed, in what order, and whether * they may be keys and if so of what type depends on the algorithm. * -# Optionally set the operation's maximum capacity with * psa_key_derivation_set_capacity(). You may do this before, in the middle * of or after providing inputs. For some algorithms, this step is mandatory * because the output depends on the maximum capacity. * -# To derive a key, call psa_key_derivation_output_key() or * psa_key_derivation_output_key_custom(). * To derive a byte string for a different purpose, call * psa_key_derivation_output_bytes(). * Successive calls to these functions use successive output bytes * calculated by the key derivation algorithm. * -# Clean up the key derivation operation object with * psa_key_derivation_abort(). * * If this function returns an error, the key derivation operation object is * not changed. * * If an error occurs at any step after a call to psa_key_derivation_setup(), * the operation will need to be reset by a call to psa_key_derivation_abort(). * * Implementations must reject an attempt to derive a key of size 0. * * \param[in,out] operation The key derivation operation object * to set up. It must * have been initialized but not set up yet. * \param alg The key derivation algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c alg is not a key derivation algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * \c alg is not supported or is not a key derivation algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_setup( psa_key_derivation_operation_t *operation, psa_algorithm_t alg); /** Retrieve the current capacity of a key derivation operation. * * The capacity of a key derivation is the maximum number of bytes that it can * return. When you get *N* bytes of output from a key derivation operation, * this reduces its capacity by *N*. * * \param[in] operation The operation to query. * \param[out] capacity On success, the capacity of the operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_get_capacity( const psa_key_derivation_operation_t *operation, size_t *capacity); /** Set the maximum capacity of a key derivation operation. * * The capacity of a key derivation operation is the maximum number of bytes * that the key derivation operation can return from this point onwards. * * \param[in,out] operation The key derivation operation object to modify. * \param capacity The new capacity of the operation. * It must be less or equal to the operation's * current capacity. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p capacity is larger than the operation's current capacity. * In this case, the operation object remains valid and its capacity * remains unchanged. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or the * library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_set_capacity( psa_key_derivation_operation_t *operation, size_t capacity); /** Use the maximum possible capacity for a key derivation operation. * * Use this value as the capacity argument when setting up a key derivation * to indicate that the operation should have the maximum possible capacity. * The value of the maximum possible capacity depends on the key derivation * algorithm. */ #define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t) (-1)) /** Provide an input for key derivation or key agreement. * * Which inputs are required and in what order depends on the algorithm. * Refer to the documentation of each key derivation or key agreement * algorithm for information. * * This function passes direct inputs, which is usually correct for * non-secret inputs. To pass a secret input, which should be in a key * object, call psa_key_derivation_input_key() instead of this function. * Refer to the documentation of individual step types * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) * for more information. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to use. * It must have been set up with * psa_key_derivation_setup() and must not * have produced any output yet. * \param step Which step the input data is for. * \param[in] data Input data to use. * \param data_length Size of the \p data buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c step is not compatible with the operation's algorithm, or * \c step does not allow direct inputs. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid for this input \p step, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_input_bytes( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length); /** Provide a numeric input for key derivation or key agreement. * * Which inputs are required and in what order depends on the algorithm. * However, when an algorithm requires a particular order, numeric inputs * usually come first as they tend to be configuration parameters. * Refer to the documentation of each key derivation or key agreement * algorithm for information. * * This function is used for inputs which are fixed-size non-negative * integers. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to use. * It must have been set up with * psa_key_derivation_setup() and must not * have produced any output yet. * \param step Which step the input data is for. * \param[in] value The value of the numeric input. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c step is not compatible with the operation's algorithm, or * \c step does not allow numeric inputs. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid for this input \p step, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_input_integer( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, uint64_t value); /** Provide an input for key derivation in the form of a key. * * Which inputs are required and in what order depends on the algorithm. * Refer to the documentation of each key derivation or key agreement * algorithm for information. * * This function obtains input from a key object, which is usually correct for * secret inputs or for non-secret personalization strings kept in the key * store. To pass a non-secret parameter which is not in the key store, * call psa_key_derivation_input_bytes() instead of this function. * Refer to the documentation of individual step types * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) * for more information. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to use. * It must have been set up with * psa_key_derivation_setup() and must not * have produced any output yet. * \param step Which step the input data is for. * \param key Identifier of the key. It must have an * appropriate type for step and must allow the * usage #PSA_KEY_USAGE_DERIVE or * #PSA_KEY_USAGE_VERIFY_DERIVATION (see note) * and the algorithm used by the operation. * * \note Once all inputs steps are completed, the operations will allow: * - psa_key_derivation_output_bytes() if each input was either a direct input * or a key with #PSA_KEY_USAGE_DERIVE set; * - psa_key_derivation_output_key() or psa_key_derivation_output_key_custom() * if the input for step * #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD * was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was * either a direct input or a key with #PSA_KEY_USAGE_DERIVE set; * - psa_key_derivation_verify_bytes() if each input was either a direct input * or a key with #PSA_KEY_USAGE_VERIFY_DERIVATION set; * - psa_key_derivation_verify_key() under the same conditions as * psa_key_derivation_verify_bytes(). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key allows neither #PSA_KEY_USAGE_DERIVE nor * #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this * algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c step is not compatible with the operation's algorithm, or * \c step does not allow key inputs of the given type * or does not allow key inputs at all. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid for this input \p step, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_input_key( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, mbedtls_svc_key_id_t key); /** Perform a key agreement and use the shared secret as input to a key * derivation. * * A key agreement algorithm takes two inputs: a private key \p private_key * a public key \p peer_key. * The result of this function is passed as input to a key derivation. * The output of this key derivation can be extracted by reading from the * resulting operation to produce keys and other cryptographic material. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to use. * It must have been set up with * psa_key_derivation_setup() with a * key agreement and derivation algorithm * \c alg (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) * is false). * The operation must be ready for an * input of the type given by \p step. * \param step Which step the input data is for. * \param private_key Identifier of the private key to use. It must * allow the usage #PSA_KEY_USAGE_DERIVE. * \param[in] peer_key Public key of the peer. The peer key must be in the * same format that psa_import_key() accepts for the * public key type corresponding to the type of * private_key. That is, this function performs the * equivalent of * #psa_import_key(..., * `peer_key`, `peer_key_length`) where * with key attributes indicating the public key * type corresponding to the type of `private_key`. * For example, for EC keys, this means that peer_key * is interpreted as a point on the curve that the * private key is on. The standard formats for public * keys are documented in the documentation of * psa_export_public_key(). * \param peer_key_length Size of \p peer_key in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \c private_key is not compatible with \c alg, * or \p peer_key is not valid for \c alg or not compatible with * \c private_key, or \c step does not allow an input resulting * from a key agreement. * \retval #PSA_ERROR_NOT_SUPPORTED * \c alg is not supported or is not a key derivation algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid for this key agreement \p step, * or the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_key_agreement( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, mbedtls_svc_key_id_t private_key, const uint8_t *peer_key, size_t peer_key_length); /** Read some data from a key derivation operation. * * This function calculates output bytes from a key derivation algorithm and * return those bytes. * If you view the key derivation's output as a stream of bytes, this * function destructively reads the requested number of bytes from the * stream. * The operation's capacity decreases by the number of bytes read. * * If this function returns an error status other than * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to read from. * \param[out] output Buffer where the output will be written. * \param output_length Number of bytes to output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * One of the inputs was a key whose policy didn't allow * #PSA_KEY_USAGE_DERIVE. * \retval #PSA_ERROR_INSUFFICIENT_DATA * The operation's capacity was less than * \p output_length bytes. Note that in this case, * no output is written to the output buffer. * The operation's capacity is set to 0, thus * subsequent calls to this function will not * succeed, even with a smaller output buffer. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_output_bytes( psa_key_derivation_operation_t *operation, uint8_t *output, size_t output_length); /** Derive a key from an ongoing key derivation operation. * * This function calculates output bytes from a key derivation algorithm * and uses those bytes to generate a key deterministically. * The key's location, usage policy, type and size are taken from * \p attributes. * * If you view the key derivation's output as a stream of bytes, this * function destructively reads as many bytes as required from the * stream. * The operation's capacity decreases by the number of bytes read. * * If this function returns an error status other than * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * How much output is produced and consumed from the operation, and how * the key is derived, depends on the key type and on the key size * (denoted \c bits below): * * - For key types for which the key is an arbitrary sequence of bytes * of a given size, this function is functionally equivalent to * calling #psa_key_derivation_output_bytes * and passing the resulting output to #psa_import_key. * However, this function has a security benefit: * if the implementation provides an isolation boundary then * the key material is not exposed outside the isolation boundary. * As a consequence, for these key types, this function always consumes * exactly (\c bits / 8) bytes from the operation. * The following key types defined in this specification follow this scheme: * * - #PSA_KEY_TYPE_AES; * - #PSA_KEY_TYPE_ARIA; * - #PSA_KEY_TYPE_CAMELLIA; * - #PSA_KEY_TYPE_DERIVE; * - #PSA_KEY_TYPE_HMAC; * - #PSA_KEY_TYPE_PASSWORD_HASH. * * - For ECC keys on a Montgomery elliptic curve * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a * Montgomery curve), this function always draws a byte string whose * length is determined by the curve, and sets the mandatory bits * accordingly. That is: * * - Curve25519 (#PSA_ECC_FAMILY_MONTGOMERY, 255 bits): draw a 32-byte * string and process it as specified in RFC 7748 §5. * - Curve448 (#PSA_ECC_FAMILY_MONTGOMERY, 448 bits): draw a 56-byte * string and process it as specified in RFC 7748 §5. * * - For key types for which the key is represented by a single sequence of * \c bits bits with constraints as to which bit sequences are acceptable, * this function draws a byte string of length (\c bits / 8) bytes rounded * up to the nearest whole number of bytes. If the resulting byte string * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. * This process is repeated until an acceptable byte string is drawn. * The byte string drawn from the operation is interpreted as specified * for the output produced by psa_export_key(). * The following key types defined in this specification follow this scheme: * * - #PSA_KEY_TYPE_DES. * Force-set the parity bits, but discard forbidden weak keys. * For 2-key and 3-key triple-DES, the three keys are generated * successively (for example, for 3-key triple-DES, * if the first 8 bytes specify a weak key and the next 8 bytes do not, * discard the first 8 bytes, use the next 8 bytes as the first key, * and continue reading output from the operation to derive the other * two keys). * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) * where \c group designates any Diffie-Hellman group) and * ECC keys on a Weierstrass elliptic curve * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a * Weierstrass curve). * For these key types, interpret the byte string as integer * in big-endian order. Discard it if it is not in the range * [0, *N* - 2] where *N* is the boundary of the private key domain * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, * or the order of the curve's base point for ECC). * Add 1 to the resulting integer and use this as the private key *x*. * This method allows compliance to NIST standards, specifically * the methods titled "key-pair generation by testing candidates" * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, * in FIPS 186-4 §B.1.2 for DSA, and * in NIST SP 800-56A §5.6.1.2.2 or * FIPS 186-4 §B.4.2 for elliptic curve keys. * * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, * the way in which the operation output is consumed is * implementation-defined. * * In all cases, the data that is read is discarded from the operation. * The operation's capacity is decreased by the number of bytes read. * * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, * the input to that step must be provided with psa_key_derivation_input_key(). * Future versions of this specification may include additional restrictions * on the derived key based on the attributes and strength of the secret key. * * \note This function is equivalent to calling * psa_key_derivation_output_key_custom() * with the custom production parameters #PSA_CUSTOM_KEY_PARAMETERS_INIT * and `custom_data_length == 0` (i.e. `custom_data` is empty). * * \param[in] attributes The attributes for the new key. * If the key type to be created is * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in * the policy must be the same as in the current * operation. * \param[in,out] operation The key derivation operation object to read from. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_INSUFFICIENT_DATA * There was not enough data to create the desired key. * Note that in this case, no output is written to the output buffer. * The operation's capacity is set to 0, thus subsequent calls to * this function will not succeed, even with a smaller output buffer. * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular location. * \retval #PSA_ERROR_INVALID_ARGUMENT * The provided key attributes are not valid for the operation. * \retval #PSA_ERROR_NOT_PERMITTED * The #PSA_KEY_DERIVATION_INPUT_SECRET or * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a * key; or one of the inputs was a key whose policy didn't allow * #PSA_KEY_USAGE_DERIVE. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, mbedtls_svc_key_id_t *key); /** Derive a key from an ongoing key derivation operation with custom * production parameters. * * See the description of psa_key_derivation_out_key() for the operation of * this function with the default production parameters. * Mbed TLS currently does not currently support any non-default production * parameters. * * \note This function is experimental and may change in future minor * versions of Mbed TLS. * * \param[in] attributes The attributes for the new key. * If the key type to be created is * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in * the policy must be the same as in the current * operation. * \param[in,out] operation The key derivation operation object to read from. * \param[in] custom Customization parameters for the key generation. * When this is #PSA_CUSTOM_KEY_PARAMETERS_INIT * with \p custom_data_length = 0, * this function is equivalent to * psa_key_derivation_output_key(). * \param[in] custom_data Variable-length data associated with \c custom. * \param custom_data_length * Length of `custom_data` in bytes. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_INSUFFICIENT_DATA * There was not enough data to create the desired key. * Note that in this case, no output is written to the output buffer. * The operation's capacity is set to 0, thus subsequent calls to * this function will not succeed, even with a smaller output buffer. * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular location. * \retval #PSA_ERROR_INVALID_ARGUMENT * The provided key attributes are not valid for the operation. * \retval #PSA_ERROR_NOT_PERMITTED * The #PSA_KEY_DERIVATION_INPUT_SECRET or * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a * key; or one of the inputs was a key whose policy didn't allow * #PSA_KEY_USAGE_DERIVE. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_output_key_custom( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, const psa_custom_key_parameters_t *custom, const uint8_t *custom_data, size_t custom_data_length, mbedtls_svc_key_id_t *key); #ifndef __cplusplus /* Omitted when compiling in C++, because one of the parameters is a * pointer to a struct with a flexible array member, and that is not * standard C++. * https://github.com/Mbed-TLS/mbedtls/issues/9020 */ /** Derive a key from an ongoing key derivation operation with custom * production parameters. * * \note * This is a deprecated variant of psa_key_derivation_output_key_custom(). * It is equivalent except that the associated variable-length data * is passed in `params->data` instead of a separate parameter. * This function will be removed in a future version of Mbed TLS. * * \param[in] attributes The attributes for the new key. * If the key type to be created is * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in * the policy must be the same as in the current * operation. * \param[in,out] operation The key derivation operation object to read from. * \param[in] params Customization parameters for the key derivation. * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT * with \p params_data_length = 0, * this function is equivalent to * psa_key_derivation_output_key(). * Mbed TLS currently only supports the default * production parameters, i.e. * #PSA_KEY_PRODUCTION_PARAMETERS_INIT, * for all key types. * \param params_data_length * Length of `params->data` in bytes. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_INSUFFICIENT_DATA * There was not enough data to create the desired key. * Note that in this case, no output is written to the output buffer. * The operation's capacity is set to 0, thus subsequent calls to * this function will not succeed, even with a smaller output buffer. * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular location. * \retval #PSA_ERROR_INVALID_ARGUMENT * The provided key attributes are not valid for the operation. * \retval #PSA_ERROR_NOT_PERMITTED * The #PSA_KEY_DERIVATION_INPUT_SECRET or * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a * key; or one of the inputs was a key whose policy didn't allow * #PSA_KEY_USAGE_DERIVE. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_output_key_ext( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, const psa_key_production_parameters_t *params, size_t params_data_length, mbedtls_svc_key_id_t *key); #endif /* !__cplusplus */ /** Compare output data from a key derivation operation to an expected value. * * This function calculates output bytes from a key derivation algorithm and * compares those bytes to an expected value in constant time. * If you view the key derivation's output as a stream of bytes, this * function destructively reads the expected number of bytes from the * stream before comparing them. * The operation's capacity decreases by the number of bytes read. * * This is functionally equivalent to the following code: * \code * psa_key_derivation_output_bytes(operation, tmp, output_length); * if (memcmp(output, tmp, output_length) != 0) * return PSA_ERROR_INVALID_SIGNATURE; * \endcode * except (1) it works even if the key's policy does not allow outputting the * bytes, and (2) the comparison will be done in constant time. * * If this function returns an error status other than * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, * the operation enters an error state and must be aborted by calling * psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to read from. * \param[in] expected Buffer containing the expected derivation output. * \param expected_length Length of the expected output; this is also the * number of bytes that will be read. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The output was read successfully, but it differs from the expected * output. * \retval #PSA_ERROR_NOT_PERMITTED * One of the inputs was a key whose policy didn't allow * #PSA_KEY_USAGE_VERIFY_DERIVATION. * \retval #PSA_ERROR_INSUFFICIENT_DATA * The operation's capacity was less than * \p output_length bytes. Note that in this case, * the operation's capacity is set to 0, thus * subsequent calls to this function will not * succeed, even with a smaller expected output. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_verify_bytes( psa_key_derivation_operation_t *operation, const uint8_t *expected, size_t expected_length); /** Compare output data from a key derivation operation to an expected value * stored in a key object. * * This function calculates output bytes from a key derivation algorithm and * compares those bytes to an expected value, provided as key of type * #PSA_KEY_TYPE_PASSWORD_HASH. * If you view the key derivation's output as a stream of bytes, this * function destructively reads the number of bytes corresponding to the * length of the expected value from the stream before comparing them. * The operation's capacity decreases by the number of bytes read. * * This is functionally equivalent to exporting the key and calling * psa_key_derivation_verify_bytes() on the result, except that it * works even if the key cannot be exported. * * If this function returns an error status other than * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, * the operation enters an error state and must be aborted by calling * psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to read from. * \param[in] expected A key of type #PSA_KEY_TYPE_PASSWORD_HASH * containing the expected output. Its policy must * include the #PSA_KEY_USAGE_VERIFY_DERIVATION flag * and the permitted algorithm must match the * operation. The value of this key was likely * computed by a previous call to * psa_key_derivation_output_key() or * psa_key_derivation_output_key_custom(). * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The output was read successfully, but if differs from the expected * output. * \retval #PSA_ERROR_INVALID_HANDLE * The key passed as the expected value does not exist. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key passed as the expected value has an invalid type. * \retval #PSA_ERROR_NOT_PERMITTED * The key passed as the expected value does not allow this usage or * this algorithm; or one of the inputs was a key whose policy didn't * allow #PSA_KEY_USAGE_VERIFY_DERIVATION. * \retval #PSA_ERROR_INSUFFICIENT_DATA * The operation's capacity was less than * the length of the expected value. In this case, * the operation's capacity is set to 0, thus * subsequent calls to this function will not * succeed, even with a smaller expected output. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_verify_key( psa_key_derivation_operation_t *operation, psa_key_id_t expected); /** Abort a key derivation operation. * * Aborting an operation frees all associated resources except for the \c * operation structure itself. Once aborted, the operation object can be reused * for another operation by calling psa_key_derivation_setup() again. * * This function may be called at any time after the operation * object has been initialized as described in #psa_key_derivation_operation_t. * * In particular, it is valid to call psa_key_derivation_abort() twice, or to * call psa_key_derivation_abort() on an operation that has not been set up. * * \param[in,out] operation The operation to abort. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_abort( psa_key_derivation_operation_t *operation); /** Perform a key agreement and return the raw shared secret. * * \warning The raw result of a key agreement algorithm such as finite-field * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should * not be used directly as key material. It should instead be passed as * input to a key derivation algorithm. To chain a key agreement with * a key derivation, use psa_key_derivation_key_agreement() and other * functions from the key derivation interface. * * \param alg The key agreement algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) * is true). * \param private_key Identifier of the private key to use. It must * allow the usage #PSA_KEY_USAGE_DERIVE. * \param[in] peer_key Public key of the peer. It must be * in the same format that psa_import_key() * accepts. The standard formats for public * keys are documented in the documentation * of psa_export_public_key(). * \param peer_key_length Size of \p peer_key in bytes. * \param[out] output Buffer where the decrypted message is to * be written. * \param output_size Size of the \c output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p alg is not a key agreement algorithm, or * \p private_key is not compatible with \p alg, * or \p peer_key is not valid for \p alg or not compatible with * \p private_key. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p output_size is too small * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not a supported key agreement algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, mbedtls_svc_key_id_t private_key, const uint8_t *peer_key, size_t peer_key_length, uint8_t *output, size_t output_size, size_t *output_length); /**@}*/ /** \defgroup random Random generation * @{ */ /** * \brief Generate random bytes. * * \warning This function **can** fail! Callers MUST check the return status * and MUST NOT use the content of the output buffer if the return * status is not #PSA_SUCCESS. * * \note To generate a key, use psa_generate_key() instead. * * \param[out] output Output buffer for the generated data. * \param output_size Number of bytes to generate and output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_generate_random(uint8_t *output, size_t output_size); /** * \brief Generate a key or key pair. * * The key is generated randomly. * Its location, usage policy, type and size are taken from \p attributes. * * Implementations must reject an attempt to generate a key of size 0. * * The following type-specific considerations apply: * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), * the public exponent is 65537. * The modulus is a product of two probabilistic primes * between 2^{n-1} and 2^n where n is the bit size specified in the * attributes. * * \note This function is equivalent to calling psa_generate_key_custom() * with the custom production parameters #PSA_CUSTOM_KEY_PARAMETERS_INIT * and `custom_data_length == 0` (i.e. `custom_data` is empty). * * \param[in] attributes The attributes for the new key. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key); /** * \brief Generate a key or key pair using custom production parameters. * * See the description of psa_generate_key() for the operation of this * function with the default production parameters. In addition, this function * supports the following production customizations, described in more detail * in the documentation of ::psa_custom_key_parameters_t: * * - RSA keys: generation with a custom public exponent. * * \note This function is experimental and may change in future minor * versions of Mbed TLS. * * \param[in] attributes The attributes for the new key. * \param[in] custom Customization parameters for the key generation. * When this is #PSA_CUSTOM_KEY_PARAMETERS_INIT * with \p custom_data_length = 0, * this function is equivalent to * psa_generate_key(). * \param[in] custom_data Variable-length data associated with \c custom. * \param custom_data_length * Length of `custom_data` in bytes. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes, const psa_custom_key_parameters_t *custom, const uint8_t *custom_data, size_t custom_data_length, mbedtls_svc_key_id_t *key); #ifndef __cplusplus /* Omitted when compiling in C++, because one of the parameters is a * pointer to a struct with a flexible array member, and that is not * standard C++. * https://github.com/Mbed-TLS/mbedtls/issues/9020 */ /** * \brief Generate a key or key pair using custom production parameters. * * \note * This is a deprecated variant of psa_key_derivation_output_key_custom(). * It is equivalent except that the associated variable-length data * is passed in `params->data` instead of a separate parameter. * This function will be removed in a future version of Mbed TLS. * * \param[in] attributes The attributes for the new key. * \param[in] params Customization parameters for the key generation. * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT * with \p params_data_length = 0, * this function is equivalent to * psa_generate_key(). * \param params_data_length * Length of `params->data` in bytes. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes, const psa_key_production_parameters_t *params, size_t params_data_length, mbedtls_svc_key_id_t *key); #endif /* !__cplusplus */ /**@}*/ /** \defgroup interruptible_hash Interruptible sign/verify hash * @{ */ /** The type of the state data structure for interruptible hash * signing operations. * * Before calling any function on a sign hash operation object, the * application must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_sign_hash_interruptible_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_sign_hash_interruptible_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer * #PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT, for example: * \code * psa_sign_hash_interruptible_operation_t operation = * PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT; * \endcode * - Assign the result of the function * psa_sign_hash_interruptible_operation_init() to the structure, for * example: * \code * psa_sign_hash_interruptible_operation_t operation; * operation = psa_sign_hash_interruptible_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_sign_hash_interruptible_operation_s psa_sign_hash_interruptible_operation_t; /** The type of the state data structure for interruptible hash * verification operations. * * Before calling any function on a sign hash operation object, the * application must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_verify_hash_interruptible_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_verify_hash_interruptible_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer * #PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT, for example: * \code * psa_verify_hash_interruptible_operation_t operation = * PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT; * \endcode * - Assign the result of the function * psa_verify_hash_interruptible_operation_init() to the structure, for * example: * \code * psa_verify_hash_interruptible_operation_t operation; * operation = psa_verify_hash_interruptible_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_verify_hash_interruptible_operation_s psa_verify_hash_interruptible_operation_t; /** * \brief Set the maximum number of ops allowed to be * executed by an interruptible function in a * single call. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note The time taken to execute a single op is * implementation specific and depends on * software, hardware, the algorithm, key type and * curve chosen. Even within a single operation, * successive ops can take differing amounts of * time. The only guarantee is that lower values * for \p max_ops means functions will block for a * lesser maximum amount of time. The functions * \c psa_sign_interruptible_get_num_ops() and * \c psa_verify_interruptible_get_num_ops() are * provided to help with tuning this value. * * \note This value defaults to * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, which * means the whole operation will be done in one * go, regardless of the number of ops required. * * \note If more ops are needed to complete a * computation, #PSA_OPERATION_INCOMPLETE will be * returned by the function performing the * computation. It is then the caller's * responsibility to either call again with the * same operation context until it returns 0 or an * error code; or to call the relevant abort * function if the answer is no longer required. * * \note The interpretation of \p max_ops is also * implementation defined. On a hard real time * system, this can indicate a hard deadline, as a * real-time system needs a guarantee of not * spending more than X time, however care must be * taken in such an implementation to avoid the * situation whereby calls just return, not being * able to do any actual work within the allotted * time. On a non-real-time system, the * implementation can be more relaxed, but again * whether this number should be interpreted as as * hard or soft limit or even whether a less than * or equals as regards to ops executed in a * single call is implementation defined. * * \note For keys in local storage when no accelerator * driver applies, please see also the * documentation for \c mbedtls_ecp_set_max_ops(), * which is the internal implementation in these * cases. * * \warning With implementations that interpret this number * as a hard limit, setting this number too small * may result in an infinite loop, whereby each * call results in immediate return with no ops * done (as there is not enough time to execute * any), and thus no result will ever be achieved. * * \note This only applies to functions whose * documentation mentions they may return * #PSA_OPERATION_INCOMPLETE. * * \param max_ops The maximum number of ops to be executed in a * single call. This can be a number from 0 to * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0 * is the least amount of work done per call. */ void psa_interruptible_set_max_ops(uint32_t max_ops); /** * \brief Get the maximum number of ops allowed to be * executed by an interruptible function in a * single call. This will return the last * value set by * \c psa_interruptible_set_max_ops() or * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED if * that function has never been called. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \return Maximum number of ops allowed to be * executed by an interruptible function in a * single call. */ uint32_t psa_interruptible_get_max_ops(void); /** * \brief Get the number of ops that a hash signing * operation has taken so far. If the operation * has completed, then this will represent the * number of ops required for the entire * operation. After initialization or calling * \c psa_sign_hash_interruptible_abort() on * the operation, a value of 0 will be returned. * * \note This interface is guaranteed re-entrant and * thus may be called from driver code. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * This is a helper provided to help you tune the * value passed to \c * psa_interruptible_set_max_ops(). * * \param operation The \c psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \return Number of ops that the operation has taken so * far. */ uint32_t psa_sign_hash_get_num_ops( const psa_sign_hash_interruptible_operation_t *operation); /** * \brief Get the number of ops that a hash verification * operation has taken so far. If the operation * has completed, then this will represent the * number of ops required for the entire * operation. After initialization or calling \c * psa_verify_hash_interruptible_abort() on the * operation, a value of 0 will be returned. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * This is a helper provided to help you tune the * value passed to \c * psa_interruptible_set_max_ops(). * * \param operation The \c * psa_verify_hash_interruptible_operation_t to * use. This must be initialized first. * * \return Number of ops that the operation has taken so * far. */ uint32_t psa_verify_hash_get_num_ops( const psa_verify_hash_interruptible_operation_t *operation); /** * \brief Start signing a hash or short message with a * private key, in an interruptible manner. * * \see \c psa_sign_hash_complete() * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function combined with \c * psa_sign_hash_complete() is equivalent to * \c psa_sign_hash() but * \c psa_sign_hash_complete() can return early and * resume according to the limit set with \c * psa_interruptible_set_max_ops() to reduce the * maximum time spent in a function call. * * \note Users should call \c psa_sign_hash_complete() * repeatedly on the same context after a * successful call to this function until \c * psa_sign_hash_complete() either returns 0 or an * error. \c psa_sign_hash_complete() will return * #PSA_OPERATION_INCOMPLETE if there is more work * to do. Alternatively users can call * \c psa_sign_hash_abort() at any point if they no * longer want the result. * * \note If this function returns an error status, the * operation enters an error state and must be * aborted by calling \c psa_sign_hash_abort(). * * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \param key Identifier of the key to use for the operation. * It must be an asymmetric key pair. The key must * allow the usage #PSA_KEY_USAGE_SIGN_HASH. * \param alg A signature algorithm (\c PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) * is true), that is compatible with * the type of \p key. * \param[in] hash The hash or message to sign. * \param hash_length Size of the \p hash buffer in bytes. * * \retval #PSA_SUCCESS * The operation started successfully - call \c psa_sign_hash_complete() * with the same context to complete the operation * * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_SIGN_HASH flag, or it does * not permit the requested algorithm. * \retval #PSA_ERROR_BAD_STATE * An operation has previously been started on this context, and is * still in progress. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_sign_hash_start( psa_sign_hash_interruptible_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length); /** * \brief Continue and eventually complete the action of * signing a hash or short message with a private * key, in an interruptible manner. * * \see \c psa_sign_hash_start() * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function combined with \c * psa_sign_hash_start() is equivalent to * \c psa_sign_hash() but this function can return * early and resume according to the limit set with * \c psa_interruptible_set_max_ops() to reduce the * maximum time spent in a function call. * * \note Users should call this function on the same * operation object repeatedly until it either * returns 0 or an error. This function will return * #PSA_OPERATION_INCOMPLETE if there is more work * to do. Alternatively users can call * \c psa_sign_hash_abort() at any point if they no * longer want the result. * * \note When this function returns successfully, the * operation becomes inactive. If this function * returns an error status, the operation enters an * error state and must be aborted by calling * \c psa_sign_hash_abort(). * * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t * to use. This must be initialized first, and have * had \c psa_sign_hash_start() called with it * first. * * \param[out] signature Buffer where the signature is to be written. * \param signature_size Size of the \p signature buffer in bytes. This * must be appropriate for the selected * algorithm and key: * - The required signature size is * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c * key_bits, \c alg) where \c key_type and \c * key_bits are the type and bit-size * respectively of key. * - #PSA_SIGNATURE_MAX_SIZE evaluates to the * maximum signature size of any supported * signature algorithm. * \param[out] signature_length On success, the number of bytes that make up * the returned signature value. * * \retval #PSA_SUCCESS * Operation completed successfully * * \retval #PSA_OPERATION_INCOMPLETE * Operation was interrupted due to the setting of \c * psa_interruptible_set_max_ops(). There is still work to be done. * Call this function again with the same operation object. * * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \c alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \c key. * * \retval #PSA_ERROR_BAD_STATE * An operation was not previously started on this context via * \c psa_sign_hash_start(). * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has either not been previously initialized by * psa_crypto_init() or you did not previously call * psa_sign_hash_start() with this operation object. It is * implementation-dependent whether a failure to initialize results in * this error code. */ psa_status_t psa_sign_hash_complete( psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Abort a sign hash operation. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function is the only function that clears * the number of ops completed as part of the * operation. Please ensure you copy this value via * \c psa_sign_hash_get_num_ops() if required * before calling. * * \note Aborting an operation frees all associated * resources except for the \p operation structure * itself. Once aborted, the operation object can * be reused for another operation by calling \c * psa_sign_hash_start() again. * * \note You may call this function any time after the * operation object has been initialized. In * particular, calling \c psa_sign_hash_abort() * after the operation has already been terminated * by a call to \c psa_sign_hash_abort() or * psa_sign_hash_complete() is safe. * * \param[in,out] operation Initialized sign hash operation. * * \retval #PSA_SUCCESS * The operation was aborted successfully. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_sign_hash_abort( psa_sign_hash_interruptible_operation_t *operation); /** * \brief Start reading and verifying a hash or short * message, in an interruptible manner. * * \see \c psa_verify_hash_complete() * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function combined with \c * psa_verify_hash_complete() is equivalent to * \c psa_verify_hash() but \c * psa_verify_hash_complete() can return early and * resume according to the limit set with \c * psa_interruptible_set_max_ops() to reduce the * maximum time spent in a function. * * \note Users should call \c psa_verify_hash_complete() * repeatedly on the same operation object after a * successful call to this function until \c * psa_verify_hash_complete() either returns 0 or * an error. \c psa_verify_hash_complete() will * return #PSA_OPERATION_INCOMPLETE if there is * more work to do. Alternatively users can call * \c psa_verify_hash_abort() at any point if they * no longer want the result. * * \note If this function returns an error status, the * operation enters an error state and must be * aborted by calling \c psa_verify_hash_abort(). * * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t * to use. This must be initialized first. * * \param key Identifier of the key to use for the operation. * The key must allow the usage * #PSA_KEY_USAGE_VERIFY_HASH. * \param alg A signature algorithm (\c PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) * is true), that is compatible with * the type of \p key. * \param[in] hash The hash whose signature is to be verified. * \param hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The operation started successfully - please call \c * psa_verify_hash_complete() with the same context to complete the * operation. * * \retval #PSA_ERROR_BAD_STATE * Another operation has already been started on this context, and is * still in progress. * * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_VERIFY_HASH flag, or it does * not permit the requested algorithm. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval PSA_ERROR_DATA_CORRUPT \emptydescription * \retval PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_verify_hash_start( psa_verify_hash_interruptible_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Continue and eventually complete the action of * reading and verifying a hash or short message * signed with a private key, in an interruptible * manner. * * \see \c psa_verify_hash_start() * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function combined with \c * psa_verify_hash_start() is equivalent to * \c psa_verify_hash() but this function can * return early and resume according to the limit * set with \c psa_interruptible_set_max_ops() to * reduce the maximum time spent in a function * call. * * \note Users should call this function on the same * operation object repeatedly until it either * returns 0 or an error. This function will return * #PSA_OPERATION_INCOMPLETE if there is more work * to do. Alternatively users can call * \c psa_verify_hash_abort() at any point if they * no longer want the result. * * \note When this function returns successfully, the * operation becomes inactive. If this function * returns an error status, the operation enters an * error state and must be aborted by calling * \c psa_verify_hash_abort(). * * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t * to use. This must be initialized first, and have * had \c psa_verify_hash_start() called with it * first. * * \retval #PSA_SUCCESS * Operation completed successfully, and the passed signature is valid. * * \retval #PSA_OPERATION_INCOMPLETE * Operation was interrupted due to the setting of \c * psa_interruptible_set_max_ops(). There is still work to be done. * Call this function again with the same operation object. * * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_BAD_STATE * An operation was not previously started on this context via * \c psa_verify_hash_start(). * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has either not been previously initialized by * psa_crypto_init() or you did not previously call * psa_verify_hash_start() on this object. It is * implementation-dependent whether a failure to initialize results in * this error code. */ psa_status_t psa_verify_hash_complete( psa_verify_hash_interruptible_operation_t *operation); /** * \brief Abort a verify hash operation. * * \warning This is a beta API, and thus subject to change at * any point. It is not bound by the usual interface * stability promises. * * \note This function is the only function that clears the * number of ops completed as part of the operation. * Please ensure you copy this value via * \c psa_verify_hash_get_num_ops() if required * before calling. * * \note Aborting an operation frees all associated * resources except for the operation structure * itself. Once aborted, the operation object can be * reused for another operation by calling \c * psa_verify_hash_start() again. * * \note You may call this function any time after the * operation object has been initialized. * In particular, calling \c psa_verify_hash_abort() * after the operation has already been terminated by * a call to \c psa_verify_hash_abort() or * psa_verify_hash_complete() is safe. * * \param[in,out] operation Initialized verify hash operation. * * \retval #PSA_SUCCESS * The operation was aborted successfully. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_verify_hash_abort( psa_verify_hash_interruptible_operation_t *operation); /**@}*/ #ifdef __cplusplus } #endif /* The file "crypto_sizes.h" contains definitions for size calculation * macros whose definitions are implementation-specific. */ #include "crypto_sizes.h" /* The file "crypto_struct.h" contains definitions for * implementation-specific structs that are declared above. */ #if defined(MBEDTLS_PSA_CRYPTO_STRUCT_FILE) #include MBEDTLS_PSA_CRYPTO_STRUCT_FILE #else #include "crypto_struct.h" #endif /* The file "crypto_extra.h" contains vendor-specific definitions. This * can include vendor-defined algorithms, extra functions, etc. */ #include "crypto_extra.h" #endif /* PSA_CRYPTO_H */ webfakes/src/mbedtls/include/psa/crypto_driver_common.h0000644000176200001440000000302714740737024023116 0ustar liggesusers/** * \file psa/crypto_driver_common.h * \brief Definitions for all PSA crypto drivers * * This file contains common definitions shared by all PSA crypto drivers. * Do not include it directly: instead, include the header file(s) for * the type(s) of driver that you are implementing. For example, if * you are writing a dynamically registered driver for a secure element, * include `psa/crypto_se_driver.h`. * * This file is part of the PSA Crypto Driver Model, containing functions for * driver developers to implement to enable hardware to be called in a * standardized way by a PSA Cryptographic API implementation. The functions * comprising the driver model, which driver authors implement, are not * intended to be called by application developers. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_COMMON_H #define PSA_CRYPTO_DRIVER_COMMON_H #include #include /* Include type definitions (psa_status_t, psa_algorithm_t, * psa_key_type_t, etc.) and macros to build and analyze values * of these types. */ #include "crypto_types.h" #include "crypto_values.h" /* Include size definitions which are used to size some arrays in operation * structures. */ #include /** For encrypt-decrypt functions, whether the operation is an encryption * or a decryption. */ typedef enum { PSA_CRYPTO_DRIVER_DECRYPT, PSA_CRYPTO_DRIVER_ENCRYPT } psa_encrypt_or_decrypt_t; #endif /* PSA_CRYPTO_DRIVER_COMMON_H */ webfakes/src/mbedtls/include/psa/crypto_compat.h0000644000176200001440000002105614740737024021540 0ustar liggesusers/** * \file psa/crypto_compat.h * * \brief PSA cryptography module: Backward compatibility aliases * * This header declares alternative names for macro and functions. * New application code should not use these names. * These names may be removed in a future version of Mbed TLS. * * \note This file may not be included directly. Applications must * include psa/crypto.h. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_COMPAT_H #define PSA_CRYPTO_COMPAT_H #ifdef __cplusplus extern "C" { #endif /* * To support both openless APIs and psa_open_key() temporarily, define * psa_key_handle_t to be equal to mbedtls_svc_key_id_t. Do not mark the * type and its utility macros and functions deprecated yet. This will be done * in a subsequent phase. */ typedef mbedtls_svc_key_id_t psa_key_handle_t; #define PSA_KEY_HANDLE_INIT MBEDTLS_SVC_KEY_ID_INIT /** Check whether a handle is null. * * \param handle Handle * * \return Non-zero if the handle is null, zero otherwise. */ static inline int psa_key_handle_is_null(psa_key_handle_t handle) { return mbedtls_svc_key_id_is_null(handle); } /** Open a handle to an existing persistent key. * * Open a handle to a persistent key. A key is persistent if it was created * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key * always has a nonzero key identifier, set with psa_set_key_id() when * creating the key. Implementations may provide additional pre-provisioned * keys that can be opened with psa_open_key(). Such keys have an application * key identifier in the vendor range, as documented in the description of * #psa_key_id_t. * * The application must eventually close the handle with psa_close_key() or * psa_destroy_key() to release associated resources. If the application dies * without calling one of these functions, the implementation should perform * the equivalent of a call to psa_close_key(). * * Some implementations permit an application to open the same key multiple * times. If this is successful, each call to psa_open_key() will return a * different key handle. * * \note This API is not part of the PSA Cryptography API Release 1.0.0 * specification. It was defined in the 1.0 Beta 3 version of the * specification but was removed in the 1.0.0 released version. This API is * kept for the time being to not break applications relying on it. It is not * deprecated yet but will be in the near future. * * \note Applications that rely on opening a key multiple times will not be * portable to implementations that only permit a single key handle to be * opened. See also :ref:\`key-handles\`. * * * \param key The persistent identifier of the key. * \param[out] handle On success, a handle to the key. * * \retval #PSA_SUCCESS * Success. The application can now use the value of `*handle` * to access the key. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * The implementation does not have sufficient resources to open the * key. This can be due to reaching an implementation limit on the * number of open keys, the number of open key handles, or available * memory. * \retval #PSA_ERROR_DOES_NOT_EXIST * There is no persistent key with key identifier \p key. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not a valid persistent key identifier. * \retval #PSA_ERROR_NOT_PERMITTED * The specified key exists, but the application does not have the * permission to access it. Note that this specification does not * define any way to create such a key, but it may be possible * through implementation-specific means. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle); /** Close a key handle. * * If the handle designates a volatile key, this will destroy the key material * and free all associated resources, just like psa_destroy_key(). * * If this is the last open handle to a persistent key, then closing the handle * will free all resources associated with the key in volatile memory. The key * data in persistent storage is not affected and can be opened again later * with a call to psa_open_key(). * * Closing the key handle makes the handle invalid, and the key handle * must not be used again by the application. * * \note This API is not part of the PSA Cryptography API Release 1.0.0 * specification. It was defined in the 1.0 Beta 3 version of the * specification but was removed in the 1.0.0 released version. This API is * kept for the time being to not break applications relying on it. It is not * deprecated yet but will be in the near future. * * \note If the key handle was used to set up an active * :ref:\`multipart operation \`, then closing the * key handle can cause the multipart operation to fail. Applications should * maintain the key handle until after the multipart operation has finished. * * \param handle The key handle to close. * If this is \c 0, do nothing and return \c PSA_SUCCESS. * * \retval #PSA_SUCCESS * \p handle was a valid handle or \c 0. It is now closed. * \retval #PSA_ERROR_INVALID_HANDLE * \p handle is not a valid handle nor \c 0. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_close_key(psa_key_handle_t handle); /** \addtogroup attributes * @{ */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** Custom Diffie-Hellman group. * * Mbed TLS does not support custom DH groups. * * \deprecated This value is not useful, so this macro will be removed in * a future version of the library. */ #define PSA_DH_FAMILY_CUSTOM \ ((psa_dh_family_t) MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(0x7e)) /** * \brief Set domain parameters for a key. * * \deprecated Mbed TLS no longer supports any domain parameters. * This function only does the equivalent of * psa_set_key_type() and will be removed in a future version * of the library. * * \param[in,out] attributes Attribute structure where \p type will be set. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). * \param[in] data Ignored. * \param data_length Must be 0. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription */ static inline psa_status_t MBEDTLS_DEPRECATED psa_set_key_domain_parameters( psa_key_attributes_t *attributes, psa_key_type_t type, const uint8_t *data, size_t data_length) { (void) data; if (data_length != 0) { return PSA_ERROR_NOT_SUPPORTED; } psa_set_key_type(attributes, type); return PSA_SUCCESS; } /** * \brief Get domain parameters for a key. * * \deprecated Mbed TLS no longer supports any domain parameters. * This function alwaya has an empty output and will be * removed in a future version of the library. * \param[in] attributes Ignored. * \param[out] data Ignored. * \param data_size Ignored. * \param[out] data_length Set to 0. * * \retval #PSA_SUCCESS \emptydescription */ static inline psa_status_t MBEDTLS_DEPRECATED psa_get_key_domain_parameters( const psa_key_attributes_t *attributes, uint8_t *data, size_t data_size, size_t *data_length) { (void) attributes; (void) data; (void) data_size; *data_length = 0; return PSA_SUCCESS; } /** Safe output buffer size for psa_get_key_domain_parameters(). * */ #define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(1u) #endif /* MBEDTLS_DEPRECATED_REMOVED */ /**@}*/ #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_COMPAT_H */ webfakes/src/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h0000644000176200001440000000743514740737024026210 0ustar liggesusers/** * \file psa/crypto_adjust_config_key_pair_types.h * \brief Adjust PSA configuration for key pair types. * * This is an internal header. Do not include it directly. * * See docs/proposed/psa-conditional-inclusion-c.md. * - Support non-basic operations in a keypair type implicitly enables basic * support for that keypair type. * - Support for a keypair type implicitly enables the corresponding public * key type. * - Basic support for a keypair type implicilty enables import/export support * for that keypair type. Warning: this is implementation-specific (mainly * for the benefit of testing) and may change in the future! */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H #define PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ /***************************************************************** * ANYTHING -> BASIC ****************************************************************/ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE) #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #endif /***************************************************************** * BASIC -> corresponding PUBLIC ****************************************************************/ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 #endif /***************************************************************** * BASIC -> IMPORT+EXPORT * * (Implementation-specific, may change in the future.) ****************************************************************/ /* Even though KEY_PAIR symbols' feature several level of support (BASIC, IMPORT, * EXPORT, GENERATE, DERIVE) we're not planning to have support only for BASIC * without IMPORT/EXPORT since these last 2 features are strongly used in tests. * In general it is allowed to include more feature than what is strictly * requested. * As a consequence IMPORT and EXPORT features will be automatically enabled * as soon as the BASIC one is. */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #endif #endif /* PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H */ webfakes/src/mbedtls/include/psa/crypto_driver_contexts_composites.h0000644000176200001440000001346214740737024025746 0ustar liggesusers/* * Declaration of context structures for use with the PSA driver wrapper * interface. This file contains the context structures for 'composite' * operations, i.e. those operations which need to make use of other operations * from the primitives (crypto_driver_contexts_primitives.h) * * Warning: This file will be auto-generated in the future. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the PSA drivers included in the cryptographic * library. The definitions of these objects are then used by crypto_struct.h * to define the implementation-defined types of PSA multi-part state objects. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H #define PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H #include "psa/crypto_driver_common.h" /* Include the context structure definitions for the Mbed TLS software drivers */ #include "psa/crypto_builtin_composites.h" /* Include the context structure definitions for those drivers that were * declared during the autogeneration process. */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) #include #endif #if defined(PSA_CRYPTO_DRIVER_TEST) #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC) typedef libtestdriver1_mbedtls_psa_mac_operation_t mbedtls_transparent_test_driver_mac_operation_t; typedef libtestdriver1_mbedtls_psa_mac_operation_t mbedtls_opaque_test_driver_mac_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT #define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT #else typedef mbedtls_psa_mac_operation_t mbedtls_transparent_test_driver_mac_operation_t; typedef mbedtls_psa_mac_operation_t mbedtls_opaque_test_driver_mac_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \ MBEDTLS_PSA_MAC_OPERATION_INIT #define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \ MBEDTLS_PSA_MAC_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD) typedef libtestdriver1_mbedtls_psa_aead_operation_t mbedtls_transparent_test_driver_aead_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_AEAD_OPERATION_INIT #else typedef mbedtls_psa_aead_operation_t mbedtls_transparent_test_driver_aead_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ MBEDTLS_PSA_AEAD_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE) typedef libtestdriver1_mbedtls_psa_pake_operation_t mbedtls_transparent_test_driver_pake_operation_t; typedef libtestdriver1_mbedtls_psa_pake_operation_t mbedtls_opaque_test_driver_pake_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT #define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT #else typedef mbedtls_psa_pake_operation_t mbedtls_transparent_test_driver_pake_operation_t; typedef mbedtls_psa_pake_operation_t mbedtls_opaque_test_driver_pake_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \ MBEDTLS_PSA_PAKE_OPERATION_INIT #define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \ MBEDTLS_PSA_PAKE_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE */ #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Define the context to be used for an operation that is executed through the * PSA Driver wrapper layer as the union of all possible driver's contexts. * * The union members are the driver's context structures, and the member names * are formatted as `'drivername'_ctx`. This allows for procedural generation * of both this file and the content of psa_crypto_driver_wrappers.h */ typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_mac_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_mac_operation_t transparent_test_driver_ctx; mbedtls_opaque_test_driver_mac_operation_t opaque_test_driver_ctx; #endif } psa_driver_mac_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_aead_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_aead_operation_t transparent_test_driver_ctx; #endif } psa_driver_aead_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_sign_hash_interruptible_operation_t mbedtls_ctx; } psa_driver_sign_hash_interruptible_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_verify_hash_interruptible_operation_t mbedtls_ctx; } psa_driver_verify_hash_interruptible_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_pake_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_pake_operation_t transparent_test_driver_ctx; mbedtls_opaque_test_driver_pake_operation_t opaque_test_driver_ctx; #endif } psa_driver_pake_context_t; #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */ /* End of automatically generated file. */ webfakes/src/mbedtls/include/psa/build_info.h0000644000176200001440000000076414740737024020772 0ustar liggesusers/** * \file psa/build_info.h * * \brief Build-time PSA configuration info * * Include this file if you need to depend on the * configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE * in PSA cryptography core specific files. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILD_INFO_H #define PSA_CRYPTO_BUILD_INFO_H #include "mbedtls/build_info.h" #endif /* PSA_CRYPTO_BUILD_INFO_H */ webfakes/src/mbedtls/include/psa/crypto_driver_contexts_primitives.h0000644000176200001440000000775714740737024025766 0ustar liggesusers/* * Declaration of context structures for use with the PSA driver wrapper * interface. This file contains the context structures for 'primitive' * operations, i.e. those operations which do not rely on other contexts. * * Warning: This file will be auto-generated in the future. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the PSA drivers included in the cryptographic * library. The definitions of these objects are then used by crypto_struct.h * to define the implementation-defined types of PSA multi-part state objects. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H #define PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H #include "psa/crypto_driver_common.h" /* Include the context structure definitions for the Mbed TLS software drivers */ #include "psa/crypto_builtin_primitives.h" /* Include the context structure definitions for those drivers that were * declared during the autogeneration process. */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) #include #endif #if defined(PSA_CRYPTO_DRIVER_TEST) #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER) typedef libtestdriver1_mbedtls_psa_cipher_operation_t mbedtls_transparent_test_driver_cipher_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_CIPHER_OPERATION_INIT #else typedef mbedtls_psa_cipher_operation_t mbedtls_transparent_test_driver_cipher_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \ MBEDTLS_PSA_CIPHER_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH) typedef libtestdriver1_mbedtls_psa_hash_operation_t mbedtls_transparent_test_driver_hash_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_HASH_OPERATION_INIT #else typedef mbedtls_psa_hash_operation_t mbedtls_transparent_test_driver_hash_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \ MBEDTLS_PSA_HASH_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH */ typedef struct { unsigned int initialised : 1; mbedtls_transparent_test_driver_cipher_operation_t ctx; } mbedtls_opaque_test_driver_cipher_operation_t; #define MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT \ { 0, MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT } #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Define the context to be used for an operation that is executed through the * PSA Driver wrapper layer as the union of all possible driver's contexts. * * The union members are the driver's context structures, and the member names * are formatted as `'drivername'_ctx`. This allows for procedural generation * of both this file and the content of psa_crypto_driver_wrappers.h */ typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_hash_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_hash_operation_t test_driver_ctx; #endif } psa_driver_hash_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_cipher_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_cipher_operation_t transparent_test_driver_ctx; mbedtls_opaque_test_driver_cipher_operation_t opaque_test_driver_ctx; #endif } psa_driver_cipher_context_t; #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H */ /* End of automatically generated file. */ webfakes/src/mbedtls/include/psa/crypto_se_driver.h0000644000176200001440000020450414740737024022240 0ustar liggesusers/** * \file psa/crypto_se_driver.h * \brief PSA external cryptoprocessor driver module * * This header declares types and function signatures for cryptography * drivers that access key material via opaque references. * This is meant for cryptoprocessors that have a separate key storage from the * space in which the PSA Crypto implementation runs, typically secure * elements (SEs). * * This file is part of the PSA Crypto Driver HAL (hardware abstraction layer), * containing functions for driver developers to implement to enable hardware * to be called in a standardized way by a PSA Cryptography API * implementation. The functions comprising the driver HAL, which driver * authors implement, are not intended to be called by application developers. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SE_DRIVER_H #define PSA_CRYPTO_SE_DRIVER_H #include "mbedtls/private_access.h" #include "crypto_driver_common.h" #ifdef __cplusplus extern "C" { #endif /** \defgroup se_init Secure element driver initialization */ /**@{*/ /** \brief Driver context structure * * Driver functions receive a pointer to this structure. * Each registered driver has one instance of this structure. * * Implementations must include the fields specified here and * may include other fields. */ typedef struct { /** A read-only pointer to the driver's persistent data. * * Drivers typically use this persistent data to keep track of * which slot numbers are available. This is only a guideline: * drivers may use the persistent data for any purpose, keeping * in mind the restrictions on when the persistent data is saved * to storage: the persistent data is only saved after calling * certain functions that receive a writable pointer to the * persistent data. * * The core allocates a memory buffer for the persistent data. * The pointer is guaranteed to be suitably aligned for any data type, * like a pointer returned by `malloc` (but the core can use any * method to allocate the buffer, not necessarily `malloc`). * * The size of this buffer is in the \c persistent_data_size field of * this structure. * * Before the driver is initialized for the first time, the content of * the persistent data is all-bits-zero. After a driver upgrade, if the * size of the persistent data has increased, the original data is padded * on the right with zeros; if the size has decreased, the original data * is truncated to the new size. * * This pointer is to read-only data. Only a few driver functions are * allowed to modify the persistent data. These functions receive a * writable pointer. These functions are: * - psa_drv_se_t::p_init * - psa_drv_se_key_management_t::p_allocate * - psa_drv_se_key_management_t::p_destroy * * The PSA Cryptography core saves the persistent data from one * session to the next. It does this before returning from API functions * that call a driver method that is allowed to modify the persistent * data, specifically: * - psa_crypto_init() causes a call to psa_drv_se_t::p_init, and may call * psa_drv_se_key_management_t::p_destroy to complete an action * that was interrupted by a power failure. * - Key creation functions cause a call to * psa_drv_se_key_management_t::p_allocate, and may cause a call to * psa_drv_se_key_management_t::p_destroy in case an error occurs. * - psa_destroy_key() causes a call to * psa_drv_se_key_management_t::p_destroy. */ const void *const MBEDTLS_PRIVATE(persistent_data); /** The size of \c persistent_data in bytes. * * This is always equal to the value of the `persistent_data_size` field * of the ::psa_drv_se_t structure when the driver is registered. */ const size_t MBEDTLS_PRIVATE(persistent_data_size); /** Driver transient data. * * The core initializes this value to 0 and does not read or modify it * afterwards. The driver may store whatever it wants in this field. */ uintptr_t MBEDTLS_PRIVATE(transient_data); } psa_drv_se_context_t; /** \brief A driver initialization function. * * \param[in,out] drv_context The driver context structure. * \param[in,out] persistent_data A pointer to the persistent data * that allows writing. * \param location The location value for which this driver * is registered. The driver will be invoked * for all keys whose lifetime is in this * location. * * \retval #PSA_SUCCESS * The driver is operational. * The core will update the persistent data in storage. * \return * Any other return value prevents the driver from being used in * this session. * The core will NOT update the persistent data in storage. */ typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context, void *persistent_data, psa_key_location_t location); #if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Mbed TLS with secure element support enabled defines this type in * crypto_types.h because it is also visible to applications through an * implementation-specific extension. * For the PSA Cryptography specification, this type is only visible * via crypto_se_driver.h. */ /** An internal designation of a key slot between the core part of the * PSA Crypto implementation and the driver. The meaning of this value * is driver-dependent. */ typedef uint64_t psa_key_slot_number_t; #endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */ /**@}*/ /** \defgroup se_mac Secure Element Message Authentication Codes * Generation and authentication of Message Authentication Codes (MACs) using * a secure element can be done either as a single function call (via the * `psa_drv_se_mac_generate_t` or `psa_drv_se_mac_verify_t` functions), or in * parts using the following sequence: * - `psa_drv_se_mac_setup_t` * - `psa_drv_se_mac_update_t` * - `psa_drv_se_mac_update_t` * - ... * - `psa_drv_se_mac_finish_t` or `psa_drv_se_mac_finish_verify_t` * * If a previously started secure element MAC operation needs to be terminated, * it should be done so by the `psa_drv_se_mac_abort_t`. Failure to do so may * result in allocated resources not being freed or in other undefined * behavior. */ /**@{*/ /** \brief A function that starts a secure element MAC operation for a PSA * Crypto Driver implementation * * \param[in,out] drv_context The driver context structure. * \param[in,out] op_context A structure that will contain the * hardware-specific MAC context * \param[in] key_slot The slot of the key to be used for the * operation * \param[in] algorithm The algorithm to be used to underly the MAC * operation * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context, void *op_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm); /** \brief A function that continues a previously started secure element MAC * operation * * \param[in,out] op_context A hardware-specific structure for the * previously-established MAC operation to be * updated * \param[in] p_input A buffer containing the message to be appended * to the MAC operation * \param[in] input_length The size in bytes of the input message buffer */ typedef psa_status_t (*psa_drv_se_mac_update_t)(void *op_context, const uint8_t *p_input, size_t input_length); /** \brief a function that completes a previously started secure element MAC * operation by returning the resulting MAC. * * \param[in,out] op_context A hardware-specific structure for the * previously started MAC operation to be * finished * \param[out] p_mac A buffer where the generated MAC will be * placed * \param[in] mac_size The size in bytes of the buffer that has been * allocated for the `output` buffer * \param[out] p_mac_length After completion, will contain the number of * bytes placed in the `p_mac` buffer * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context, uint8_t *p_mac, size_t mac_size, size_t *p_mac_length); /** \brief A function that completes a previously started secure element MAC * operation by comparing the resulting MAC against a provided value * * \param[in,out] op_context A hardware-specific structure for the previously * started MAC operation to be finished * \param[in] p_mac The MAC value against which the resulting MAC * will be compared against * \param[in] mac_length The size in bytes of the value stored in `p_mac` * * \retval #PSA_SUCCESS * The operation completed successfully and the MACs matched each * other * \retval #PSA_ERROR_INVALID_SIGNATURE * The operation completed successfully, but the calculated MAC did * not match the provided MAC */ typedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *op_context, const uint8_t *p_mac, size_t mac_length); /** \brief A function that aborts a previous started secure element MAC * operation * * \param[in,out] op_context A hardware-specific structure for the previously * started MAC operation to be aborted */ typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *op_context); /** \brief A function that performs a secure element MAC operation in one * command and returns the calculated MAC * * \param[in,out] drv_context The driver context structure. * \param[in] p_input A buffer containing the message to be MACed * \param[in] input_length The size in bytes of `p_input` * \param[in] key_slot The slot of the key to be used * \param[in] alg The algorithm to be used to underlie the MAC * operation * \param[out] p_mac A buffer where the generated MAC will be * placed * \param[in] mac_size The size in bytes of the `p_mac` buffer * \param[out] p_mac_length After completion, will contain the number of * bytes placed in the `output` buffer * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context, const uint8_t *p_input, size_t input_length, psa_key_slot_number_t key_slot, psa_algorithm_t alg, uint8_t *p_mac, size_t mac_size, size_t *p_mac_length); /** \brief A function that performs a secure element MAC operation in one * command and compares the resulting MAC against a provided value * * \param[in,out] drv_context The driver context structure. * \param[in] p_input A buffer containing the message to be MACed * \param[in] input_length The size in bytes of `input` * \param[in] key_slot The slot of the key to be used * \param[in] alg The algorithm to be used to underlie the MAC * operation * \param[in] p_mac The MAC value against which the resulting MAC will * be compared against * \param[in] mac_length The size in bytes of `mac` * * \retval #PSA_SUCCESS * The operation completed successfully and the MACs matched each * other * \retval #PSA_ERROR_INVALID_SIGNATURE * The operation completed successfully, but the calculated MAC did * not match the provided MAC */ typedef psa_status_t (*psa_drv_se_mac_verify_t)(psa_drv_se_context_t *drv_context, const uint8_t *p_input, size_t input_length, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_mac, size_t mac_length); /** \brief A struct containing all of the function pointers needed to * perform secure element MAC operations * * PSA Crypto API implementations should populate the table as appropriate * upon startup. * * If one of the functions is not implemented (such as * `psa_drv_se_mac_generate_t`), it should be set to NULL. * * Driver implementers should ensure that they implement all of the functions * that make sense for their hardware, and that they provide a full solution * (for example, if they support `p_setup`, they should also support * `p_update` and at least one of `p_finish` or `p_finish_verify`). * */ typedef struct { /**The size in bytes of the hardware-specific secure element MAC context * structure */ size_t MBEDTLS_PRIVATE(context_size); /** Function that performs a MAC setup operation */ psa_drv_se_mac_setup_t MBEDTLS_PRIVATE(p_setup); /** Function that performs a MAC update operation */ psa_drv_se_mac_update_t MBEDTLS_PRIVATE(p_update); /** Function that completes a MAC operation */ psa_drv_se_mac_finish_t MBEDTLS_PRIVATE(p_finish); /** Function that completes a MAC operation with a verify check */ psa_drv_se_mac_finish_verify_t MBEDTLS_PRIVATE(p_finish_verify); /** Function that aborts a previously started MAC operation */ psa_drv_se_mac_abort_t MBEDTLS_PRIVATE(p_abort); /** Function that performs a MAC operation in one call */ psa_drv_se_mac_generate_t MBEDTLS_PRIVATE(p_mac); /** Function that performs a MAC and verify operation in one call */ psa_drv_se_mac_verify_t MBEDTLS_PRIVATE(p_mac_verify); } psa_drv_se_mac_t; /**@}*/ /** \defgroup se_cipher Secure Element Symmetric Ciphers * * Encryption and Decryption using secure element keys in block modes other * than ECB must be done in multiple parts, using the following flow: * - `psa_drv_se_cipher_setup_t` * - `psa_drv_se_cipher_set_iv_t` (optional depending upon block mode) * - `psa_drv_se_cipher_update_t` * - `psa_drv_se_cipher_update_t` * - ... * - `psa_drv_se_cipher_finish_t` * * If a previously started secure element Cipher operation needs to be * terminated, it should be done so by the `psa_drv_se_cipher_abort_t`. Failure * to do so may result in allocated resources not being freed or in other * undefined behavior. * * In situations where a PSA Cryptographic API implementation is using a block * mode not-supported by the underlying hardware or driver, it can construct * the block mode itself, while calling the `psa_drv_se_cipher_ecb_t` function * for the cipher operations. */ /**@{*/ /** \brief A function that provides the cipher setup function for a * secure element driver * * \param[in,out] drv_context The driver context structure. * \param[in,out] op_context A structure that will contain the * hardware-specific cipher context. * \param[in] key_slot The slot of the key to be used for the * operation * \param[in] algorithm The algorithm to be used in the cipher * operation * \param[in] direction Indicates whether the operation is an encrypt * or decrypt * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context, void *op_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm, psa_encrypt_or_decrypt_t direction); /** \brief A function that sets the initialization vector (if * necessary) for a secure element cipher operation * * Rationale: The `psa_se_cipher_*` operation in the PSA Cryptographic API has * two IV functions: one to set the IV, and one to generate it internally. The * generate function is not necessary for the drivers to implement as the PSA * Crypto implementation can do the generation using its RNG features. * * \param[in,out] op_context A structure that contains the previously set up * hardware-specific cipher context * \param[in] p_iv A buffer containing the initialization vector * \param[in] iv_length The size (in bytes) of the `p_iv` buffer * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context, const uint8_t *p_iv, size_t iv_length); /** \brief A function that continues a previously started secure element cipher * operation * * \param[in,out] op_context A hardware-specific structure for the * previously started cipher operation * \param[in] p_input A buffer containing the data to be * encrypted/decrypted * \param[in] input_size The size in bytes of the buffer pointed to * by `p_input` * \param[out] p_output The caller-allocated buffer where the * output will be placed * \param[in] output_size The allocated size in bytes of the * `p_output` buffer * \param[out] p_output_length After completion, will contain the number * of bytes placed in the `p_output` buffer * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context, const uint8_t *p_input, size_t input_size, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** \brief A function that completes a previously started secure element cipher * operation * * \param[in,out] op_context A hardware-specific structure for the * previously started cipher operation * \param[out] p_output The caller-allocated buffer where the output * will be placed * \param[in] output_size The allocated size in bytes of the `p_output` * buffer * \param[out] p_output_length After completion, will contain the number of * bytes placed in the `p_output` buffer * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** \brief A function that aborts a previously started secure element cipher * operation * * \param[in,out] op_context A hardware-specific structure for the * previously started cipher operation */ typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *op_context); /** \brief A function that performs the ECB block mode for secure element * cipher operations * * Note: this function should only be used with implementations that do not * provide a needed higher-level operation. * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot The slot of the key to be used for the operation * \param[in] algorithm The algorithm to be used in the cipher operation * \param[in] direction Indicates whether the operation is an encrypt or * decrypt * \param[in] p_input A buffer containing the data to be * encrypted/decrypted * \param[in] input_size The size in bytes of the buffer pointed to by * `p_input` * \param[out] p_output The caller-allocated buffer where the output * will be placed * \param[in] output_size The allocated size in bytes of the `p_output` * buffer * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm, psa_encrypt_or_decrypt_t direction, const uint8_t *p_input, size_t input_size, uint8_t *p_output, size_t output_size); /** * \brief A struct containing all of the function pointers needed to implement * cipher operations using secure elements. * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup or at build time. * * If one of the functions is not implemented (such as * `psa_drv_se_cipher_ecb_t`), it should be set to NULL. */ typedef struct { /** The size in bytes of the hardware-specific secure element cipher * context structure */ size_t MBEDTLS_PRIVATE(context_size); /** Function that performs a cipher setup operation */ psa_drv_se_cipher_setup_t MBEDTLS_PRIVATE(p_setup); /** Function that sets a cipher IV (if necessary) */ psa_drv_se_cipher_set_iv_t MBEDTLS_PRIVATE(p_set_iv); /** Function that performs a cipher update operation */ psa_drv_se_cipher_update_t MBEDTLS_PRIVATE(p_update); /** Function that completes a cipher operation */ psa_drv_se_cipher_finish_t MBEDTLS_PRIVATE(p_finish); /** Function that aborts a cipher operation */ psa_drv_se_cipher_abort_t MBEDTLS_PRIVATE(p_abort); /** Function that performs ECB mode for a cipher operation * (Danger: ECB mode should not be used directly by clients of the PSA * Crypto Client API) */ psa_drv_se_cipher_ecb_t MBEDTLS_PRIVATE(p_ecb); } psa_drv_se_cipher_t; /**@}*/ /** \defgroup se_asymmetric Secure Element Asymmetric Cryptography * * Since the amount of data that can (or should) be encrypted or signed using * asymmetric keys is limited by the key size, asymmetric key operations using * keys in a secure element must be done in single function calls. */ /**@{*/ /** * \brief A function that signs a hash or short message with a private key in * a secure element * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Key slot of an asymmetric key pair * \param[in] alg A signature algorithm that is compatible * with the type of `key` * \param[in] p_hash The hash to sign * \param[in] hash_length Size of the `p_hash` buffer in bytes * \param[out] p_signature Buffer where the signature is to be written * \param[in] signature_size Size of the `p_signature` buffer in bytes * \param[out] p_signature_length On success, the number of bytes * that make up the returned signature value * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_hash, size_t hash_length, uint8_t *p_signature, size_t signature_size, size_t *p_signature_length); /** * \brief A function that verifies the signature a hash or short message using * an asymmetric public key in a secure element * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Key slot of a public key or an asymmetric key * pair * \param[in] alg A signature algorithm that is compatible with * the type of `key` * \param[in] p_hash The hash whose signature is to be verified * \param[in] hash_length Size of the `p_hash` buffer in bytes * \param[in] p_signature Buffer containing the signature to verify * \param[in] signature_length Size of the `p_signature` buffer in bytes * * \retval #PSA_SUCCESS * The signature is valid. */ typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_hash, size_t hash_length, const uint8_t *p_signature, size_t signature_length); /** * \brief A function that encrypts a short message with an asymmetric public * key in a secure element * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Key slot of a public key or an asymmetric key * pair * \param[in] alg An asymmetric encryption algorithm that is * compatible with the type of `key` * \param[in] p_input The message to encrypt * \param[in] input_length Size of the `p_input` buffer in bytes * \param[in] p_salt A salt or label, if supported by the * encryption algorithm * If the algorithm does not support a * salt, pass `NULL`. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass `NULL`. * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param[in] salt_length Size of the `p_salt` buffer in bytes * If `p_salt` is `NULL`, pass 0. * \param[out] p_output Buffer where the encrypted message is to * be written * \param[in] output_size Size of the `p_output` buffer in bytes * \param[out] p_output_length On success, the number of bytes that make up * the returned output * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_input, size_t input_length, const uint8_t *p_salt, size_t salt_length, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** * \brief A function that decrypts a short message with an asymmetric private * key in a secure element. * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Key slot of an asymmetric key pair * \param[in] alg An asymmetric encryption algorithm that is * compatible with the type of `key` * \param[in] p_input The message to decrypt * \param[in] input_length Size of the `p_input` buffer in bytes * \param[in] p_salt A salt or label, if supported by the * encryption algorithm * If the algorithm does not support a * salt, pass `NULL`. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass `NULL`. * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param[in] salt_length Size of the `p_salt` buffer in bytes * If `p_salt` is `NULL`, pass 0. * \param[out] p_output Buffer where the decrypted message is to * be written * \param[in] output_size Size of the `p_output` buffer in bytes * \param[out] p_output_length On success, the number of bytes * that make up the returned output * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_input, size_t input_length, const uint8_t *p_salt, size_t salt_length, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** * \brief A struct containing all of the function pointers needed to implement * asymmetric cryptographic operations using secure elements. * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup or at build time. * * If one of the functions is not implemented, it should be set to NULL. */ typedef struct { /** Function that performs an asymmetric sign operation */ psa_drv_se_asymmetric_sign_t MBEDTLS_PRIVATE(p_sign); /** Function that performs an asymmetric verify operation */ psa_drv_se_asymmetric_verify_t MBEDTLS_PRIVATE(p_verify); /** Function that performs an asymmetric encrypt operation */ psa_drv_se_asymmetric_encrypt_t MBEDTLS_PRIVATE(p_encrypt); /** Function that performs an asymmetric decrypt operation */ psa_drv_se_asymmetric_decrypt_t MBEDTLS_PRIVATE(p_decrypt); } psa_drv_se_asymmetric_t; /**@}*/ /** \defgroup se_aead Secure Element Authenticated Encryption with Additional Data * Authenticated Encryption with Additional Data (AEAD) operations with secure * elements must be done in one function call. While this creates a burden for * implementers as there must be sufficient space in memory for the entire * message, it prevents decrypted data from being made available before the * authentication operation is complete and the data is known to be authentic. */ /**@{*/ /** \brief A function that performs a secure element authenticated encryption * operation * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Slot containing the key to use. * \param[in] algorithm The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(`alg`) is true) * \param[in] p_nonce Nonce or IV to use * \param[in] nonce_length Size of the `p_nonce` buffer in bytes * \param[in] p_additional_data Additional data that will be * authenticated but not encrypted * \param[in] additional_data_length Size of `p_additional_data` in bytes * \param[in] p_plaintext Data that will be authenticated and * encrypted * \param[in] plaintext_length Size of `p_plaintext` in bytes * \param[out] p_ciphertext Output buffer for the authenticated and * encrypted data. The additional data is * not part of this output. For algorithms * where the encrypted data and the * authentication tag are defined as * separate outputs, the authentication * tag is appended to the encrypted data. * \param[in] ciphertext_size Size of the `p_ciphertext` buffer in * bytes * \param[out] p_ciphertext_length On success, the size of the output in * the `p_ciphertext` buffer * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm, const uint8_t *p_nonce, size_t nonce_length, const uint8_t *p_additional_data, size_t additional_data_length, const uint8_t *p_plaintext, size_t plaintext_length, uint8_t *p_ciphertext, size_t ciphertext_size, size_t *p_ciphertext_length); /** A function that performs a secure element authenticated decryption operation * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Slot containing the key to use * \param[in] algorithm The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(`alg`) is true) * \param[in] p_nonce Nonce or IV to use * \param[in] nonce_length Size of the `p_nonce` buffer in bytes * \param[in] p_additional_data Additional data that has been * authenticated but not encrypted * \param[in] additional_data_length Size of `p_additional_data` in bytes * \param[in] p_ciphertext Data that has been authenticated and * encrypted. * For algorithms where the encrypted data * and the authentication tag are defined * as separate inputs, the buffer must * contain the encrypted data followed by * the authentication tag. * \param[in] ciphertext_length Size of `p_ciphertext` in bytes * \param[out] p_plaintext Output buffer for the decrypted data * \param[in] plaintext_size Size of the `p_plaintext` buffer in * bytes * \param[out] p_plaintext_length On success, the size of the output in * the `p_plaintext` buffer * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm, const uint8_t *p_nonce, size_t nonce_length, const uint8_t *p_additional_data, size_t additional_data_length, const uint8_t *p_ciphertext, size_t ciphertext_length, uint8_t *p_plaintext, size_t plaintext_size, size_t *p_plaintext_length); /** * \brief A struct containing all of the function pointers needed to implement * secure element Authenticated Encryption with Additional Data operations * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup. * * If one of the functions is not implemented, it should be set to NULL. */ typedef struct { /** Function that performs the AEAD encrypt operation */ psa_drv_se_aead_encrypt_t MBEDTLS_PRIVATE(p_encrypt); /** Function that performs the AEAD decrypt operation */ psa_drv_se_aead_decrypt_t MBEDTLS_PRIVATE(p_decrypt); } psa_drv_se_aead_t; /**@}*/ /** \defgroup se_key_management Secure Element Key Management * Currently, key management is limited to importing keys in the clear, * destroying keys, and exporting keys in the clear. * Whether a key may be exported is determined by the key policies in place * on the key slot. */ /**@{*/ /** An enumeration indicating how a key is created. */ typedef enum { PSA_KEY_CREATION_IMPORT, /**< During psa_import_key() */ PSA_KEY_CREATION_GENERATE, /**< During psa_generate_key() */ PSA_KEY_CREATION_DERIVE, /**< During psa_key_derivation_output_key() */ PSA_KEY_CREATION_COPY, /**< During psa_copy_key() */ #ifndef __DOXYGEN_ONLY__ /** A key is being registered with mbedtls_psa_register_se_key(). * * The core only passes this value to * psa_drv_se_key_management_t::p_validate_slot_number, not to * psa_drv_se_key_management_t::p_allocate. The call to * `p_validate_slot_number` is not followed by any other call to the * driver: the key is considered successfully registered if the call to * `p_validate_slot_number` succeeds, or if `p_validate_slot_number` is * null. * * With this creation method, the driver must return #PSA_SUCCESS if * the given attributes are compatible with the existing key in the slot, * and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there * is no key with the specified slot number. * * This is an Mbed TLS extension. */ PSA_KEY_CREATION_REGISTER, #endif } psa_key_creation_method_t; /** \brief A function that allocates a slot for a key. * * To create a key in a specific slot in a secure element, the core * first calls this function to determine a valid slot number, * then calls a function to create the key material in that slot. * In nominal conditions (that is, if no error occurs), * the effect of a call to a key creation function in the PSA Cryptography * API with a lifetime that places the key in a secure element is the * following: * -# The core calls psa_drv_se_key_management_t::p_allocate * (or in some implementations * psa_drv_se_key_management_t::p_validate_slot_number). The driver * selects (or validates) a suitable slot number given the key attributes * and the state of the secure element. * -# The core calls a key creation function in the driver. * * The key creation functions in the PSA Cryptography API are: * - psa_import_key(), which causes * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_IMPORT * then a call to psa_drv_se_key_management_t::p_import. * - psa_generate_key(), which causes * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_GENERATE * then a call to psa_drv_se_key_management_t::p_import. * - psa_key_derivation_output_key(), which causes * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_DERIVE * then a call to psa_drv_se_key_derivation_t::p_derive. * - psa_copy_key(), which causes * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_COPY * then a call to psa_drv_se_key_management_t::p_export. * * In case of errors, other behaviors are possible. * - If the PSA Cryptography subsystem dies after the first step, * for example because the device has lost power abruptly, * the second step may never happen, or may happen after a reset * and re-initialization. Alternatively, after a reset and * re-initialization, the core may call * psa_drv_se_key_management_t::p_destroy on the slot number that * was allocated (or validated) instead of calling a key creation function. * - If an error occurs, the core may call * psa_drv_se_key_management_t::p_destroy on the slot number that * was allocated (or validated) instead of calling a key creation function. * * Errors and system resets also have an impact on the driver's persistent * data. If a reset happens before the overall key creation process is * completed (before or after the second step above), it is unspecified * whether the persistent data after the reset is identical to what it * was before or after the call to `p_allocate` (or `p_validate_slot_number`). * * \param[in,out] drv_context The driver context structure. * \param[in,out] persistent_data A pointer to the persistent data * that allows writing. * \param[in] attributes Attributes of the key. * \param method The way in which the key is being created. * \param[out] key_slot Slot where the key will be stored. * This must be a valid slot for a key of the * chosen type. It must be unoccupied. * * \retval #PSA_SUCCESS * Success. * The core will record \c *key_slot as the key slot where the key * is stored and will update the persistent data in storage. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription */ typedef psa_status_t (*psa_drv_se_allocate_key_t)( psa_drv_se_context_t *drv_context, void *persistent_data, const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_key_slot_number_t *key_slot); /** \brief A function that determines whether a slot number is valid * for a key. * * To create a key in a specific slot in a secure element, the core * first calls this function to validate the choice of slot number, * then calls a function to create the key material in that slot. * See the documentation of #psa_drv_se_allocate_key_t for more details. * * As of the PSA Cryptography API specification version 1.0, there is no way * for applications to trigger a call to this function. However some * implementations offer the capability to create or declare a key in * a specific slot via implementation-specific means, generally for the * sake of initial device provisioning or onboarding. Such a mechanism may * be added to a future version of the PSA Cryptography API specification. * * This function may update the driver's persistent data through * \p persistent_data. The core will save the updated persistent data at the * end of the key creation process. See the description of * ::psa_drv_se_allocate_key_t for more information. * * \param[in,out] drv_context The driver context structure. * \param[in,out] persistent_data A pointer to the persistent data * that allows writing. * \param[in] attributes Attributes of the key. * \param method The way in which the key is being created. * \param[in] key_slot Slot where the key is to be stored. * * \retval #PSA_SUCCESS * The given slot number is valid for a key with the given * attributes. * \retval #PSA_ERROR_INVALID_ARGUMENT * The given slot number is not valid for a key with the * given attributes. This includes the case where the slot * number is not valid at all. * \retval #PSA_ERROR_ALREADY_EXISTS * There is already a key with the specified slot number. * Drivers may choose to return this error from the key * creation function instead. */ typedef psa_status_t (*psa_drv_se_validate_slot_number_t)( psa_drv_se_context_t *drv_context, void *persistent_data, const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_key_slot_number_t key_slot); /** \brief A function that imports a key into a secure element in binary format * * This function can support any output from psa_export_key(). Refer to the * documentation of psa_export_key() for the format for each key type. * * \param[in,out] drv_context The driver context structure. * \param key_slot Slot where the key will be stored. * This must be a valid slot for a key of the * chosen type. It must be unoccupied. * \param[in] attributes The key attributes, including the lifetime, * the key type and the usage policy. * Drivers should not access the key size stored * in the attributes: it may not match the * data passed in \p data. * Drivers can call psa_get_key_lifetime(), * psa_get_key_type(), * psa_get_key_usage_flags() and * psa_get_key_algorithm() to access this * information. * \param[in] data Buffer containing the key data. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] bits On success, the key size in bits. The driver * must determine this value after parsing the * key according to the key type. * This value is not used if the function fails. * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_import_key_t)( psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, size_t *bits); /** * \brief A function that destroys a secure element key and restore the slot to * its default state * * This function destroys the content of the key from a secure element. * Implementations shall make a best effort to ensure that any previous content * of the slot is unrecoverable. * * This function returns the specified slot to its default state. * * \param[in,out] drv_context The driver context structure. * \param[in,out] persistent_data A pointer to the persistent data * that allows writing. * \param key_slot The key slot to erase. * * \retval #PSA_SUCCESS * The slot's content, if any, has been erased. */ typedef psa_status_t (*psa_drv_se_destroy_key_t)( psa_drv_se_context_t *drv_context, void *persistent_data, psa_key_slot_number_t key_slot); /** * \brief A function that exports a secure element key in binary format * * The output of this function can be passed to psa_import_key() to * create an equivalent object. * * If a key is created with `psa_import_key()` and then exported with * this function, it is not guaranteed that the resulting data is * identical: the implementation may choose a different representation * of the same key if the format permits it. * * This function should generate output in the same format that * `psa_export_key()` does. Refer to the * documentation of `psa_export_key()` for the format for each key type. * * \param[in,out] drv_context The driver context structure. * \param[in] key Slot whose content is to be exported. This must * be an occupied key slot. * \param[out] p_data Buffer where the key data is to be written. * \param[in] data_size Size of the `p_data` buffer in bytes. * \param[out] p_data_length On success, the number of bytes * that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ typedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key, uint8_t *p_data, size_t data_size, size_t *p_data_length); /** * \brief A function that generates a symmetric or asymmetric key on a secure * element * * If the key type \c type recorded in \p attributes * is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\c type) = 1), * the driver may export the public key at the time of generation, * in the format documented for psa_export_public_key() by writing it * to the \p pubkey buffer. * This is optional, intended for secure elements that output the * public key at generation time and that cannot export the public key * later. Drivers that do not need this feature should leave * \p *pubkey_length set to 0 and should * implement the psa_drv_key_management_t::p_export_public function. * Some implementations do not support this feature, in which case * \p pubkey is \c NULL and \p pubkey_size is 0. * * \param[in,out] drv_context The driver context structure. * \param key_slot Slot where the key will be stored. * This must be a valid slot for a key of the * chosen type. It must be unoccupied. * \param[in] attributes The key attributes, including the lifetime, * the key type and size, and the usage policy. * Drivers can call psa_get_key_lifetime(), * psa_get_key_type(), psa_get_key_bits(), * psa_get_key_usage_flags() and * psa_get_key_algorithm() to access this * information. * \param[out] pubkey A buffer where the driver can write the * public key, when generating an asymmetric * key pair. * This is \c NULL when generating a symmetric * key or if the core does not support * exporting the public key at generation time. * \param pubkey_size The size of the `pubkey` buffer in bytes. * This is 0 when generating a symmetric * key or if the core does not support * exporting the public key at generation time. * \param[out] pubkey_length On entry, this is always 0. * On success, the number of bytes written to * \p pubkey. If this is 0 or unchanged on return, * the core will not read the \p pubkey buffer, * and will instead call the driver's * psa_drv_key_management_t::p_export_public * function to export the public key when needed. */ typedef psa_status_t (*psa_drv_se_generate_key_t)( psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, const psa_key_attributes_t *attributes, uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length); /** * \brief A struct containing all of the function pointers needed to for secure * element key management * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup or at build time. * * If one of the functions is not implemented, it should be set to NULL. */ typedef struct { /** Function that allocates a slot for a key. */ psa_drv_se_allocate_key_t MBEDTLS_PRIVATE(p_allocate); /** Function that checks the validity of a slot for a key. */ psa_drv_se_validate_slot_number_t MBEDTLS_PRIVATE(p_validate_slot_number); /** Function that performs a key import operation */ psa_drv_se_import_key_t MBEDTLS_PRIVATE(p_import); /** Function that performs a generation */ psa_drv_se_generate_key_t MBEDTLS_PRIVATE(p_generate); /** Function that performs a key destroy operation */ psa_drv_se_destroy_key_t MBEDTLS_PRIVATE(p_destroy); /** Function that performs a key export operation */ psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export); /** Function that performs a public key export operation */ psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export_public); } psa_drv_se_key_management_t; /**@}*/ /** \defgroup driver_derivation Secure Element Key Derivation and Agreement * Key derivation is the process of generating new key material using an * existing key and additional parameters, iterating through a basic * cryptographic function, such as a hash. * Key agreement is a part of cryptographic protocols that allows two parties * to agree on the same key value, but starting from different original key * material. * The flows are similar, and the PSA Crypto Driver Model uses the same functions * for both of the flows. * * There are two different final functions for the flows, * `psa_drv_se_key_derivation_derive` and `psa_drv_se_key_derivation_export`. * `psa_drv_se_key_derivation_derive` is used when the key material should be * placed in a slot on the hardware and not exposed to the caller. * `psa_drv_se_key_derivation_export` is used when the key material should be * returned to the PSA Cryptographic API implementation. * * Different key derivation algorithms require a different number of inputs. * Instead of having an API that takes as input variable length arrays, which * can be problematic to manage on embedded platforms, the inputs are passed * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that * is called multiple times with different `collateral_id`s. Thus, for a key * derivation algorithm that required 3 parameter inputs, the flow would look * something like: * ~~~~~~~~~~~~~{.c} * psa_drv_se_key_derivation_setup(kdf_algorithm, source_key, dest_key_size_bytes); * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_0, * p_collateral_0, * collateral_0_size); * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_1, * p_collateral_1, * collateral_1_size); * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_2, * p_collateral_2, * collateral_2_size); * psa_drv_se_key_derivation_derive(); * ~~~~~~~~~~~~~ * * key agreement example: * ~~~~~~~~~~~~~{.c} * psa_drv_se_key_derivation_setup(alg, source_key. dest_key_size_bytes); * psa_drv_se_key_derivation_collateral(DHE_PUBKEY, p_pubkey, pubkey_size); * psa_drv_se_key_derivation_export(p_session_key, * session_key_size, * &session_key_length); * ~~~~~~~~~~~~~ */ /**@{*/ /** \brief A function that Sets up a secure element key derivation operation by * specifying the algorithm and the source key sot * * \param[in,out] drv_context The driver context structure. * \param[in,out] op_context A hardware-specific structure containing any * context information for the implementation * \param[in] kdf_alg The algorithm to be used for the key derivation * \param[in] source_key The key to be used as the source material for * the key derivation * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context, void *op_context, psa_algorithm_t kdf_alg, psa_key_slot_number_t source_key); /** \brief A function that provides collateral (parameters) needed for a secure * element key derivation or key agreement operation * * Since many key derivation algorithms require multiple parameters, it is * expected that this function may be called multiple times for the same * operation, each with a different algorithm-specific `collateral_id` * * \param[in,out] op_context A hardware-specific structure containing any * context information for the implementation * \param[in] collateral_id An ID for the collateral being provided * \param[in] p_collateral A buffer containing the collateral data * \param[in] collateral_size The size in bytes of the collateral * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context, uint32_t collateral_id, const uint8_t *p_collateral, size_t collateral_size); /** \brief A function that performs the final secure element key derivation * step and place the generated key material in a slot * * \param[in,out] op_context A hardware-specific structure containing any * context information for the implementation * \param[in] dest_key The slot where the generated key material * should be placed * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context, psa_key_slot_number_t dest_key); /** \brief A function that performs the final step of a secure element key * agreement and place the generated key material in a buffer * * \param[out] p_output Buffer in which to place the generated key * material * \param[in] output_size The size in bytes of `p_output` * \param[out] p_output_length Upon success, contains the number of bytes of * key material placed in `p_output` * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** * \brief A struct containing all of the function pointers needed to for secure * element key derivation and agreement * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup. * * If one of the functions is not implemented, it should be set to NULL. */ typedef struct { /** The driver-specific size of the key derivation context */ size_t MBEDTLS_PRIVATE(context_size); /** Function that performs a key derivation setup */ psa_drv_se_key_derivation_setup_t MBEDTLS_PRIVATE(p_setup); /** Function that sets key derivation collateral */ psa_drv_se_key_derivation_collateral_t MBEDTLS_PRIVATE(p_collateral); /** Function that performs a final key derivation step */ psa_drv_se_key_derivation_derive_t MBEDTLS_PRIVATE(p_derive); /** Function that performs a final key derivation or agreement and * exports the key */ psa_drv_se_key_derivation_export_t MBEDTLS_PRIVATE(p_export); } psa_drv_se_key_derivation_t; /**@}*/ /** \defgroup se_registration Secure element driver registration */ /**@{*/ /** A structure containing pointers to all the entry points of a * secure element driver. * * Future versions of this specification may add extra substructures at * the end of this structure. */ typedef struct { /** The version of the driver HAL that this driver implements. * This is a protection against loading driver binaries built against * a different version of this specification. * Use #PSA_DRV_SE_HAL_VERSION. */ uint32_t MBEDTLS_PRIVATE(hal_version); /** The size of the driver's persistent data in bytes. * * This can be 0 if the driver does not need persistent data. * * See the documentation of psa_drv_se_context_t::persistent_data * for more information about why and how a driver can use * persistent data. */ size_t MBEDTLS_PRIVATE(persistent_data_size); /** The driver initialization function. * * This function is called once during the initialization of the * PSA Cryptography subsystem, before any other function of the * driver is called. If this function returns a failure status, * the driver will be unusable, at least until the next system reset. * * If this field is \c NULL, it is equivalent to a function that does * nothing and returns #PSA_SUCCESS. */ psa_drv_se_init_t MBEDTLS_PRIVATE(p_init); const psa_drv_se_key_management_t *MBEDTLS_PRIVATE(key_management); const psa_drv_se_mac_t *MBEDTLS_PRIVATE(mac); const psa_drv_se_cipher_t *MBEDTLS_PRIVATE(cipher); const psa_drv_se_aead_t *MBEDTLS_PRIVATE(aead); const psa_drv_se_asymmetric_t *MBEDTLS_PRIVATE(asymmetric); const psa_drv_se_key_derivation_t *MBEDTLS_PRIVATE(derivation); } psa_drv_se_t; /** The current version of the secure element driver HAL. */ /* 0.0.0 patchlevel 5 */ #define PSA_DRV_SE_HAL_VERSION 0x00000005 /** Register an external cryptoprocessor (secure element) driver. * * This function is only intended to be used by driver code, not by * application code. In implementations with separation between the * PSA cryptography module and applications, this function should * only be available to callers that run in the same memory space as * the cryptography module, and should not be exposed to applications * running in a different memory space. * * This function may be called before psa_crypto_init(). It is * implementation-defined whether this function may be called * after psa_crypto_init(). * * \note Implementations store metadata about keys including the lifetime * value, which contains the driver's location indicator. Therefore, * from one instantiation of the PSA Cryptography * library to the next one, if there is a key in storage with a certain * lifetime value, you must always register the same driver (or an * updated version that communicates with the same secure element) * with the same location value. * * \param location The location value through which this driver will * be exposed to applications. * This driver will be used for all keys such that * `location == #PSA_KEY_LIFETIME_GET_LOCATION( lifetime )`. * The value #PSA_KEY_LOCATION_LOCAL_STORAGE is reserved * and may not be used for drivers. Implementations * may reserve other values. * \param[in] methods The method table of the driver. This structure must * remain valid for as long as the cryptography * module keeps running. It is typically a global * constant. * * \return #PSA_SUCCESS * The driver was successfully registered. Applications can now * use \p location to access keys through the methods passed to * this function. * \return #PSA_ERROR_BAD_STATE * This function was called after the initialization of the * cryptography module, and this implementation does not support * driver registration at this stage. * \return #PSA_ERROR_ALREADY_EXISTS * There is already a registered driver for this value of \p location. * \return #PSA_ERROR_INVALID_ARGUMENT * \p location is a reserved value. * \return #PSA_ERROR_NOT_SUPPORTED * `methods->hal_version` is not supported by this implementation. * \return #PSA_ERROR_INSUFFICIENT_MEMORY * \return #PSA_ERROR_NOT_PERMITTED * \return #PSA_ERROR_STORAGE_FAILURE * \return #PSA_ERROR_DATA_CORRUPT */ psa_status_t psa_register_se_driver( psa_key_location_t location, const psa_drv_se_t *methods); /**@}*/ #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_SE_DRIVER_H */ webfakes/src/mbedtls/include/psa/crypto_builtin_composites.h0000644000176200001440000001637414740737024024177 0ustar liggesusers/* * Context structure declaration of the Mbed TLS software-based PSA drivers * called through the PSA Crypto driver dispatch layer. * This file contains the context structures of those algorithms which need to * rely on other algorithms, i.e. are 'composite' algorithms. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the Mbed TLS software-based PSA drivers. The * definitions of these objects are then used by crypto_struct.h to define the * implementation-defined types of PSA multi-part state objects. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILTIN_COMPOSITES_H #define PSA_CRYPTO_BUILTIN_COMPOSITES_H #include "mbedtls/private_access.h" #include #include "mbedtls/cmac.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) #include "mbedtls/gcm.h" #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) #include "mbedtls/ccm.h" #endif #include "mbedtls/chachapoly.h" /* * MAC multi-part operation definitions. */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) #define MBEDTLS_PSA_BUILTIN_MAC #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) typedef struct { /** The HMAC algorithm in use */ psa_algorithm_t MBEDTLS_PRIVATE(alg); /** The hash context. */ struct psa_hash_operation_s hash_ctx; /** The HMAC part of the context. */ uint8_t MBEDTLS_PRIVATE(opad)[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; } mbedtls_psa_hmac_operation_t; #define MBEDTLS_PSA_HMAC_OPERATION_INIT { 0, PSA_HASH_OPERATION_INIT, { 0 } } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ typedef struct { psa_algorithm_t MBEDTLS_PRIVATE(alg); union { unsigned MBEDTLS_PRIVATE(dummy); /* Make the union non-empty even with no supported algorithms. */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_psa_hmac_operation_t MBEDTLS_PRIVATE(hmac); #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_cipher_context_t MBEDTLS_PRIVATE(cmac); #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_mac_operation_t; #define MBEDTLS_PSA_MAC_OPERATION_INIT { 0, { 0 } } #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) #define MBEDTLS_PSA_BUILTIN_AEAD 1 #endif /* Context structure for the Mbed TLS AEAD implementation. */ typedef struct { psa_algorithm_t MBEDTLS_PRIVATE(alg); psa_key_type_t MBEDTLS_PRIVATE(key_type); unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; uint8_t MBEDTLS_PRIVATE(tag_length); union { unsigned dummy; /* Enable easier initializing of the union. */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) mbedtls_ccm_context MBEDTLS_PRIVATE(ccm); #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) mbedtls_gcm_context MBEDTLS_PRIVATE(gcm); #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) mbedtls_chachapoly_context MBEDTLS_PRIVATE(chachapoly); #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ } ctx; } mbedtls_psa_aead_operation_t; #define MBEDTLS_PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, { 0 } } #include "mbedtls/ecdsa.h" /* Context structure for the Mbed TLS interruptible sign hash implementation. */ typedef struct { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx); mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx); uint32_t MBEDTLS_PRIVATE(num_ops); size_t MBEDTLS_PRIVATE(coordinate_bytes); psa_algorithm_t MBEDTLS_PRIVATE(alg); mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; size_t MBEDTLS_PRIVATE(hash_length); #else /* Make the struct non-empty if algs not supported. */ unsigned MBEDTLS_PRIVATE(dummy); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } mbedtls_psa_sign_hash_interruptible_operation_t; #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) #define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 } #else #define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } #endif /* Context structure for the Mbed TLS interruptible verify hash * implementation.*/ typedef struct { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx); mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx); uint32_t MBEDTLS_PRIVATE(num_ops); uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; size_t MBEDTLS_PRIVATE(hash_length); mbedtls_mpi MBEDTLS_PRIVATE(r); mbedtls_mpi MBEDTLS_PRIVATE(s); #else /* Make the struct non-empty if algs not supported. */ unsigned MBEDTLS_PRIVATE(dummy); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } mbedtls_psa_verify_hash_interruptible_operation_t; #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) #define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, \ { 0 } } #else #define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } #endif /* EC-JPAKE operation definitions */ #include "mbedtls/ecjpake.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) #define MBEDTLS_PSA_BUILTIN_PAKE 1 #endif /* Note: the format for mbedtls_ecjpake_read/write function has an extra * length byte for each step, plus an extra 3 bytes for ECParameters in the * server's 2nd round. */ #define MBEDTLS_PSA_JPAKE_BUFFER_SIZE ((3 + 1 + 65 + 1 + 65 + 1 + 32) * 2) typedef struct { psa_algorithm_t MBEDTLS_PRIVATE(alg); uint8_t *MBEDTLS_PRIVATE(password); size_t MBEDTLS_PRIVATE(password_len); #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) mbedtls_ecjpake_role MBEDTLS_PRIVATE(role); uint8_t MBEDTLS_PRIVATE(buffer[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]); size_t MBEDTLS_PRIVATE(buffer_length); size_t MBEDTLS_PRIVATE(buffer_offset); #endif /* Context structure for the Mbed TLS EC-JPAKE implementation. */ union { unsigned int MBEDTLS_PRIVATE(dummy); #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) mbedtls_ecjpake_context MBEDTLS_PRIVATE(jpake); #endif } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_pake_operation_t; #define MBEDTLS_PSA_PAKE_OPERATION_INIT { { 0 } } #endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */ webfakes/src/mbedtls/include/psa/crypto_extra.h0000644000176200001440000024010614740737024021377 0ustar liggesusers/** * \file psa/crypto_extra.h * * \brief PSA cryptography module: Mbed TLS vendor extensions * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * This file is reserved for vendor-specific definitions. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_EXTRA_H #define PSA_CRYPTO_EXTRA_H #include "mbedtls/private_access.h" #include "crypto_types.h" #include "crypto_compat.h" #ifdef __cplusplus extern "C" { #endif /* UID for secure storage seed */ #define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52 /* See mbedtls_config.h for definition */ #if !defined(MBEDTLS_PSA_KEY_SLOT_COUNT) #define MBEDTLS_PSA_KEY_SLOT_COUNT 32 #endif /** \addtogroup attributes * @{ */ /** \brief Declare the enrollment algorithm for a key. * * An operation on a key may indifferently use the algorithm set with * psa_set_key_algorithm() or with this function. * * \param[out] attributes The attribute structure to write to. * \param alg2 A second algorithm that the key may be used * for, in addition to the algorithm set with * psa_set_key_algorithm(). * * \warning Setting an enrollment algorithm is not recommended, because * using the same key with different algorithms can allow some * attacks based on arithmetic relations between different * computations made with the same key, or can escalate harmless * side channels into exploitable ones. Use this function only * if it is necessary to support a protocol for which it has been * verified that the usage of the key with multiple algorithms * is safe. */ static inline void psa_set_key_enrollment_algorithm( psa_key_attributes_t *attributes, psa_algorithm_t alg2) { attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) = alg2; } /** Retrieve the enrollment algorithm policy from key attributes. * * \param[in] attributes The key attribute structure to query. * * \return The enrollment algorithm stored in the attribute structure. */ static inline psa_algorithm_t psa_get_key_enrollment_algorithm( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2); } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /** Retrieve the slot number where a key is stored. * * A slot number is only defined for keys that are stored in a secure * element. * * This information is only useful if the secure element is not entirely * managed through the PSA Cryptography API. It is up to the secure * element driver to decide how PSA slot numbers map to any other interface * that the secure element may have. * * \param[in] attributes The key attribute structure to query. * \param[out] slot_number On success, the slot number containing the key. * * \retval #PSA_SUCCESS * The key is located in a secure element, and \p *slot_number * indicates the slot number that contains it. * \retval #PSA_ERROR_NOT_PERMITTED * The caller is not permitted to query the slot number. * Mbed TLS currently does not return this error. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key is not located in a secure element. */ psa_status_t psa_get_key_slot_number( const psa_key_attributes_t *attributes, psa_key_slot_number_t *slot_number); /** Choose the slot number where a key is stored. * * This function declares a slot number in the specified attribute * structure. * * A slot number is only meaningful for keys that are stored in a secure * element. It is up to the secure element driver to decide how PSA slot * numbers map to any other interface that the secure element may have. * * \note Setting a slot number in key attributes for a key creation can * cause the following errors when creating the key: * - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does * not support choosing a specific slot number. * - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to * choose slot numbers in general or to choose this specific slot. * - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not * valid in general or not valid for this specific key. * - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the * selected slot. * * \param[out] attributes The attribute structure to write to. * \param slot_number The slot number to set. */ static inline void psa_set_key_slot_number( psa_key_attributes_t *attributes, psa_key_slot_number_t slot_number) { attributes->MBEDTLS_PRIVATE(has_slot_number) = 1; attributes->MBEDTLS_PRIVATE(slot_number) = slot_number; } /** Remove the slot number attribute from a key attribute structure. * * This function undoes the action of psa_set_key_slot_number(). * * \param[out] attributes The attribute structure to write to. */ static inline void psa_clear_key_slot_number( psa_key_attributes_t *attributes) { attributes->MBEDTLS_PRIVATE(has_slot_number) = 0; } /** Register a key that is already present in a secure element. * * The key must be located in a secure element designated by the * lifetime field in \p attributes, in the slot set with * psa_set_key_slot_number() in the attribute structure. * This function makes the key available through the key identifier * specified in \p attributes. * * \param[in] attributes The attributes of the existing key. * - The lifetime must be a persistent lifetime * in a secure element. Volatile lifetimes are * not currently supported. * - The key identifier must be in the valid * range for persistent keys. * - The key type and size must be specified and * must be consistent with the key material * in the secure element. * * \retval #PSA_SUCCESS * The key was successfully registered. * Note that depending on the design of the driver, this may or may * not guarantee that a key actually exists in the designated slot * and is compatible with the specified attributes. * \retval #PSA_ERROR_ALREADY_EXISTS * There is already a key with the identifier specified in * \p attributes. * \retval #PSA_ERROR_NOT_SUPPORTED * The secure element driver for the specified lifetime does not * support registering a key. * \retval #PSA_ERROR_INVALID_ARGUMENT * The identifier in \p attributes is invalid, namely the identifier is * not in the user range, or * \p attributes specifies a lifetime which is not located * in a secure element, or no slot number is specified in \p attributes, * or the specified slot number is not valid. * \retval #PSA_ERROR_NOT_PERMITTED * The caller is not authorized to register the specified key slot. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t mbedtls_psa_register_se_key( const psa_key_attributes_t *attributes); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ /**@}*/ /** * \brief Library deinitialization. * * This function clears all data associated with the PSA layer, * including the whole key store. * This function is not thread safe, it wipes every key slot regardless of * state and reader count. It should only be called when no slot is in use. * * This is an Mbed TLS extension. */ void mbedtls_psa_crypto_free(void); /** \brief Statistics about * resource consumption related to the PSA keystore. * * \note The content of this structure is not part of the stable API and ABI * of Mbed TLS and may change arbitrarily from version to version. */ typedef struct mbedtls_psa_stats_s { /** Number of slots containing key material for a volatile key. */ size_t MBEDTLS_PRIVATE(volatile_slots); /** Number of slots containing key material for a key which is in * internal persistent storage. */ size_t MBEDTLS_PRIVATE(persistent_slots); /** Number of slots containing a reference to a key in a * secure element. */ size_t MBEDTLS_PRIVATE(external_slots); /** Number of slots which are occupied, but do not contain * key material yet. */ size_t MBEDTLS_PRIVATE(half_filled_slots); /** Number of slots that contain cache data. */ size_t MBEDTLS_PRIVATE(cache_slots); /** Number of slots that are not used for anything. */ size_t MBEDTLS_PRIVATE(empty_slots); /** Number of slots that are locked. */ size_t MBEDTLS_PRIVATE(locked_slots); /** Largest key id value among open keys in internal persistent storage. */ psa_key_id_t MBEDTLS_PRIVATE(max_open_internal_key_id); /** Largest key id value among open keys in secure elements. */ psa_key_id_t MBEDTLS_PRIVATE(max_open_external_key_id); } mbedtls_psa_stats_t; /** \brief Get statistics about * resource consumption related to the PSA keystore. * * \note When Mbed TLS is built as part of a service, with isolation * between the application and the keystore, the service may or * may not expose this function. */ void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats); /** * \brief Inject an initial entropy seed for the random generator into * secure storage. * * This function injects data to be used as a seed for the random generator * used by the PSA Crypto implementation. On devices that lack a trusted * entropy source (preferably a hardware random number generator), * the Mbed PSA Crypto implementation uses this value to seed its * random generator. * * On devices without a trusted entropy source, this function must be * called exactly once in the lifetime of the device. On devices with * a trusted entropy source, calling this function is optional. * In all cases, this function may only be called before calling any * other function in the PSA Crypto API, including psa_crypto_init(). * * When this function returns successfully, it populates a file in * persistent storage. Once the file has been created, this function * can no longer succeed. * * If any error occurs, this function does not change the system state. * You can call this function again after correcting the reason for the * error if possible. * * \warning This function **can** fail! Callers MUST check the return status. * * \warning If you use this function, you should use it as part of a * factory provisioning process. The value of the injected seed * is critical to the security of the device. It must be * *secret*, *unpredictable* and (statistically) *unique per device*. * You should be generate it randomly using a cryptographically * secure random generator seeded from trusted entropy sources. * You should transmit it securely to the device and ensure * that its value is not leaked or stored anywhere beyond the * needs of transmitting it from the point of generation to * the call of this function, and erase all copies of the value * once this function returns. * * This is an Mbed TLS extension. * * \note This function is only available on the following platforms: * * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled. * Note that you must provide compatible implementations of * mbedtls_nv_seed_read and mbedtls_nv_seed_write. * * In a client-server integration of PSA Cryptography, on the client side, * if the server supports this feature. * \param[in] seed Buffer containing the seed value to inject. * \param[in] seed_size Size of the \p seed buffer. * The size of the seed in bytes must be greater * or equal to both #MBEDTLS_ENTROPY_BLOCK_SIZE * and the value of \c MBEDTLS_ENTROPY_MIN_PLATFORM * in `library/entropy_poll.h` in the Mbed TLS source * code. * It must be less or equal to * #MBEDTLS_ENTROPY_MAX_SEED_SIZE. * * \retval #PSA_SUCCESS * The seed value was injected successfully. The random generator * of the PSA Crypto implementation is now ready for use. * You may now call psa_crypto_init() and use the PSA Crypto * implementation. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p seed_size is out of range. * \retval #PSA_ERROR_STORAGE_FAILURE * There was a failure reading or writing from storage. * \retval #PSA_ERROR_NOT_PERMITTED * The library has already been initialized. It is no longer * possible to call this function. */ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size); /** \addtogroup crypto_types * @{ */ /** DSA public key. * * The import and export format is the * representation of the public key `y = g^x mod p` as a big-endian byte * string. The length of the byte string is the length of the base prime `p` * in bytes. */ #define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t) 0x4002) /** DSA key pair (private and public key). * * The import and export format is the * representation of the private key `x` as a big-endian byte string. The * length of the byte string is the private key size in bytes (leading zeroes * are not stripped). * * Deterministic DSA key derivation with psa_generate_derived_key follows * FIPS 186-4 §B.1.2: interpret the byte string as integer * in big-endian order. Discard it if it is not in the range * [0, *N* - 2] where *N* is the boundary of the private key domain * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, * or the order of the curve's base point for ECC). * Add 1 to the resulting integer and use this as the private key *x*. * */ #define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t) 0x7002) /** Whether a key type is a DSA key (pair or public-only). */ #define PSA_KEY_TYPE_IS_DSA(type) \ (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) #define PSA_ALG_DSA_BASE ((psa_algorithm_t) 0x06000400) /** DSA signature with hashing. * * This is the signature scheme defined by FIPS 186-4, * with a random per-message secret number (*k*). * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding DSA signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_DSA(hash_alg) \ (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t) 0x06000500) #define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG /** Deterministic DSA signature with hashing. * * This is the deterministic variant defined by RFC 6979 of * the signature scheme defined by FIPS 186-4. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding DSA signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_IS_DSA(alg) \ (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ PSA_ALG_DSA_BASE) #define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) #define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) #define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) /* We need to expand the sample definition of this macro from * the API definition. */ #undef PSA_ALG_IS_VENDOR_HASH_AND_SIGN #define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) \ PSA_ALG_IS_DSA(alg) /**@}*/ /** \addtogroup attributes * @{ */ /** PAKE operation stages. */ #define PSA_PAKE_OPERATION_STAGE_SETUP 0 #define PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS 1 #define PSA_PAKE_OPERATION_STAGE_COMPUTATION 2 /**@}*/ /** \defgroup psa_external_rng External random generator * @{ */ #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) /** External random generator function, implemented by the platform. * * When the compile-time option #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled, * this function replaces Mbed TLS's entropy and DRBG modules for all * random generation triggered via PSA crypto interfaces. * * \note This random generator must deliver random numbers with cryptographic * quality and high performance. It must supply unpredictable numbers * with a uniform distribution. The implementation of this function * is responsible for ensuring that the random generator is seeded * with sufficient entropy. If you have a hardware TRNG which is slow * or delivers non-uniform output, declare it as an entropy source * with mbedtls_entropy_add_source() instead of enabling this option. * * \param[in,out] context Pointer to the random generator context. * This is all-bits-zero on the first call * and preserved between successive calls. * \param[out] output Output buffer. On success, this buffer * contains random data with a uniform * distribution. * \param output_size The size of the \p output buffer in bytes. * \param[out] output_length On success, set this value to \p output_size. * * \retval #PSA_SUCCESS * Success. The output buffer contains \p output_size bytes of * cryptographic-quality random data, and \c *output_length is * set to \p output_size. * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY * The random generator requires extra entropy and there is no * way to obtain entropy under current environment conditions. * This error should not happen under normal circumstances since * this function is responsible for obtaining as much entropy as * it needs. However implementations of this function may return * #PSA_ERROR_INSUFFICIENT_ENTROPY if there is no way to obtain * entropy without blocking indefinitely. * \retval #PSA_ERROR_HARDWARE_FAILURE * A failure of the random generator hardware that isn't covered * by #PSA_ERROR_INSUFFICIENT_ENTROPY. */ psa_status_t mbedtls_psa_external_get_random( mbedtls_psa_external_random_context_t *context, uint8_t *output, size_t output_size, size_t *output_length); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ /**@}*/ /** \defgroup psa_builtin_keys Built-in keys * @{ */ /** The minimum value for a key identifier that is built into the * implementation. * * The range of key identifiers from #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN * to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX within the range from * #PSA_KEY_ID_VENDOR_MIN and #PSA_KEY_ID_VENDOR_MAX and must not intersect * with any other set of implementation-chosen key identifiers. * * This value is part of the library's API since changing it would invalidate * the values of built-in key identifiers in applications. */ #define MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ((psa_key_id_t) 0x7fff0000) /** The maximum value for a key identifier that is built into the * implementation. * * See #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN for more information. */ #define MBEDTLS_PSA_KEY_ID_BUILTIN_MAX ((psa_key_id_t) 0x7fffefff) /** A slot number identifying a key in a driver. * * Values of this type are used to identify built-in keys. */ typedef uint64_t psa_drv_slot_number_t; #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) /** Test whether a key identifier belongs to the builtin key range. * * \param key_id Key identifier to test. * * \retval 1 * The key identifier is a builtin key identifier. * \retval 0 * The key identifier is not a builtin key identifier. */ static inline int psa_key_id_is_builtin(psa_key_id_t key_id) { return (key_id >= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN) && (key_id <= MBEDTLS_PSA_KEY_ID_BUILTIN_MAX); } /** Platform function to obtain the location and slot number of a built-in key. * * An application-specific implementation of this function must be provided if * #MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS is enabled. This would typically be provided * as part of a platform's system image. * * #MBEDTLS_SVC_KEY_ID_GET_KEY_ID(\p key_id) needs to be in the range from * #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX. * * In a multi-application configuration * (\c MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER is defined), * this function should check that #MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(\p key_id) * is allowed to use the given key. * * \param key_id The key ID for which to retrieve the * location and slot attributes. * \param[out] lifetime On success, the lifetime associated with the key * corresponding to \p key_id. Lifetime is a * combination of which driver contains the key, * and with what persistence level the key is * intended to be used. If the platform * implementation does not contain specific * information about the intended key persistence * level, the persistence level may be reported as * #PSA_KEY_PERSISTENCE_DEFAULT. * \param[out] slot_number On success, the slot number known to the driver * registered at the lifetime location reported * through \p lifetime which corresponds to the * requested built-in key. * * \retval #PSA_SUCCESS * The requested key identifier designates a built-in key. * In a multi-application configuration, the requested owner * is allowed to access it. * \retval #PSA_ERROR_DOES_NOT_EXIST * The requested key identifier is not a built-in key which is known * to this function. If a key exists in the key storage with this * identifier, the data from the storage will be used. * \return (any other error) * Any other error is propagated to the function that requested the key. * Common errors include: * - #PSA_ERROR_NOT_PERMITTED: the key exists but the requested owner * is not allowed to access it. */ psa_status_t mbedtls_psa_platform_get_builtin_key( mbedtls_svc_key_id_t key_id, psa_key_lifetime_t *lifetime, psa_drv_slot_number_t *slot_number); #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ /** @} */ /** \addtogroup crypto_types * @{ */ #define PSA_ALG_CATEGORY_PAKE ((psa_algorithm_t) 0x0a000000) /** Whether the specified algorithm is a password-authenticated key exchange. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a password-authenticated key exchange (PAKE) * algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_PAKE(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE) /** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. * * This is J-PAKE as defined by RFC 8236, instantiated with the following * parameters: * * - The group can be either an elliptic curve or defined over a finite field. * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the * J-PAKE algorithm. * - A cryptographic hash function. * * To select these parameters and set up the cipher suite, call these functions * in any order: * * \code * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); * psa_pake_cs_set_primitive(cipher_suite, * PSA_PAKE_PRIMITIVE(type, family, bits)); * psa_pake_cs_set_hash(cipher_suite, hash); * \endcode * * For more information on how to set a specific curve or field, refer to the * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. * * After initializing a J-PAKE operation, call * * \code * psa_pake_setup(operation, cipher_suite); * psa_pake_set_user(operation, ...); * psa_pake_set_peer(operation, ...); * psa_pake_set_password_key(operation, ...); * \endcode * * The password is provided as a key. This can be the password text itself, * in an agreed character encoding, or some value derived from the password * as required by a higher level protocol. * * (The implementation converts the key material to a number as described in * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here * \c q is order of the group defined by the primitive set in the cipher suite. * The \c psa_pake_set_password_key() function returns an error if the result * of the reduction is 0.) * * The key exchange flow for J-PAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call * \code * // Get g1 * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Get the ZKP public key for x1 * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Get the ZKP proof for x1 * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * // Get g2 * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Get the ZKP public key for x2 * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Get the ZKP proof for x2 * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * \endcode * -# To provide the first round data received from the peer to the operation, * call * \code * // Set g3 * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Set the ZKP public key for x3 * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Set the ZKP proof for x3 * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * // Set g4 * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Set the ZKP public key for x4 * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Set the ZKP proof for x4 * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * \endcode * -# To get the second round data that needs to be sent to the peer, call * \code * // Get A * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Get ZKP public key for x2*s * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Get ZKP proof for x2*s * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * \endcode * -# To provide the second round data received from the peer to the operation, * call * \code * // Set B * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Set ZKP public key for x4*s * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Set ZKP proof for x4*s * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * \endcode * -# To access the shared secret call * \code * // Get Ka=Kb=K * psa_pake_get_implicit_key() * \endcode * * For more information consult the documentation of the individual * \c PSA_PAKE_STEP_XXX constants. * * At this point there is a cryptographic guarantee that only the authenticated * party who used the same password is able to compute the key. But there is no * guarantee that the peer is the party it claims to be and was able to do so. * * That is, the authentication is only implicit (the peer is not authenticated * at this point, and no action should be taken that assume that they are - like * for example accessing restricted files). * * To make the authentication explicit there are various methods, see Section 5 * of RFC 8236 for two examples. * */ #define PSA_ALG_JPAKE ((psa_algorithm_t) 0x0a000100) /** @} */ /** \defgroup pake Password-authenticated key exchange (PAKE) * * This is a proposed PAKE interface for the PSA Crypto API. It is not part of * the official PSA Crypto API yet. * * \note The content of this section is not part of the stable API and ABI * of Mbed TLS and may change arbitrarily from version to version. * Same holds for the corresponding macros #PSA_ALG_CATEGORY_PAKE and * #PSA_ALG_JPAKE. * @{ */ /** \brief Encoding of the application role of PAKE * * Encodes the application's role in the algorithm is being executed. For more * information see the documentation of individual \c PSA_PAKE_ROLE_XXX * constants. */ typedef uint8_t psa_pake_role_t; /** Encoding of input and output indicators for PAKE. * * Some PAKE algorithms need to exchange more data than just a single key share. * This type is for encoding additional input and output data for such * algorithms. */ typedef uint8_t psa_pake_step_t; /** Encoding of the type of the PAKE's primitive. * * Values defined by this standard will never be in the range 0x80-0xff. * Vendors who define additional types must use an encoding in this range. * * For more information see the documentation of individual * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. */ typedef uint8_t psa_pake_primitive_type_t; /** \brief Encoding of the family of the primitive associated with the PAKE. * * For more information see the documentation of individual * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. */ typedef uint8_t psa_pake_family_t; /** \brief Encoding of the primitive associated with the PAKE. * * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro. */ typedef uint32_t psa_pake_primitive_t; /** A value to indicate no role in a PAKE algorithm. * This value can be used in a call to psa_pake_set_role() for symmetric PAKE * algorithms which do not assign roles. */ #define PSA_PAKE_ROLE_NONE ((psa_pake_role_t) 0x00) /** The first peer in a balanced PAKE. * * Although balanced PAKE algorithms are symmetric, some of them needs an * ordering of peers for the transcript calculations. If the algorithm does not * need this, both #PSA_PAKE_ROLE_FIRST and #PSA_PAKE_ROLE_SECOND are * accepted. */ #define PSA_PAKE_ROLE_FIRST ((psa_pake_role_t) 0x01) /** The second peer in a balanced PAKE. * * Although balanced PAKE algorithms are symmetric, some of them needs an * ordering of peers for the transcript calculations. If the algorithm does not * need this, either #PSA_PAKE_ROLE_FIRST or #PSA_PAKE_ROLE_SECOND are * accepted. */ #define PSA_PAKE_ROLE_SECOND ((psa_pake_role_t) 0x02) /** The client in an augmented PAKE. * * Augmented PAKE algorithms need to differentiate between client and server. */ #define PSA_PAKE_ROLE_CLIENT ((psa_pake_role_t) 0x11) /** The server in an augmented PAKE. * * Augmented PAKE algorithms need to differentiate between client and server. */ #define PSA_PAKE_ROLE_SERVER ((psa_pake_role_t) 0x12) /** The PAKE primitive type indicating the use of elliptic curves. * * The values of the \c family and \c bits fields of the cipher suite identify a * specific elliptic curve, using the same mapping that is used for ECC * (::psa_ecc_family_t) keys. * * (Here \c family means the value returned by psa_pake_cs_get_family() and * \c bits means the value returned by psa_pake_cs_get_bits().) * * Input and output during the operation can involve group elements and scalar * values: * -# The format for group elements is the same as for public keys on the * specific curve would be. For more information, consult the documentation of * psa_export_public_key(). * -# The format for scalars is the same as for private keys on the specific * curve would be. For more information, consult the documentation of * psa_export_key(). */ #define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t) 0x01) /** The PAKE primitive type indicating the use of Diffie-Hellman groups. * * The values of the \c family and \c bits fields of the cipher suite identify * a specific Diffie-Hellman group, using the same mapping that is used for * Diffie-Hellman (::psa_dh_family_t) keys. * * (Here \c family means the value returned by psa_pake_cs_get_family() and * \c bits means the value returned by psa_pake_cs_get_bits().) * * Input and output during the operation can involve group elements and scalar * values: * -# The format for group elements is the same as for public keys on the * specific group would be. For more information, consult the documentation of * psa_export_public_key(). * -# The format for scalars is the same as for private keys on the specific * group would be. For more information, consult the documentation of * psa_export_key(). */ #define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t) 0x02) /** Construct a PAKE primitive from type, family and bit-size. * * \param pake_type The type of the primitive * (value of type ::psa_pake_primitive_type_t). * \param pake_family The family of the primitive * (the type and interpretation of this parameter depends * on \p pake_type, for more information consult the * documentation of individual ::psa_pake_primitive_type_t * constants). * \param pake_bits The bit-size of the primitive * (Value of type \c size_t. The interpretation * of this parameter depends on \p pake_family, for more * information consult the documentation of individual * ::psa_pake_primitive_type_t constants). * * \return The constructed primitive value of type ::psa_pake_primitive_t. * Return 0 if the requested primitive can't be encoded as * ::psa_pake_primitive_t. */ #define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ ((pake_bits & 0xFFFF) != pake_bits) ? 0 : \ ((psa_pake_primitive_t) (((pake_type) << 24 | \ (pake_family) << 16) | (pake_bits))) /** The key share being sent to or received from the peer. * * The format for both input and output at this step is the same as for public * keys on the group determined by the primitive (::psa_pake_primitive_t) would * be. * * For more information on the format, consult the documentation of * psa_export_public_key(). * * For information regarding how the group is determined, consult the * documentation #PSA_PAKE_PRIMITIVE. */ #define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t) 0x01) /** A Schnorr NIZKP public key. * * This is the ephemeral public key in the Schnorr Non-Interactive * Zero-Knowledge Proof (the value denoted by the letter 'V' in RFC 8235). * * The format for both input and output at this step is the same as for public * keys on the group determined by the primitive (::psa_pake_primitive_t) would * be. * * For more information on the format, consult the documentation of * psa_export_public_key(). * * For information regarding how the group is determined, consult the * documentation #PSA_PAKE_PRIMITIVE. */ #define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t) 0x02) /** A Schnorr NIZKP proof. * * This is the proof in the Schnorr Non-Interactive Zero-Knowledge Proof (the * value denoted by the letter 'r' in RFC 8235). * * Both for input and output, the value at this step is an integer less than * the order of the group selected in the cipher suite. The format depends on * the group as well: * * - For Montgomery curves, the encoding is little endian. * - For everything else the encoding is big endian (see Section 2.3.8 of * _SEC 1: Elliptic Curve Cryptography_ at https://www.secg.org/sec1-v2.pdf). * * In both cases leading zeroes are allowed as long as the length in bytes does * not exceed the byte length of the group order. * * For information regarding how the group is determined, consult the * documentation #PSA_PAKE_PRIMITIVE. */ #define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t) 0x03) /** The type of the data structure for PAKE cipher suites. * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t; /** Return an initial value for a PAKE cipher suite object. */ static psa_pake_cipher_suite_t psa_pake_cipher_suite_init(void); /** Retrieve the PAKE algorithm from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The PAKE algorithm stored in the cipher suite structure. */ static psa_algorithm_t psa_pake_cs_get_algorithm( const psa_pake_cipher_suite_t *cipher_suite); /** Declare the PAKE algorithm for the cipher suite. * * This function overwrites any PAKE algorithm * previously set in \p cipher_suite. * * \param[out] cipher_suite The cipher suite structure to write to. * \param algorithm The PAKE algorithm to write. * (`PSA_ALG_XXX` values of type ::psa_algorithm_t * such that #PSA_ALG_IS_PAKE(\c alg) is true.) * If this is 0, the PAKE algorithm in * \p cipher_suite becomes unspecified. */ static void psa_pake_cs_set_algorithm(psa_pake_cipher_suite_t *cipher_suite, psa_algorithm_t algorithm); /** Retrieve the primitive from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The primitive stored in the cipher suite structure. */ static psa_pake_primitive_t psa_pake_cs_get_primitive( const psa_pake_cipher_suite_t *cipher_suite); /** Declare the primitive for a PAKE cipher suite. * * This function overwrites any primitive previously set in \p cipher_suite. * * \param[out] cipher_suite The cipher suite structure to write to. * \param primitive The primitive to write. If this is 0, the * primitive type in \p cipher_suite becomes * unspecified. */ static void psa_pake_cs_set_primitive(psa_pake_cipher_suite_t *cipher_suite, psa_pake_primitive_t primitive); /** Retrieve the PAKE family from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The PAKE family stored in the cipher suite structure. */ static psa_pake_family_t psa_pake_cs_get_family( const psa_pake_cipher_suite_t *cipher_suite); /** Retrieve the PAKE primitive bit-size from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The PAKE primitive bit-size stored in the cipher suite structure. */ static uint16_t psa_pake_cs_get_bits( const psa_pake_cipher_suite_t *cipher_suite); /** Retrieve the hash algorithm from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The hash algorithm stored in the cipher suite structure. The return * value is 0 if the PAKE is not parametrised by a hash algorithm or if * the hash algorithm is not set. */ static psa_algorithm_t psa_pake_cs_get_hash( const psa_pake_cipher_suite_t *cipher_suite); /** Declare the hash algorithm for a PAKE cipher suite. * * This function overwrites any hash algorithm * previously set in \p cipher_suite. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * \param[out] cipher_suite The cipher suite structure to write to. * \param hash The hash involved in the cipher suite. * (`PSA_ALG_XXX` values of type ::psa_algorithm_t * such that #PSA_ALG_IS_HASH(\c alg) is true.) * If this is 0, the hash algorithm in * \p cipher_suite becomes unspecified. */ static void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite, psa_algorithm_t hash); /** The type of the state data structure for PAKE operations. * * Before calling any function on a PAKE operation object, the application * must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_pake_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_pake_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT, * for example: * \code * psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT; * \endcode * - Assign the result of the function psa_pake_operation_init() * to the structure, for example: * \code * psa_pake_operation_t operation; * operation = psa_pake_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_pake_operation_s psa_pake_operation_t; /** The type of input values for PAKE operations. */ typedef struct psa_crypto_driver_pake_inputs_s psa_crypto_driver_pake_inputs_t; /** The type of computation stage for J-PAKE operations. */ typedef struct psa_jpake_computation_stage_s psa_jpake_computation_stage_t; /** Return an initial value for a PAKE operation object. */ static psa_pake_operation_t psa_pake_operation_init(void); /** Get the length of the password in bytes from given inputs. * * \param[in] inputs Operation inputs. * \param[out] password_len Password length. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Password hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_password_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *password_len); /** Get the password from given inputs. * * \param[in] inputs Operation inputs. * \param[out] buffer Return buffer for password. * \param buffer_size Size of the return buffer in bytes. * \param[out] buffer_length Actual size of the password in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Password hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_password( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *buffer, size_t buffer_size, size_t *buffer_length); /** Get the length of the user id in bytes from given inputs. * * \param[in] inputs Operation inputs. * \param[out] user_len User id length. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * User id hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_user_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *user_len); /** Get the length of the peer id in bytes from given inputs. * * \param[in] inputs Operation inputs. * \param[out] peer_len Peer id length. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Peer id hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_peer_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *peer_len); /** Get the user id from given inputs. * * \param[in] inputs Operation inputs. * \param[out] user_id User id. * \param user_id_size Size of \p user_id in bytes. * \param[out] user_id_len Size of the user id in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * User id hasn't been set yet. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p user_id is too small. */ psa_status_t psa_crypto_driver_pake_get_user( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *user_id, size_t user_id_size, size_t *user_id_len); /** Get the peer id from given inputs. * * \param[in] inputs Operation inputs. * \param[out] peer_id Peer id. * \param peer_id_size Size of \p peer_id in bytes. * \param[out] peer_id_length Size of the peer id in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Peer id hasn't been set yet. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p peer_id is too small. */ psa_status_t psa_crypto_driver_pake_get_peer( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length); /** Get the cipher suite from given inputs. * * \param[in] inputs Operation inputs. * \param[out] cipher_suite Return buffer for role. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Cipher_suite hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_cipher_suite( const psa_crypto_driver_pake_inputs_t *inputs, psa_pake_cipher_suite_t *cipher_suite); /** Set the session information for a password-authenticated key exchange. * * The sequence of operations to set up a password-authenticated key exchange * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_pake_operation_t, e.g. * #PSA_PAKE_OPERATION_INIT. * -# Call psa_pake_setup() to specify the cipher suite. * -# Call \c psa_pake_set_xxx() functions on the operation to complete the * setup. The exact sequence of \c psa_pake_set_xxx() functions that needs * to be called depends on the algorithm in use. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * A typical sequence of calls to perform a password-authenticated key * exchange: * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the * key share that needs to be sent to the peer. * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide * the key share that was received from the peer. * -# Depending on the algorithm additional calls to psa_pake_output() and * psa_pake_input() might be necessary. * -# Call psa_pake_get_implicit_key() for accessing the shared secret. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * If an error occurs at any step after a call to psa_pake_setup(), * the operation will need to be reset by a call to psa_pake_abort(). The * application may call psa_pake_abort() at any time after the operation * has been initialized. * * After a successful call to psa_pake_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A call to psa_pake_abort(). * - A successful call to psa_pake_get_implicit_key(). * * \param[in,out] operation The operation object to set up. It must have * been initialized but not set up yet. * \param[in] cipher_suite The cipher suite to use. (A cipher suite fully * characterizes a PAKE algorithm and determines * the algorithm as well.) * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The algorithm in \p cipher_suite is not a PAKE algorithm, or the * PAKE primitive in \p cipher_suite is not compatible with the * PAKE algorithm, or the hash algorithm in \p cipher_suite is invalid * or not compatible with the PAKE algorithm and primitive. * \retval #PSA_ERROR_NOT_SUPPORTED * The algorithm in \p cipher_suite is not a supported PAKE algorithm, * or the PAKE primitive in \p cipher_suite is not supported or not * compatible with the PAKE algorithm, or the hash algorithm in * \p cipher_suite is not supported or not compatible with the PAKE * algorithm and primitive. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, const psa_pake_cipher_suite_t *cipher_suite); /** Set the password for a password-authenticated key exchange from key ID. * * Call this function when the password, or a value derived from the password, * is already present in the key store. * * \param[in,out] operation The operation object to set the password for. It * must have been set up by psa_pake_setup() and * not yet in use (neither psa_pake_output() nor * psa_pake_input() has been called yet). It must * be on operation for which the password hasn't * been set yet (psa_pake_set_password_key() * hasn't been called yet). * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a * memory-hard function). It must remain valid * until the operation terminates. It must be of * type #PSA_KEY_TYPE_PASSWORD or * #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow * the usage #PSA_KEY_USAGE_DERIVE. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE * \p password is not a valid key identifier. * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_DERIVE flag, or it does not * permit the \p operation's algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key type for \p password is not #PSA_KEY_TYPE_PASSWORD or * #PSA_KEY_TYPE_PASSWORD_HASH, or \p password is not compatible with * the \p operation's cipher suite. * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size of \p password is not supported with the * \p operation's cipher suite. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must have been set up.), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, mbedtls_svc_key_id_t password); /** Set the user ID for a password-authenticated key exchange. * * Call this function to set the user ID. For PAKE algorithms that associate a * user identifier with each side of the session you need to call * psa_pake_set_peer() as well. For PAKE algorithms that associate a single * user identifier with the session, call psa_pake_set_user() only. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * \param[in,out] operation The operation object to set the user ID for. It * must have been set up by psa_pake_setup() and * not yet in use (neither psa_pake_output() nor * psa_pake_input() has been called yet). It must * be on operation for which the user ID hasn't * been set (psa_pake_set_user() hasn't been * called yet). * \param[in] user_id The user ID to authenticate with. * \param user_id_len Size of the \p user_id buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p user_id is not valid for the \p operation's algorithm and cipher * suite. * \retval #PSA_ERROR_NOT_SUPPORTED * The value of \p user_id is not supported by the implementation. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, const uint8_t *user_id, size_t user_id_len); /** Set the peer ID for a password-authenticated key exchange. * * Call this function in addition to psa_pake_set_user() for PAKE algorithms * that associate a user identifier with each side of the session. For PAKE * algorithms that associate a single user identifier with the session, call * psa_pake_set_user() only. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * \param[in,out] operation The operation object to set the peer ID for. It * must have been set up by psa_pake_setup() and * not yet in use (neither psa_pake_output() nor * psa_pake_input() has been called yet). It must * be on operation for which the peer ID hasn't * been set (psa_pake_set_peer() hasn't been * called yet). * \param[in] peer_id The peer's ID to authenticate. * \param peer_id_len Size of the \p peer_id buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p peer_id is not valid for the \p operation's algorithm and cipher * suite. * \retval #PSA_ERROR_NOT_SUPPORTED * The algorithm doesn't associate a second identity with the session. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * Calling psa_pake_set_peer() is invalid with the \p operation's * algorithm, the operation state is not valid, or the library has not * been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, const uint8_t *peer_id, size_t peer_id_len); /** Set the application role for a password-authenticated key exchange. * * Not all PAKE algorithms need to differentiate the communicating entities. * It is optional to call this function for PAKEs that don't require a role * to be specified. For such PAKEs the application role parameter is ignored, * or #PSA_PAKE_ROLE_NONE can be passed as \c role. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * \param[in,out] operation The operation object to specify the * application's role for. It must have been set up * by psa_pake_setup() and not yet in use (neither * psa_pake_output() nor psa_pake_input() has been * called yet). It must be on operation for which * the application's role hasn't been specified * (psa_pake_set_role() hasn't been called yet). * \param role A value of type ::psa_pake_role_t indicating the * application's role in the PAKE the algorithm * that is being set up. For more information see * the documentation of \c PSA_PAKE_ROLE_XXX * constants. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The \p role is not a valid PAKE role in the \p operation’s algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * The \p role for this algorithm is not supported or is not valid. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_set_role(psa_pake_operation_t *operation, psa_pake_role_t role); /** Get output for a step of a password-authenticated key exchange. * * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_pake_abort(). * * \param[in,out] operation Active PAKE operation. * \param step The step of the algorithm for which the output is * requested. * \param[out] output Buffer where the output is to be written in the * format appropriate for this \p step. Refer to * the documentation of the individual * \c PSA_PAKE_STEP_XXX constants for more * information. * \param output_size Size of the \p output buffer in bytes. This must * be at least #PSA_PAKE_OUTPUT_SIZE(\c alg, \c * primitive, \p output_step) where \c alg and * \p primitive are the PAKE algorithm and primitive * in the operation's cipher suite, and \p step is * the output step. * * \param[out] output_length On success, the number of bytes of the returned * output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p step is not compatible with the operation's algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * \p step is not supported with the operation's algorithm. * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, and fully set * up, and this call must conform to the algorithm's requirements * for ordering of input and output steps), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_output(psa_pake_operation_t *operation, psa_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length); /** Provide input for a step of a password-authenticated key exchange. * * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_pake_abort(). * * \param[in,out] operation Active PAKE operation. * \param step The step for which the input is provided. * \param[in] input Buffer containing the input in the format * appropriate for this \p step. Refer to the * documentation of the individual * \c PSA_PAKE_STEP_XXX constants for more * information. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_SIGNATURE * The verification fails for a #PSA_PAKE_STEP_ZK_PROOF input step. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p input_length is not compatible with the \p operation’s algorithm, * or the \p input is not valid for the \p operation's algorithm, * cipher suite or \p step. * \retval #PSA_ERROR_NOT_SUPPORTED * \p step p is not supported with the \p operation's algorithm, or the * \p input is not supported for the \p operation's algorithm, cipher * suite or \p step. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, and fully set * up, and this call must conform to the algorithm's requirements * for ordering of input and output steps), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_input(psa_pake_operation_t *operation, psa_pake_step_t step, const uint8_t *input, size_t input_length); /** Get implicitly confirmed shared secret from a PAKE. * * At this point there is a cryptographic guarantee that only the authenticated * party who used the same password is able to compute the key. But there is no * guarantee that the peer is the party it claims to be and was able to do so. * * That is, the authentication is only implicit. Since the peer is not * authenticated yet, no action should be taken yet that assumes that the peer * is who it claims to be. For example, do not access restricted files on the * peer's behalf until an explicit authentication has succeeded. * * This function can be called after the key exchange phase of the operation * has completed. It imports the shared secret output of the PAKE into the * provided derivation operation. The input step * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key * material in the key derivation operation. * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. * * When this function returns successfully, \p operation becomes inactive. * If this function returns an error status, both \p operation * and \c key_derivation operations enter an error state and must be aborted by * calling psa_pake_abort() and psa_key_derivation_abort() respectively. * * \param[in,out] operation Active PAKE operation. * \param[out] output A key derivation operation that is ready * for an input step of type * #PSA_KEY_DERIVATION_INPUT_SECRET. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the * algorithm in the \p output key derivation operation. * \retval #PSA_ERROR_NOT_SUPPORTED * Input from a PAKE is not supported by the algorithm in the \p output * key derivation operation. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The PAKE operation state is not valid (it must be active, but beyond * that validity is specific to the algorithm), or * the library has not been previously initialized by psa_crypto_init(), * or the state of \p output is not valid for * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the * step is out of order or the application has done this step already * and it may not be repeated. * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, psa_key_derivation_operation_t *output); /** Abort a PAKE operation. * * Aborting an operation frees all associated resources except for the \c * operation structure itself. Once aborted, the operation object can be reused * for another operation by calling psa_pake_setup() again. * * This function may be called at any time after the operation * object has been initialized as described in #psa_pake_operation_t. * * In particular, calling psa_pake_abort() after the operation has been * terminated by a call to psa_pake_abort() or psa_pake_get_implicit_key() * is safe and has no effect. * * \param[in,out] operation The operation to abort. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_abort(psa_pake_operation_t *operation); /**@}*/ /** A sufficient output buffer size for psa_pake_output(). * * If the size of the output buffer is at least this large, it is guaranteed * that psa_pake_output() will not fail due to an insufficient output buffer * size. The actual size of the output might be smaller in any given call. * * See also #PSA_PAKE_OUTPUT_MAX_SIZE * * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param primitive A primitive of type ::psa_pake_primitive_t that is * compatible with algorithm \p alg. * \param output_step A value of type ::psa_pake_step_t that is valid for the * algorithm \p alg. * \return A sufficient output buffer size for the specified * PAKE algorithm, primitive, and output step. If the * PAKE algorithm, primitive, or output step is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) \ (alg == PSA_ALG_JPAKE && \ primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \ PSA_ECC_FAMILY_SECP_R1, 256) ? \ ( \ output_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \ output_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \ 32 \ ) : \ 0) /** A sufficient input buffer size for psa_pake_input(). * * The value returned by this macro is guaranteed to be large enough for any * valid input to psa_pake_input() in an operation with the specified * parameters. * * See also #PSA_PAKE_INPUT_MAX_SIZE * * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param primitive A primitive of type ::psa_pake_primitive_t that is * compatible with algorithm \p alg. * \param input_step A value of type ::psa_pake_step_t that is valid for the * algorithm \p alg. * \return A sufficient input buffer size for the specified * input, cipher suite and algorithm. If the cipher suite, * the input type or PAKE algorithm is not recognized, or * the parameters are incompatible, return 0. */ #define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) \ (alg == PSA_ALG_JPAKE && \ primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \ PSA_ECC_FAMILY_SECP_R1, 256) ? \ ( \ input_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \ input_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \ 32 \ ) : \ 0) /** Output buffer size for psa_pake_output() for any of the supported PAKE * algorithm and primitive suites and output step. * * This macro must expand to a compile-time constant integer. * * The value of this macro must be at least as large as the largest value * returned by PSA_PAKE_OUTPUT_SIZE() * * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p primitive, \p output_step). */ #define PSA_PAKE_OUTPUT_MAX_SIZE 65 /** Input buffer size for psa_pake_input() for any of the supported PAKE * algorithm and primitive suites and input step. * * This macro must expand to a compile-time constant integer. * * The value of this macro must be at least as large as the largest value * returned by PSA_PAKE_INPUT_SIZE() * * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p primitive, \p output_step). */ #define PSA_PAKE_INPUT_MAX_SIZE 65 /** Returns a suitable initializer for a PAKE cipher suite object of type * psa_pake_cipher_suite_t. */ #define PSA_PAKE_CIPHER_SUITE_INIT { PSA_ALG_NONE, 0, 0, 0, PSA_ALG_NONE } /** Returns a suitable initializer for a PAKE operation object of type * psa_pake_operation_t. */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_PAKE_OPERATION_INIT { 0 } #else #define PSA_PAKE_OPERATION_INIT { 0, PSA_ALG_NONE, 0, PSA_PAKE_OPERATION_STAGE_SETUP, \ { 0 }, { { 0 } } } #endif struct psa_pake_cipher_suite_s { psa_algorithm_t algorithm; psa_pake_primitive_type_t type; psa_pake_family_t family; uint16_t bits; psa_algorithm_t hash; }; static inline psa_algorithm_t psa_pake_cs_get_algorithm( const psa_pake_cipher_suite_t *cipher_suite) { return cipher_suite->algorithm; } static inline void psa_pake_cs_set_algorithm( psa_pake_cipher_suite_t *cipher_suite, psa_algorithm_t algorithm) { if (!PSA_ALG_IS_PAKE(algorithm)) { cipher_suite->algorithm = 0; } else { cipher_suite->algorithm = algorithm; } } static inline psa_pake_primitive_t psa_pake_cs_get_primitive( const psa_pake_cipher_suite_t *cipher_suite) { return PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family, cipher_suite->bits); } static inline void psa_pake_cs_set_primitive( psa_pake_cipher_suite_t *cipher_suite, psa_pake_primitive_t primitive) { cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24); cipher_suite->family = (psa_pake_family_t) (0xFF & (primitive >> 16)); cipher_suite->bits = (uint16_t) (0xFFFF & primitive); } static inline psa_pake_family_t psa_pake_cs_get_family( const psa_pake_cipher_suite_t *cipher_suite) { return cipher_suite->family; } static inline uint16_t psa_pake_cs_get_bits( const psa_pake_cipher_suite_t *cipher_suite) { return cipher_suite->bits; } static inline psa_algorithm_t psa_pake_cs_get_hash( const psa_pake_cipher_suite_t *cipher_suite) { return cipher_suite->hash; } static inline void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite, psa_algorithm_t hash) { if (!PSA_ALG_IS_HASH(hash)) { cipher_suite->hash = 0; } else { cipher_suite->hash = hash; } } struct psa_crypto_driver_pake_inputs_s { uint8_t *MBEDTLS_PRIVATE(password); size_t MBEDTLS_PRIVATE(password_len); uint8_t *MBEDTLS_PRIVATE(user); size_t MBEDTLS_PRIVATE(user_len); uint8_t *MBEDTLS_PRIVATE(peer); size_t MBEDTLS_PRIVATE(peer_len); psa_key_attributes_t MBEDTLS_PRIVATE(attributes); psa_pake_cipher_suite_t MBEDTLS_PRIVATE(cipher_suite); }; typedef enum psa_crypto_driver_pake_step { PSA_JPAKE_STEP_INVALID = 0, /* Invalid step */ PSA_JPAKE_X1_STEP_KEY_SHARE = 1, /* Round 1: input/output key share (for ephemeral private key X1).*/ PSA_JPAKE_X1_STEP_ZK_PUBLIC = 2, /* Round 1: input/output Schnorr NIZKP public key for the X1 key */ PSA_JPAKE_X1_STEP_ZK_PROOF = 3, /* Round 1: input/output Schnorr NIZKP proof for the X1 key */ PSA_JPAKE_X2_STEP_KEY_SHARE = 4, /* Round 1: input/output key share (for ephemeral private key X2).*/ PSA_JPAKE_X2_STEP_ZK_PUBLIC = 5, /* Round 1: input/output Schnorr NIZKP public key for the X2 key */ PSA_JPAKE_X2_STEP_ZK_PROOF = 6, /* Round 1: input/output Schnorr NIZKP proof for the X2 key */ PSA_JPAKE_X2S_STEP_KEY_SHARE = 7, /* Round 2: output X2S key (our key) */ PSA_JPAKE_X2S_STEP_ZK_PUBLIC = 8, /* Round 2: output Schnorr NIZKP public key for the X2S key (our key) */ PSA_JPAKE_X2S_STEP_ZK_PROOF = 9, /* Round 2: output Schnorr NIZKP proof for the X2S key (our key) */ PSA_JPAKE_X4S_STEP_KEY_SHARE = 10, /* Round 2: input X4S key (from peer) */ PSA_JPAKE_X4S_STEP_ZK_PUBLIC = 11, /* Round 2: input Schnorr NIZKP public key for the X4S key (from peer) */ PSA_JPAKE_X4S_STEP_ZK_PROOF = 12 /* Round 2: input Schnorr NIZKP proof for the X4S key (from peer) */ } psa_crypto_driver_pake_step_t; typedef enum psa_jpake_round { PSA_JPAKE_FIRST = 0, PSA_JPAKE_SECOND = 1, PSA_JPAKE_FINISHED = 2 } psa_jpake_round_t; typedef enum psa_jpake_io_mode { PSA_JPAKE_INPUT = 0, PSA_JPAKE_OUTPUT = 1 } psa_jpake_io_mode_t; struct psa_jpake_computation_stage_s { /* The J-PAKE round we are currently on */ psa_jpake_round_t MBEDTLS_PRIVATE(round); /* The 'mode' we are currently in (inputting or outputting) */ psa_jpake_io_mode_t MBEDTLS_PRIVATE(io_mode); /* The number of completed inputs so far this round */ uint8_t MBEDTLS_PRIVATE(inputs); /* The number of completed outputs so far this round */ uint8_t MBEDTLS_PRIVATE(outputs); /* The next expected step (KEY_SHARE, ZK_PUBLIC or ZK_PROOF) */ psa_pake_step_t MBEDTLS_PRIVATE(step); }; #define PSA_JPAKE_EXPECTED_INPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \ ((round) == PSA_JPAKE_FIRST ? 2 : 1)) #define PSA_JPAKE_EXPECTED_OUTPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \ ((round) == PSA_JPAKE_FIRST ? 2 : 1)) struct psa_pake_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); /* Algorithm of the PAKE operation */ psa_algorithm_t MBEDTLS_PRIVATE(alg); /* A primitive of type compatible with algorithm */ psa_pake_primitive_t MBEDTLS_PRIVATE(primitive); /* Stage of the PAKE operation: waiting for the setup, collecting inputs * or computing. */ uint8_t MBEDTLS_PRIVATE(stage); /* Holds computation stage of the PAKE algorithms. */ union { uint8_t MBEDTLS_PRIVATE(dummy); #if defined(PSA_WANT_ALG_JPAKE) psa_jpake_computation_stage_t MBEDTLS_PRIVATE(jpake); #endif } MBEDTLS_PRIVATE(computation_stage); union { psa_driver_pake_context_t MBEDTLS_PRIVATE(ctx); psa_crypto_driver_pake_inputs_t MBEDTLS_PRIVATE(inputs); } MBEDTLS_PRIVATE(data); #endif }; static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite_init(void) { const struct psa_pake_cipher_suite_s v = PSA_PAKE_CIPHER_SUITE_INIT; return v; } static inline struct psa_pake_operation_s psa_pake_operation_init(void) { const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT; return v; } #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_EXTRA_H */ webfakes/src/mbedtls/include/psa/crypto_struct.h0000644000176200001440000004476614740737024021616 0ustar liggesusers/** * \file psa/crypto_struct.h * * \brief PSA cryptography module: Mbed TLS structured type implementations * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * This file contains the definitions of some data structures with * implementation-specific definitions. * * In implementations with isolation between the application and the * cryptography module, it is expected that the front-end and the back-end * would have different versions of this file. * *

Design notes about multipart operation structures

* * For multipart operations without driver delegation support, each multipart * operation structure contains a `psa_algorithm_t alg` field which indicates * which specific algorithm the structure is for. When the structure is not in * use, `alg` is 0. Most of the structure consists of a union which is * discriminated by `alg`. * * For multipart operations with driver delegation support, each multipart * operation structure contains an `unsigned int id` field indicating which * driver got assigned to do the operation. When the structure is not in use, * 'id' is 0. The structure contains also a driver context which is the union * of the contexts of all drivers able to handle the type of multipart * operation. * * Note that when `alg` or `id` is 0, the content of other fields is undefined. * In particular, it is not guaranteed that a freshly-initialized structure * is all-zero: we initialize structures to something like `{0, 0}`, which * is only guaranteed to initializes the first member of the union; * GCC and Clang initialize the whole structure to 0 (at the time of writing), * but MSVC and CompCert don't. * * In Mbed TLS, multipart operation structures live independently from * the key. This allows Mbed TLS to free the key objects when destroying * a key slot. If a multipart operation needs to remember the key after * the setup function returns, the operation structure needs to contain a * copy of the key. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_STRUCT_H #define PSA_CRYPTO_STRUCT_H #include "mbedtls/private_access.h" #ifdef __cplusplus extern "C" { #endif /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" /* Include the context definition for the compiled-in drivers for the primitive * algorithms. */ #include "psa/crypto_driver_contexts_primitives.h" struct psa_hash_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_driver_wrappers.h. * ID value zero means the context is not valid or not assigned to * any driver (i.e. the driver context is not active, in use). */ unsigned int MBEDTLS_PRIVATE(id); psa_driver_hash_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_HASH_OPERATION_INIT { 0 } #else #define PSA_HASH_OPERATION_INIT { 0, { 0 } } #endif static inline struct psa_hash_operation_s psa_hash_operation_init(void) { const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; return v; } struct psa_cipher_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); unsigned int MBEDTLS_PRIVATE(iv_required) : 1; unsigned int MBEDTLS_PRIVATE(iv_set) : 1; uint8_t MBEDTLS_PRIVATE(default_iv_length); psa_driver_cipher_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_CIPHER_OPERATION_INIT { 0 } #else #define PSA_CIPHER_OPERATION_INIT { 0, 0, 0, 0, { 0 } } #endif static inline struct psa_cipher_operation_s psa_cipher_operation_init(void) { const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; return v; } /* Include the context definition for the compiled-in drivers for the composite * algorithms. */ #include "psa/crypto_driver_contexts_composites.h" struct psa_mac_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); uint8_t MBEDTLS_PRIVATE(mac_size); unsigned int MBEDTLS_PRIVATE(is_sign) : 1; psa_driver_mac_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_MAC_OPERATION_INIT { 0 } #else #define PSA_MAC_OPERATION_INIT { 0, 0, 0, { 0 } } #endif static inline struct psa_mac_operation_s psa_mac_operation_init(void) { const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; return v; } struct psa_aead_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); psa_algorithm_t MBEDTLS_PRIVATE(alg); psa_key_type_t MBEDTLS_PRIVATE(key_type); size_t MBEDTLS_PRIVATE(ad_remaining); size_t MBEDTLS_PRIVATE(body_remaining); unsigned int MBEDTLS_PRIVATE(nonce_set) : 1; unsigned int MBEDTLS_PRIVATE(lengths_set) : 1; unsigned int MBEDTLS_PRIVATE(ad_started) : 1; unsigned int MBEDTLS_PRIVATE(body_started) : 1; unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; psa_driver_aead_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_AEAD_OPERATION_INIT { 0 } #else #define PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } } #endif static inline struct psa_aead_operation_s psa_aead_operation_init(void) { const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; return v; } /* Include the context definition for the compiled-in drivers for the key * derivation algorithms. */ #include "psa/crypto_driver_contexts_key_derivation.h" struct psa_key_derivation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else psa_algorithm_t MBEDTLS_PRIVATE(alg); unsigned int MBEDTLS_PRIVATE(can_output_key) : 1; size_t MBEDTLS_PRIVATE(capacity); psa_driver_key_derivation_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_KEY_DERIVATION_OPERATION_INIT { 0 } #else /* This only zeroes out the first byte in the union, the rest is unspecified. */ #define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } } #endif static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void) { const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; return v; } struct psa_custom_key_parameters_s { /* Future versions may add other fields in this structure. */ uint32_t flags; }; /** The default production parameters for key generation or key derivation. * * Calling psa_generate_key_custom() or psa_key_derivation_output_key_custom() * with `custom=PSA_CUSTOM_KEY_PARAMETERS_INIT` and `custom_data_length=0` is * equivalent to calling psa_generate_key() or psa_key_derivation_output_key() * respectively. */ #define PSA_CUSTOM_KEY_PARAMETERS_INIT { 0 } #ifndef __cplusplus /* Omitted when compiling in C++, because one of the parameters is a * pointer to a struct with a flexible array member, and that is not * standard C++. * https://github.com/Mbed-TLS/mbedtls/issues/9020 */ /* This is a deprecated variant of `struct psa_custom_key_parameters_s`. * It has exactly the same layout, plus an extra field which is a flexible * array member. Thus a `const struct psa_key_production_parameters_s *` * can be passed to any function that reads a * `const struct psa_custom_key_parameters_s *`. */ struct psa_key_production_parameters_s { uint32_t flags; uint8_t data[]; }; /** The default production parameters for key generation or key derivation. * * Calling psa_generate_key_ext() or psa_key_derivation_output_key_ext() * with `params=PSA_KEY_PRODUCTION_PARAMETERS_INIT` and * `params_data_length == 0` is equivalent to * calling psa_generate_key() or psa_key_derivation_output_key() * respectively. */ #define PSA_KEY_PRODUCTION_PARAMETERS_INIT { 0 } #endif /* !__cplusplus */ struct psa_key_policy_s { psa_key_usage_t MBEDTLS_PRIVATE(usage); psa_algorithm_t MBEDTLS_PRIVATE(alg); psa_algorithm_t MBEDTLS_PRIVATE(alg2); }; typedef struct psa_key_policy_s psa_key_policy_t; #define PSA_KEY_POLICY_INIT { 0, 0, 0 } static inline struct psa_key_policy_s psa_key_policy_init(void) { const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; return v; } /* The type used internally for key sizes. * Public interfaces use size_t, but internally we use a smaller type. */ typedef uint16_t psa_key_bits_t; /* The maximum value of the type used to represent bit-sizes. * This is used to mark an invalid key size. */ #define PSA_KEY_BITS_TOO_LARGE ((psa_key_bits_t) -1) /* The maximum size of a key in bits. * Currently defined as the maximum that can be represented, rounded down * to a whole number of bytes. * This is an uncast value so that it can be used in preprocessor * conditionals. */ #define PSA_MAX_KEY_BITS 0xfff8 struct psa_key_attributes_s { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number); int MBEDTLS_PRIVATE(has_slot_number); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_key_type_t MBEDTLS_PRIVATE(type); psa_key_bits_t MBEDTLS_PRIVATE(bits); psa_key_lifetime_t MBEDTLS_PRIVATE(lifetime); psa_key_policy_t MBEDTLS_PRIVATE(policy); /* This type has a different layout in the client view wrt the * service view of the key id, i.e. in service view usually is * expected to have MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined * thus adding an owner field to the standard psa_key_id_t. For * implementations with client/service separation, this means the * object will be marshalled through a transport channel and * interpreted differently at each side of the transport. Placing * it at the end of structures allows to interpret the structure * at the client without reorganizing the memory layout of the * struct */ mbedtls_svc_key_id_t MBEDTLS_PRIVATE(id); }; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER 0, 0, #else #define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER #endif #define PSA_KEY_ATTRIBUTES_INIT { PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER \ PSA_KEY_TYPE_NONE, 0, \ PSA_KEY_LIFETIME_VOLATILE, \ PSA_KEY_POLICY_INIT, \ MBEDTLS_SVC_KEY_ID_INIT } static inline struct psa_key_attributes_s psa_key_attributes_init(void) { const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; return v; } static inline void psa_set_key_id(psa_key_attributes_t *attributes, mbedtls_svc_key_id_t key) { psa_key_lifetime_t lifetime = attributes->MBEDTLS_PRIVATE(lifetime); attributes->MBEDTLS_PRIVATE(id) = key; if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { attributes->MBEDTLS_PRIVATE(lifetime) = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_LIFETIME_PERSISTENT, PSA_KEY_LIFETIME_GET_LOCATION(lifetime)); } } static inline mbedtls_svc_key_id_t psa_get_key_id( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(id); } #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER static inline void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes, mbedtls_key_owner_id_t owner) { attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(owner) = owner; } #endif static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, psa_key_lifetime_t lifetime) { attributes->MBEDTLS_PRIVATE(lifetime) = lifetime; if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(key_id) = 0; #else attributes->MBEDTLS_PRIVATE(id) = 0; #endif } } static inline psa_key_lifetime_t psa_get_key_lifetime( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(lifetime); } static inline void psa_extend_key_usage_flags(psa_key_usage_t *usage_flags) { if (*usage_flags & PSA_KEY_USAGE_SIGN_HASH) { *usage_flags |= PSA_KEY_USAGE_SIGN_MESSAGE; } if (*usage_flags & PSA_KEY_USAGE_VERIFY_HASH) { *usage_flags |= PSA_KEY_USAGE_VERIFY_MESSAGE; } } static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, psa_key_usage_t usage_flags) { psa_extend_key_usage_flags(&usage_flags); attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) = usage_flags; } static inline psa_key_usage_t psa_get_key_usage_flags( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage); } static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, psa_algorithm_t alg) { attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) = alg; } static inline psa_algorithm_t psa_get_key_algorithm( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg); } static inline void psa_set_key_type(psa_key_attributes_t *attributes, psa_key_type_t type) { attributes->MBEDTLS_PRIVATE(type) = type; } static inline psa_key_type_t psa_get_key_type( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(type); } static inline void psa_set_key_bits(psa_key_attributes_t *attributes, size_t bits) { if (bits > PSA_MAX_KEY_BITS) { attributes->MBEDTLS_PRIVATE(bits) = PSA_KEY_BITS_TOO_LARGE; } else { attributes->MBEDTLS_PRIVATE(bits) = (psa_key_bits_t) bits; } } static inline size_t psa_get_key_bits( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(bits); } /** * \brief The context for PSA interruptible hash signing. */ struct psa_sign_hash_interruptible_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); psa_driver_sign_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx); unsigned int MBEDTLS_PRIVATE(error_occurred) : 1; uint32_t MBEDTLS_PRIVATE(num_ops); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } #else #define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 } #endif static inline struct psa_sign_hash_interruptible_operation_s psa_sign_hash_interruptible_operation_init(void) { const struct psa_sign_hash_interruptible_operation_s v = PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT; return v; } /** * \brief The context for PSA interruptible hash verification. */ struct psa_verify_hash_interruptible_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); psa_driver_verify_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx); unsigned int MBEDTLS_PRIVATE(error_occurred) : 1; uint32_t MBEDTLS_PRIVATE(num_ops); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } #else #define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 } #endif static inline struct psa_verify_hash_interruptible_operation_s psa_verify_hash_interruptible_operation_init(void) { const struct psa_verify_hash_interruptible_operation_s v = PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT; return v; } #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_STRUCT_H */ webfakes/src/mbedtls/include/mbedtls/0000755000176200001440000000000014740737024017347 5ustar liggesuserswebfakes/src/mbedtls/include/mbedtls/ecdh.h0000644000176200001440000004625414740737024020436 0ustar liggesusers/** * \file ecdh.h * * \brief This file contains ECDH definitions and functions. * * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous * key agreement protocol allowing two parties to establish a shared * secret over an insecure channel. Each party must have an * elliptic-curve public–private key pair. * * For more information, see NIST SP 800-56A Rev. 2: Recommendation for * Pair-Wise Key Establishment Schemes Using Discrete Logarithm * Cryptography. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECDH_H #define MBEDTLS_ECDH_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ecp.h" /* * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context * defined in `ecdh.h`). For most applications, the choice of format makes * no difference, since all library functions can work with either format, * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. * The new format used when this option is disabled is smaller * (56 bytes on a 32-bit platform). In future versions of the library, it * will support alternative implementations of ECDH operations. * The new format is incompatible with applications that access * context fields directly and with restartable ECP operations. */ #if defined(MBEDTLS_ECP_RESTARTABLE) #define MBEDTLS_ECDH_LEGACY_CONTEXT #else #undef MBEDTLS_ECDH_LEGACY_CONTEXT #endif #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) #undef MBEDTLS_ECDH_LEGACY_CONTEXT #include "everest/everest.h" #endif #ifdef __cplusplus extern "C" { #endif /** * Defines the source of the imported EC key. */ typedef enum { MBEDTLS_ECDH_OURS, /**< Our key. */ MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ } mbedtls_ecdh_side; #if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) /** * Defines the ECDH implementation used. * * Later versions of the library may add new variants, therefore users should * not make any assumptions about them. */ typedef enum { MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) MBEDTLS_ECDH_VARIANT_EVEREST /*!< Everest implementation */ #endif } mbedtls_ecdh_variant; /** * The context used by the default ECDH implementation. * * Later versions might change the structure of this context, therefore users * should not make any assumptions about the structure of * mbedtls_ecdh_context_mbed. */ typedef struct mbedtls_ecdh_context_mbed { mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */ #endif } mbedtls_ecdh_context_mbed; #endif /** * * \warning Performing multiple operations concurrently on the same * ECDSA context is not supported; objects of this type * should not be shared between multiple threads. * \brief The ECDH context structure. */ typedef struct mbedtls_ecdh_context { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ int MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ mbedtls_mpi MBEDTLS_PRIVATE(_d); /*!< The previous \p d. */ #if defined(MBEDTLS_ECP_RESTARTABLE) int MBEDTLS_PRIVATE(restart_enabled); /*!< The flag for restartable mode. */ mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */ #endif /* MBEDTLS_ECP_RESTARTABLE */ #else uint8_t MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages as defined in RFC 4492. */ mbedtls_ecp_group_id MBEDTLS_PRIVATE(grp_id);/*!< The elliptic curve used. */ mbedtls_ecdh_variant MBEDTLS_PRIVATE(var); /*!< The ECDH implementation/structure used. */ union { mbedtls_ecdh_context_mbed MBEDTLS_PRIVATE(mbed_ecdh); #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) mbedtls_ecdh_context_everest MBEDTLS_PRIVATE(everest_ecdh); #endif } MBEDTLS_PRIVATE(ctx); /*!< Implementation-specific context. The context in use is specified by the \c var field. */ #if defined(MBEDTLS_ECP_RESTARTABLE) uint8_t MBEDTLS_PRIVATE(restart_enabled); /*!< The flag for restartable mode. Functions of an alternative implementation not supporting restartable mode must return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error if this flag is set. */ #endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ } mbedtls_ecdh_context; /** * \brief Return the ECP group for provided context. * * \note To access group specific fields, users should use * `mbedtls_ecp_curve_info_from_grp_id` or * `mbedtls_ecp_group_load` on the extracted `group_id`. * * \param ctx The ECDH context to parse. This must not be \c NULL. * * \return The \c mbedtls_ecp_group_id of the context. */ mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx); /** * \brief Check whether a given group can be used for ECDH. * * \param gid The ECP group ID to check. * * \return \c 1 if the group can be used, \c 0 otherwise */ int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid); /** * \brief This function generates an ECDH keypair on an elliptic * curve. * * This function performs the first of two core computations * implemented during the ECDH key exchange. The second core * computation is performed by mbedtls_ecdh_compute_shared(). * * \see ecp.h * * \param grp The ECP group to use. This must be initialized and have * domain parameters loaded, for example through * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). * \param d The destination MPI (private key). * This must be initialized. * \param Q The destination point (public key). * This must be initialized. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL in case \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return Another \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function computes the shared secret. * * This function performs the second of two core computations * implemented during the ECDH key exchange. The first core * computation is performed by mbedtls_ecdh_gen_public(). * * \see ecp.h * * \note If \p f_rng is not NULL, it is used to implement * countermeasures against side-channel attacks. * For more information, see mbedtls_ecp_mul(). * * \param grp The ECP group to use. This must be initialized and have * domain parameters loaded, for example through * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). * \param z The destination MPI (shared secret). * This must be initialized. * \param Q The public key from another party. * This must be initialized. * \param d Our secret exponent (private key). * This must be initialized. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng is \c NULL or doesn't need a * context argument. * * \return \c 0 on success. * \return Another \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function initializes an ECDH context. * * \param ctx The ECDH context to initialize. This must not be \c NULL. */ void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx); /** * \brief This function sets up the ECDH context with the information * given. * * This function should be called after mbedtls_ecdh_init() but * before mbedtls_ecdh_make_params(). There is no need to call * this function before mbedtls_ecdh_read_params(). * * This is the first function used by a TLS server for ECDHE * ciphersuites. * * \param ctx The ECDH context to set up. This must be initialized. * \param grp_id The group id of the group to set up the context for. * * \return \c 0 on success. */ int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id); /** * \brief This function frees a context. * * \param ctx The context to free. This may be \c NULL, in which * case this function does nothing. If it is not \c NULL, * it must point to an initialized ECDH context. */ void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx); /** * \brief This function generates an EC key pair and exports its * in the format used in a TLS ServerKeyExchange handshake * message. * * This is the second function used by a TLS server for ECDHE * ciphersuites. (It is called after mbedtls_ecdh_setup().) * * \see ecp.h * * \param ctx The ECDH context to use. This must be initialized * and bound to a group, for example via mbedtls_ecdh_setup(). * \param olen The address at which to store the number of Bytes written. * \param buf The destination buffer. This must be a writable buffer of * length \p blen Bytes. * \param blen The length of the destination buffer \p buf in Bytes. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL in case \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function parses the ECDHE parameters in a * TLS ServerKeyExchange handshake message. * * \note In a TLS handshake, this is the how the client * sets up its ECDHE context from the server's public * ECDHE key material. * * \see ecp.h * * \param ctx The ECDHE context to use. This must be initialized. * \param buf On input, \c *buf must be the start of the input buffer. * On output, \c *buf is updated to point to the end of the * data that has been read. On success, this is the first byte * past the end of the ServerKeyExchange parameters. * On error, this is the point at which an error has been * detected, which is usually not useful except to debug * failures. * \param end The end of the input buffer. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * */ int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx, const unsigned char **buf, const unsigned char *end); /** * \brief This function sets up an ECDH context from an EC key. * * It is used by clients and servers in place of the * ServerKeyExchange for static ECDH, and imports ECDH * parameters from the EC key information of a certificate. * * \see ecp.h * * \param ctx The ECDH context to set up. This must be initialized. * \param key The EC key to use. This must be initialized. * \param side Defines the source of the key. Possible values are: * - #MBEDTLS_ECDH_OURS: The key is ours. * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer. * * \return \c 0 on success. * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. * */ int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side); /** * \brief This function generates a public key and exports it * as a TLS ClientKeyExchange payload. * * This is the second function used by a TLS client for ECDH(E) * ciphersuites. * * \see ecp.h * * \param ctx The ECDH context to use. This must be initialized * and bound to a group, the latter usually by * mbedtls_ecdh_read_params(). * \param olen The address at which to store the number of Bytes written. * This must not be \c NULL. * \param buf The destination buffer. This must be a writable buffer * of length \p blen Bytes. * \param blen The size of the destination buffer \p buf in Bytes. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL in case \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function parses and processes the ECDHE payload of a * TLS ClientKeyExchange message. * * This is the third function used by a TLS server for ECDH(E) * ciphersuites. (It is called after mbedtls_ecdh_setup() and * mbedtls_ecdh_make_params().) * * \see ecp.h * * \param ctx The ECDH context to use. This must be initialized * and bound to a group, for example via mbedtls_ecdh_setup(). * \param buf The pointer to the ClientKeyExchange payload. This must * be a readable buffer of length \p blen Bytes. * \param blen The length of the input buffer \p buf in Bytes. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx, const unsigned char *buf, size_t blen); /** * \brief This function derives and exports the shared secret. * * This is the last function used by both TLS client * and servers. * * \note If \p f_rng is not NULL, it is used to implement * countermeasures against side-channel attacks. * For more information, see mbedtls_ecp_mul(). * * \see ecp.h * \param ctx The ECDH context to use. This must be initialized * and have its own private key generated and the peer's * public key imported. * \param olen The address at which to store the total number of * Bytes written on success. This must not be \c NULL. * \param buf The buffer to write the generated shared key to. This * must be a writable buffer of size \p blen Bytes. * \param blen The length of the destination buffer \p buf in Bytes. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context. This may be \c NULL if \p f_rng * doesn't need a context argument. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief This function enables restartable EC computations for this * context. (Default: disabled.) * * \see \c mbedtls_ecp_set_max_ops() * * \note It is not possible to safely disable restartable * computations once enabled, except by free-ing the context, * which cancels possible in-progress operations. * * \param ctx The ECDH context to use. This must be initialized. */ void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx); #endif /* MBEDTLS_ECP_RESTARTABLE */ #ifdef __cplusplus } #endif #endif /* ecdh.h */ webfakes/src/mbedtls/include/mbedtls/asn1.h0000644000176200001440000006525414740737024020376 0ustar liggesusers/** * \file asn1.h * * \brief Generic ASN.1 parsing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ASN1_H #define MBEDTLS_ASN1_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif /** * \addtogroup asn1_module * \{ */ /** * \name ASN1 Error codes * These error codes are combined with other error codes for * higher error granularity. * e.g. X.509 and PKCS #7 error codes * ASN1 is a standard to specify data structures. * \{ */ /** Out of data when parsing an ASN1 data structure. */ #define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /** ASN1 tag was of an unexpected value. */ #define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /** Error when trying to determine the length or invalid length. */ #define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /** Actual length differs from expected length. */ #define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /** Data is invalid. */ #define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /** Memory allocation failed */ #define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /** Buffer too small when writing ASN.1 data structure. */ #define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /** \} name ASN1 Error codes */ /** * \name DER constants * These constants comply with the DER encoded ASN.1 type tags. * DER encoding uses hexadecimal representation. * An example DER sequence is:\n * - 0x02 -- tag indicating INTEGER * - 0x01 -- length in octets * - 0x05 -- value * Such sequences are typically read into \c ::mbedtls_x509_buf. * \{ */ #define MBEDTLS_ASN1_BOOLEAN 0x01 #define MBEDTLS_ASN1_INTEGER 0x02 #define MBEDTLS_ASN1_BIT_STRING 0x03 #define MBEDTLS_ASN1_OCTET_STRING 0x04 #define MBEDTLS_ASN1_NULL 0x05 #define MBEDTLS_ASN1_OID 0x06 #define MBEDTLS_ASN1_ENUMERATED 0x0A #define MBEDTLS_ASN1_UTF8_STRING 0x0C #define MBEDTLS_ASN1_SEQUENCE 0x10 #define MBEDTLS_ASN1_SET 0x11 #define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 #define MBEDTLS_ASN1_T61_STRING 0x14 #define MBEDTLS_ASN1_IA5_STRING 0x16 #define MBEDTLS_ASN1_UTC_TIME 0x17 #define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 #define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C #define MBEDTLS_ASN1_BMP_STRING 0x1E #define MBEDTLS_ASN1_PRIMITIVE 0x00 #define MBEDTLS_ASN1_CONSTRUCTED 0x20 #define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 /* Slightly smaller way to check if tag is a string tag * compared to canonical implementation. */ #define MBEDTLS_ASN1_IS_STRING_TAG(tag) \ ((unsigned int) (tag) < 32u && ( \ ((1u << (tag)) & ((1u << MBEDTLS_ASN1_BMP_STRING) | \ (1u << MBEDTLS_ASN1_UTF8_STRING) | \ (1u << MBEDTLS_ASN1_T61_STRING) | \ (1u << MBEDTLS_ASN1_IA5_STRING) | \ (1u << MBEDTLS_ASN1_UNIVERSAL_STRING) | \ (1u << MBEDTLS_ASN1_PRINTABLE_STRING))) != 0)) /* * Bit masks for each of the components of an ASN.1 tag as specified in * ITU X.690 (08/2015), section 8.1 "General rules for encoding", * paragraph 8.1.2.2: * * Bit 8 7 6 5 1 * +-------+-----+------------+ * | Class | P/C | Tag number | * +-------+-----+------------+ */ #define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 #define MBEDTLS_ASN1_TAG_PC_MASK 0x20 #define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F /** \} name DER constants */ /** Returns the size of the binary string, without the trailing \\0 */ #define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) /** * Compares an mbedtls_asn1_buf structure to a reference OID. * * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a * 'unsigned char *oid' here! */ #define MBEDTLS_OID_CMP(oid_str, oid_buf) \ ((MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len) || \ memcmp((oid_str), (oid_buf)->p, (oid_buf)->len) != 0) #define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \ ((MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len)) || \ memcmp((oid_str), (oid_buf), (oid_buf_len)) != 0) #ifdef __cplusplus extern "C" { #endif /** * \name Functions to parse ASN.1 data structures * \{ */ /** * Type-length-value structure that allows for ASN1 using DER. */ typedef struct mbedtls_asn1_buf { int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ size_t len; /**< ASN1 length, in octets. */ unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ } mbedtls_asn1_buf; /** * Container for ASN1 bit strings. */ typedef struct mbedtls_asn1_bitstring { size_t len; /**< ASN1 length, in octets. */ unsigned char unused_bits; /**< Number of unused bits at the end of the string */ unsigned char *p; /**< Raw ASN1 data for the bit string */ } mbedtls_asn1_bitstring; /** * Container for a sequence of ASN.1 items */ typedef struct mbedtls_asn1_sequence { mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ /** The next entry in the sequence. * * The details of memory management for sequences are not documented and * may change in future versions. Set this field to \p NULL when * initializing a structure, and do not modify it except via Mbed TLS * library functions. */ struct mbedtls_asn1_sequence *next; } mbedtls_asn1_sequence; /** * Container for a sequence or list of 'named' ASN.1 data items */ typedef struct mbedtls_asn1_named_data { mbedtls_asn1_buf oid; /**< The object identifier. */ mbedtls_asn1_buf val; /**< The named value. */ /** The next entry in the sequence. * * The details of memory management for named data sequences are not * documented and may change in future versions. Set this field to \p NULL * when initializing a structure, and do not modify it except via Mbed TLS * library functions. */ struct mbedtls_asn1_named_data *next; /** Merge next item into the current one? * * This field exists for the sake of Mbed TLS's X.509 certificate parsing * code and may change in future versions of the library. */ unsigned char MBEDTLS_PRIVATE(next_merged); } mbedtls_asn1_named_data; #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** * \brief Get the length of an ASN.1 element. * Updates the pointer to immediately behind the length. * * \param p On entry, \c *p points to the first byte of the length, * i.e. immediately after the tag. * On successful completion, \c *p points to the first byte * after the length, i.e. the first byte of the content. * On error, the value of \c *p is undefined. * \param end End of data. * \param len On successful completion, \c *len contains the length * read from the ASN.1 input. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element * would end beyond \p end. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. */ int mbedtls_asn1_get_len(unsigned char **p, const unsigned char *end, size_t *len); /** * \brief Get the tag and length of the element. * Check for the requested tag. * Updates the pointer to immediately behind the tag and length. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * after the length, i.e. the first byte of the content. * On error, the value of \c *p is undefined. * \param end End of data. * \param len On successful completion, \c *len contains the length * read from the ASN.1 input. * \param tag The expected tag. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start * with the requested tag. * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element * would end beyond \p end. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. */ int mbedtls_asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len, int tag); #endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ #if defined(MBEDTLS_ASN1_PARSE_C) /** * \brief Retrieve a boolean ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the ASN.1 element. * On error, the value of \c *p is undefined. * \param end End of data. * \param val On success, the parsed value (\c 0 or \c 1). * * \return 0 if successful. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 BOOLEAN. */ int mbedtls_asn1_get_bool(unsigned char **p, const unsigned char *end, int *val); /** * \brief Retrieve an integer ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the ASN.1 element. * On error, the value of \c *p is undefined. * \param end End of data. * \param val On success, the parsed value. * * \return 0 if successful. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 INTEGER. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does * not fit in an \c int. */ int mbedtls_asn1_get_int(unsigned char **p, const unsigned char *end, int *val); /** * \brief Retrieve an enumerated ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the ASN.1 element. * On error, the value of \c *p is undefined. * \param end End of data. * \param val On success, the parsed value. * * \return 0 if successful. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 ENUMERATED. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does * not fit in an \c int. */ int mbedtls_asn1_get_enum(unsigned char **p, const unsigned char *end, int *val); /** * \brief Retrieve a bitstring ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p is equal to \p end. * On error, the value of \c *p is undefined. * \param end End of data. * \param bs On success, ::mbedtls_asn1_bitstring information about * the parsed value. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains * extra data after a valid BIT STRING. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 BIT STRING. */ int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end, mbedtls_asn1_bitstring *bs); /** * \brief Retrieve a bitstring ASN.1 tag without unused bits and its * value. * Updates the pointer to the beginning of the bit/octet string. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * of the content of the BIT STRING. * On error, the value of \c *p is undefined. * \param end End of data. * \param len On success, \c *len is the length of the content in bytes. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with * a valid BIT STRING with a nonzero number of unused bits. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 BIT STRING. */ int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end, size_t *len); /** * \brief Parses and splits an ASN.1 "SEQUENCE OF ". * Updates the pointer to immediately behind the full sequence tag. * * This function allocates memory for the sequence elements. You can free * the allocated memory with mbedtls_asn1_sequence_free(). * * \note On error, this function may return a partial list in \p cur. * You must set `cur->next = NULL` before calling this function! * Otherwise it is impossible to distinguish a previously non-null * pointer from a pointer to an object allocated by this function. * * \note If the sequence is empty, this function does not modify * \c *cur. If the sequence is valid and non-empty, this * function sets `cur->buf.tag` to \p tag. This allows * callers to distinguish between an empty sequence and * a one-element sequence. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p is equal to \p end. * On error, the value of \c *p is undefined. * \param end End of data. * \param cur A ::mbedtls_asn1_sequence which this function fills. * When this function returns, \c *cur is the head of a linked * list. Each node in this list is allocated with * mbedtls_calloc() apart from \p cur itself, and should * therefore be freed with mbedtls_free(). * The list describes the content of the sequence. * The head of the list (i.e. \c *cur itself) describes the * first element, `*cur->next` describes the second element, etc. * For each element, `buf.tag == tag`, `buf.len` is the length * of the content of the content of the element, and `buf.p` * points to the first byte of the content (i.e. immediately * past the length of the element). * Note that list elements may be allocated even on error. * \param tag Each element of the sequence must have this tag. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains * extra data after a valid SEQUENCE OF \p tag. * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with * an ASN.1 SEQUENCE in which an element has a tag that * is different from \p tag. * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 SEQUENCE. */ int mbedtls_asn1_get_sequence_of(unsigned char **p, const unsigned char *end, mbedtls_asn1_sequence *cur, int tag); /** * \brief Free a heap-allocated linked list presentation of * an ASN.1 sequence, including the first element. * * There are two common ways to manage the memory used for the representation * of a parsed ASN.1 sequence: * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). * When you have finished processing the sequence, * call mbedtls_asn1_sequence_free() on `head`. * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, * for example on the stack. Make sure that `head->next == NULL`. * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). * When you have finished processing the sequence, * call mbedtls_asn1_sequence_free() on `head->cur`, * then free `head` itself in the appropriate manner. * * \param seq The address of the first sequence component. This may * be \c NULL, in which case this functions returns * immediately. */ void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq); /** * \brief Traverse an ASN.1 SEQUENCE container and * call a callback for each entry. * * This function checks that the input is a SEQUENCE of elements that * each have a "must" tag, and calls a callback function on the elements * that have a "may" tag. * * For example, to validate that the input is a SEQUENCE of `tag1` and call * `cb` on each element, use * ``` * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx); * ``` * * To validate that the input is a SEQUENCE of ANY and call `cb` on * each element, use * ``` * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx); * ``` * * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING} * and call `cb` on each element that is an OCTET STRING, use * ``` * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx); * ``` * * The callback is called on the elements with a "may" tag from left to * right. If the input is not a valid SEQUENCE of elements with a "must" tag, * the callback is called on the elements up to the leftmost point where * the input is invalid. * * \warning This function is still experimental and may change * at any time. * * \param p The address of the pointer to the beginning of * the ASN.1 SEQUENCE header. This is updated to * point to the end of the ASN.1 SEQUENCE container * on a successful invocation. * \param end The end of the ASN.1 SEQUENCE container. * \param tag_must_mask A mask to be applied to the ASN.1 tags found within * the SEQUENCE before comparing to \p tag_must_val. * \param tag_must_val The required value of each ASN.1 tag found in the * SEQUENCE, after masking with \p tag_must_mask. * Mismatching tags lead to an error. * For example, a value of \c 0 for both \p tag_must_mask * and \p tag_must_val means that every tag is allowed, * while a value of \c 0xFF for \p tag_must_mask means * that \p tag_must_val is the only allowed tag. * \param tag_may_mask A mask to be applied to the ASN.1 tags found within * the SEQUENCE before comparing to \p tag_may_val. * \param tag_may_val The desired value of each ASN.1 tag found in the * SEQUENCE, after masking with \p tag_may_mask. * Mismatching tags will be silently ignored. * For example, a value of \c 0 for \p tag_may_mask and * \p tag_may_val means that any tag will be considered, * while a value of \c 0xFF for \p tag_may_mask means * that all tags with value different from \p tag_may_val * will be ignored. * \param cb The callback to trigger for each component * in the ASN.1 SEQUENCE that matches \p tag_may_val. * The callback function is called with the following * parameters: * - \p ctx. * - The tag of the current element. * - A pointer to the start of the current element's * content inside the input. * - The length of the content of the current element. * If the callback returns a non-zero value, * the function stops immediately, * forwarding the callback's return value. * \param ctx The context to be passed to the callback \p cb. * * \return \c 0 if successful the entire ASN.1 SEQUENCE * was traversed without parsing or callback errors. * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input * contains extra data after a valid SEQUENCE * of elements with an accepted tag. * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts * with an ASN.1 SEQUENCE in which an element has a tag * that is not accepted. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 SEQUENCE. * \return A non-zero error code forwarded from the callback * \p cb in case the latter returns a non-zero value. */ int mbedtls_asn1_traverse_sequence_of( unsigned char **p, const unsigned char *end, unsigned char tag_must_mask, unsigned char tag_must_val, unsigned char tag_may_mask, unsigned char tag_may_val, int (*cb)(void *ctx, int tag, unsigned char *start, size_t len), void *ctx); #if defined(MBEDTLS_BIGNUM_C) /** * \brief Retrieve an integer ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the ASN.1 element. * On error, the value of \c *p is undefined. * \param end End of data. * \param X On success, the parsed value. * * \return 0 if successful. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 INTEGER. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does * not fit in an \c int. * \return An MPI error code if the parsed value is too large. */ int mbedtls_asn1_get_mpi(unsigned char **p, const unsigned char *end, mbedtls_mpi *X); #endif /* MBEDTLS_BIGNUM_C */ /** * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. * Updates the pointer to immediately behind the full * AlgorithmIdentifier. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the AlgorithmIdentifier element. * On error, the value of \c *p is undefined. * \param end End of data. * \param alg The buffer to receive the OID. * \param params The buffer to receive the parameters. * This is zeroized if there are no parameters. * * \return 0 if successful or a specific ASN.1 or MPI error code. */ int mbedtls_asn1_get_alg(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params); /** * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no * params. * Updates the pointer to immediately behind the full * AlgorithmIdentifier. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the AlgorithmIdentifier element. * On error, the value of \c *p is undefined. * \param end End of data. * \param alg The buffer to receive the OID. * * \return 0 if successful or a specific ASN.1 or MPI error code. */ int mbedtls_asn1_get_alg_null(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg); /** * \brief Find a specific named_data entry in a sequence or list based on * the OID. * * \param list The list to seek through * \param oid The OID to look for * \param len Size of the OID * * \return NULL if not found, or a pointer to the existing entry. */ const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list, const char *oid, size_t len); #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Free a mbedtls_asn1_named_data entry * * \deprecated This function is deprecated and will be removed in a * future version of the library. * Please use mbedtls_asn1_free_named_data_list() * or mbedtls_asn1_free_named_data_list_shallow(). * * \param entry The named data entry to free. * This function calls mbedtls_free() on * `entry->oid.p` and `entry->val.p`. */ void MBEDTLS_DEPRECATED mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *entry); #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Free all entries in a mbedtls_asn1_named_data list. * * \param head Pointer to the head of the list of named data entries to free. * This function calls mbedtls_free() on * `entry->oid.p` and `entry->val.p` and then on `entry` * for each list entry, and sets \c *head to \c NULL. */ void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head); /** * \brief Free all shallow entries in a mbedtls_asn1_named_data list, * but do not free internal pointer targets. * * \param name Head of the list of named data entries to free. * This function calls mbedtls_free() on each list element. */ void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name); /** \} name Functions to parse ASN.1 data structures */ /** \} addtogroup asn1_module */ #endif /* MBEDTLS_ASN1_PARSE_C */ #ifdef __cplusplus } #endif #endif /* asn1.h */ webfakes/src/mbedtls/include/mbedtls/des.h0000644000176200001440000003105414740737024020276 0ustar liggesusers/** * \file des.h * * \brief DES block cipher * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * */ #ifndef MBEDTLS_DES_H #define MBEDTLS_DES_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include #include #define MBEDTLS_DES_ENCRYPT 1 #define MBEDTLS_DES_DECRYPT 0 /** The data input has an invalid length. */ #define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 #define MBEDTLS_DES_KEY_SIZE 8 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_DES_ALT) // Regular implementation // /** * \brief DES context structure * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ typedef struct mbedtls_des_context { uint32_t MBEDTLS_PRIVATE(sk)[32]; /*!< DES subkeys */ } mbedtls_des_context; /** * \brief Triple-DES context structure * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ typedef struct mbedtls_des3_context { uint32_t MBEDTLS_PRIVATE(sk)[96]; /*!< 3DES subkeys */ } mbedtls_des3_context; #else /* MBEDTLS_DES_ALT */ #include "des_alt.h" #endif /* MBEDTLS_DES_ALT */ /** * \brief Initialize DES context * * \param ctx DES context to be initialized * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des_init(mbedtls_des_context *ctx); /** * \brief Clear DES context * * \param ctx DES context to be cleared * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des_free(mbedtls_des_context *ctx); /** * \brief Initialize Triple-DES context * * \param ctx DES3 context to be initialized * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des3_init(mbedtls_des3_context *ctx); /** * \brief Clear Triple-DES context * * \param ctx DES3 context to be cleared * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des3_free(mbedtls_des3_context *ctx); /** * \brief Set key parity on the given key to odd. * * DES keys are 56 bits long, but each byte is padded with * a parity bit to allow verification. * * \param key 8-byte secret key * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief Check that key parity on the given key is odd. * * DES keys are 56 bits long, but each byte is padded with * a parity bit to allow verification. * * \param key 8-byte secret key * * \return 0 is parity was ok, 1 if parity was not correct. * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief Check that key is not a weak or semi-weak DES key * * \param key 8-byte secret key * * \return 0 if no weak key was found, 1 if a weak key was identified. * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief DES key schedule (56-bit, encryption) * * \param ctx DES context to be initialized * \param key 8-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief DES key schedule (56-bit, decryption) * * \param ctx DES context to be initialized * \param key 8-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief Triple-DES key schedule (112-bit, encryption) * * \param ctx 3DES context to be initialized * \param key 16-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); /** * \brief Triple-DES key schedule (112-bit, decryption) * * \param ctx 3DES context to be initialized * \param key 16-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); /** * \brief Triple-DES key schedule (168-bit, encryption) * * \param ctx 3DES context to be initialized * \param key 24-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); /** * \brief Triple-DES key schedule (168-bit, decryption) * * \param ctx 3DES context to be initialized * \param key 24-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); /** * \brief DES-ECB block encryption/decryption * * \param ctx DES context * \param input 64-bit input block * \param output 64-bit output block * * \return 0 if successful * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx, const unsigned char input[8], unsigned char output[8]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief DES-CBC buffer encryption/decryption * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If on the other hand you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * \param ctx DES context * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT * \param length length of the input data * \param iv initialization vector (updated after use) * \param input buffer holding the input data * \param output buffer holding the output data * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, int mode, size_t length, unsigned char iv[8], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ /** * \brief 3DES-ECB block encryption/decryption * * \param ctx 3DES context * \param input 64-bit input block * \param output 64-bit output block * * \return 0 if successful * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx, const unsigned char input[8], unsigned char output[8]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief 3DES-CBC buffer encryption/decryption * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If on the other hand you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * \param ctx 3DES context * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT * \param length length of the input data * \param iv initialization vector (updated after use) * \param input buffer holding the input data * \param output buffer holding the output data * * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, int mode, size_t length, unsigned char iv[8], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ /** * \brief Internal function for key expansion. * (Only exposed to allow overriding it, * see MBEDTLS_DES_SETKEY_ALT) * * \param SK Round keys * \param key Base key * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des_setkey(uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE]); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_des_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* des.h */ webfakes/src/mbedtls/include/mbedtls/config_adjust_x509.h0000644000176200001440000000275514740737024023135 0ustar liggesusers/** * \file mbedtls/config_adjust_x509.h * \brief Adjust X.509 configuration * * This is an internal header. Do not include it directly. * * Automatically enable certain dependencies. Generally, MBEDTLS_xxx * configurations need to be explicitly enabled by the user: enabling * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a * compilation error. However, we do automatically enable certain options * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option * used to identify parts of a module that are used by other module, and we * don't want to make the symbol MBEDTLS_xxx_B part of the public API. * Another case is if A didn't depend on B in earlier versions, and we * want to use B in A but we need to preserve backward compatibility with * configurations that explicitly activate MBEDTLS_xxx_A but not * MBEDTLS_xxx_B. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_X509_H #define MBEDTLS_CONFIG_ADJUST_X509_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ #endif /* MBEDTLS_CONFIG_ADJUST_X509_H */ webfakes/src/mbedtls/include/mbedtls/lms.h0000644000176200001440000005036514740737024020324 0ustar liggesusers/** * \file lms.h * * \brief This file provides an API for the LMS post-quantum-safe stateful-hash public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. * This implementation currently only supports a single parameter set * MBEDTLS_LMS_SHA256_M32_H10 in order to reduce complexity. This is one * of the signature schemes recommended by the IETF draft SUIT standard * for IOT firmware upgrades (RFC9019). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_LMS_H #define MBEDTLS_LMS_H #include #include #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #define MBEDTLS_ERR_LMS_BAD_INPUT_DATA -0x0011 /**< Bad data has been input to an LMS function */ #define MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */ #define MBEDTLS_ERR_LMS_VERIFY_FAILED -0x0015 /**< LMS signature verification failed */ #define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ #define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */ /* Currently only defined for SHA256, 32 is the max hash output size */ #define MBEDTLS_LMOTS_N_HASH_LEN_MAX (32u) #define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX (34u) #define MBEDTLS_LMOTS_N_HASH_LEN(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) #define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u) #define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u) #define MBEDTLS_LMOTS_TYPE_LEN (4u) #define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) #define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type)) #define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \ (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \ MBEDTLS_LMOTS_N_HASH_LEN(type))) #define MBEDTLS_LMS_TYPE_LEN (4) #define MBEDTLS_LMS_H_TREE_HEIGHT(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0) /* The length of a hash output, Currently only implemented for SHA256. * Max is 32 bytes. */ #define MBEDTLS_LMS_M_NODE_BYTES(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0) #define MBEDTLS_LMS_M_NODE_BYTES_MAX 32 #define MBEDTLS_LMS_SIG_LEN(type, otstype) (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ MBEDTLS_LMOTS_SIG_LEN(otstype) + \ MBEDTLS_LMS_TYPE_LEN + \ (MBEDTLS_LMS_H_TREE_HEIGHT(type) * \ MBEDTLS_LMS_M_NODE_BYTES(type))) #define MBEDTLS_LMS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMS_TYPE_LEN + \ MBEDTLS_LMOTS_TYPE_LEN + \ MBEDTLS_LMOTS_I_KEY_ID_LEN + \ MBEDTLS_LMS_M_NODE_BYTES(type)) #ifdef __cplusplus extern "C" { #endif /** The Identifier of the LMS parameter set, as per * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml * We are only implementing a subset of the types, particularly H10, for the sake of simplicity. */ typedef enum { MBEDTLS_LMS_SHA256_M32_H10 = 0x6, } mbedtls_lms_algorithm_type_t; /** The Identifier of the LMOTS parameter set, as per * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml. * We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicity. */ typedef enum { MBEDTLS_LMOTS_SHA256_N32_W8 = 4 } mbedtls_lmots_algorithm_type_t; /** LMOTS parameters structure. * * This contains the metadata associated with an LMOTS key, detailing the * algorithm type, the key ID, and the leaf identifier should be key be part of * a LMS key. */ typedef struct { unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key identifier. */ unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which leaf of the LMS key this is. 0 if the key is not part of an LMS key. */ mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as per IANA. Only SHA256_N32_W8 is currently supported. */ } mbedtls_lmots_parameters_t; /** LMOTS public context structure. * * A LMOTS public key is a hash output, and the applicable parameter set. * * The context must be initialized before it is used. A public key must either * be imported or generated from a private context. * * \dot * digraph lmots_public_t { * UNINITIALIZED -> INIT [label="init"]; * HAVE_PUBLIC_KEY -> INIT [label="free"]; * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; * } * \enddot */ typedef struct { mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. Boolean values only. */ } mbedtls_lmots_public_t; #if defined(MBEDTLS_LMS_PRIVATE) /** LMOTS private context structure. * * A LMOTS private key is one hash output for each of digit of the digest + * checksum, and the applicable parameter set. * * The context must be initialized before it is used. A public key must either * be imported or generated from a private context. * * \dot * digraph lmots_public_t { * UNINITIALIZED -> INIT [label="init"]; * HAVE_PRIVATE_KEY -> INIT [label="free"]; * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; * HAVE_PRIVATE_KEY -> INIT [label="sign"]; * } * \enddot */ typedef struct { mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][ MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lmots_private_t; #endif /* defined(MBEDTLS_LMS_PRIVATE) */ /** LMS parameters structure. * * This contains the metadata associated with an LMS key, detailing the * algorithm type, the type of the underlying OTS algorithm, and the key ID. */ typedef struct { unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key identifier. */ mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as per IANA. Only SHA256_N32_W8 is currently supported. */ mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per IANA. Only SHA256_M32_H10 is currently supported. */ } mbedtls_lms_parameters_t; /** LMS public context structure. * * A LMS public key is the hash output that is the root of the Merkle tree, and * the applicable parameter set * * The context must be initialized before it is used. A public key must either * be imported or generated from a private context. * * \dot * digraph lms_public_t { * UNINITIALIZED -> INIT [label="init"]; * HAVE_PUBLIC_KEY -> INIT [label="free"]; * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; * } * \enddot */ typedef struct { mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES_MAX]; /*!< The public key, in the form of the Merkle tree root node. */ unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. Boolean values only. */ } mbedtls_lms_public_t; #if defined(MBEDTLS_LMS_PRIVATE) /** LMS private context structure. * * A LMS private key is a set of LMOTS private keys, an index to the next usable * key, and the applicable parameter set. * * The context must be initialized before it is used. A public key must either * be imported or generated from a private context. * * \dot * digraph lms_public_t { * UNINITIALIZED -> INIT [label="init"]; * HAVE_PRIVATE_KEY -> INIT [label="free"]; * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; * } * \enddot */ typedef struct { mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not been used. */ mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key for each leaf node in the Merkle tree. NULL when have_private_key is 0 and non-NULL otherwise. is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */ mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to build the Merkle tree. NULL when have_private_key is 0 and non-NULL otherwise. Is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */ unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lms_private_t; #endif /* defined(MBEDTLS_LMS_PRIVATE) */ /** * \brief This function initializes an LMS public context * * \param ctx The uninitialized LMS context that will then be * initialized. */ void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx); /** * \brief This function uninitializes an LMS public context * * \param ctx The initialized LMS context that will then be * uninitialized. */ void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx); /** * \brief This function imports an LMS public key into a * public LMS context. * * \note Before this function is called, the context must * have been initialized. * * \note See IETF RFC8554 for details of the encoding of * this public key. * * \param ctx The initialized LMS context store the key in. * \param key The buffer from which the key will be read. * #MBEDTLS_LMS_PUBLIC_KEY_LEN bytes will be read from * this. * \param key_size The size of the key being imported. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx, const unsigned char *key, size_t key_size); /** * \brief This function exports an LMS public key from a * LMS public context that already contains a public * key. * * \note Before this function is called, the context must * have been initialized and the context must contain * a public key. * * \note See IETF RFC8554 for details of the encoding of * this public key. * * \param ctx The initialized LMS public context that contains * the public key. * \param key The buffer into which the key will be output. Must * be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size. * \param key_size The size of the key buffer. * \param key_len If not NULL, will be written with the size of the * key. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len); /** * \brief This function verifies a LMS signature, using a * LMS context that contains a public key. * * \note Before this function is called, the context must * have been initialized and must contain a public key * (either by import or generation). * * \param ctx The initialized LMS public context from which the * public key will be read. * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buf from which the signature will be read. * #MBEDTLS_LMS_SIG_LEN bytes will be read from * this. * \param sig_size The size of the signature to be verified. * * \return \c 0 on successful verification. * \return A non-zero error code on failure. */ int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size); #if defined(MBEDTLS_LMS_PRIVATE) /** * \brief This function initializes an LMS private context * * \param ctx The uninitialized LMS private context that will * then be initialized. */ void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx); /** * \brief This function uninitializes an LMS private context * * \param ctx The initialized LMS private context that will then * be uninitialized. */ void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx); /** * \brief This function generates an LMS private key, and * stores in into an LMS private context. * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with * handling stateful keys. The API for this function * may change considerably in future versions. * * \note The seed must have at least 256 bits of entropy. * * \param ctx The initialized LMOTS context to generate the key * into. * \param type The LMS parameter set identifier. * \param otstype The LMOTS parameter set identifier. * \param f_rng The RNG function to be used to generate the key ID. * \param p_rng The RNG context to be passed to f_rng * \param seed The seed used to deterministically generate the * key. * \param seed_size The length of the seed. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx, mbedtls_lms_algorithm_type_t type, mbedtls_lmots_algorithm_type_t otstype, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *seed, size_t seed_size); /** * \brief This function calculates an LMS public key from a * LMS context that already contains a private key. * * \note Before this function is called, the context must * have been initialized and the context must contain * a private key. * * \param ctx The initialized LMS public context to calculate the key * from and store it into. * * \param priv_ctx The LMS private context to read the private key * from. This must have been initialized and contain a * private key. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx, const mbedtls_lms_private_t *priv_ctx); /** * \brief This function creates a LMS signature, using a * LMS context that contains unused private keys. * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with * handling stateful keys. The API for this function * may change considerably in future versions. * * \note Before this function is called, the context must * have been initialized and must contain a private * key. * * \note Each of the LMOTS private keys inside a LMS private * key can only be used once. If they are reused, then * attackers may be able to forge signatures with that * key. This is all handled transparently, but it is * important to not perform copy operations on LMS * contexts that contain private key material. * * \param ctx The initialized LMS private context from which the * private key will be read. * \param f_rng The RNG function to be used for signature * generation. * \param p_rng The RNG context to be passed to f_rng * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buf into which the signature will be stored. * Must be at least #MBEDTLS_LMS_SIG_LEN in size. * \param sig_size The size of the buffer the signature will be * written into. * \param sig_len If not NULL, will be written with the size of the * signature. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_sign(mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *msg, unsigned int msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len); #endif /* defined(MBEDTLS_LMS_PRIVATE) */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_LMS_H */ webfakes/src/mbedtls/include/mbedtls/ssl.h0000644000176200001440000102163214740737024020326 0ustar liggesusers/** * \file ssl.h * * \brief SSL/TLS functions. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_H #define MBEDTLS_SSL_H #include "mbedtls/platform_util.h" #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" #include "mbedtls/ecp.h" #include "mbedtls/ssl_ciphersuites.h" #if defined(MBEDTLS_X509_CRT_PARSE_C) #include "mbedtls/x509_crt.h" #include "mbedtls/x509_crl.h" #endif #if defined(MBEDTLS_DHM_C) #include "mbedtls/dhm.h" #endif #include "mbedtls/md.h" #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) #include "mbedtls/ecdh.h" #endif #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #include "psa/crypto.h" /* * SSL Error codes */ /** A cryptographic operation is in progress. Try again later. */ #define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /** The requested feature is not available. */ #define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /** Bad input parameters to function. */ #define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /** Verification of the message MAC failed. */ #define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /** An invalid SSL record was received. */ #define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /** The connection indicated an EOF. */ #define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /** A message could not be parsed due to a syntactic error. */ #define MBEDTLS_ERR_SSL_DECODE_ERROR -0x7300 /* Error space gap */ /** No RNG was provided to the SSL module. */ #define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /** No client certification received from the client, but required by the authentication mode. */ #define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /** Client received an extended server hello containing an unsupported extension */ #define MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION -0x7500 /** No ALPN protocols supported that the client advertises */ #define MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL -0x7580 /** The own private key or pre-shared key is not set, but needed. */ #define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /** No CA Chain is set, but required to operate. */ #define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /** An unexpected message was received from our peer. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /** A fatal alert message was received from our peer. */ #define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /** No server could be identified matching the client's SNI. */ #define MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME -0x7800 /** The peer notified us that the connection is going to be closed. */ #define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /* Error space gap */ /* Error space gap */ /** Processing of the Certificate handshake message failed. */ #define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00 /* Error space gap */ /** A TLS 1.3 NewSessionTicket message has been received. */ #define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET -0x7B00 /** Not possible to read early data */ #define MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA -0x7B80 /** * Early data has been received as part of an on-going handshake. * This error code can be returned only on server side if and only if early * data has been enabled by means of the mbedtls_ssl_conf_early_data() API. * This error code can then be returned by mbedtls_ssl_handshake(), * mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if * early data has been received as part of the handshake sequence they * triggered. To read the early data, call mbedtls_ssl_read_early_data(). */ #define MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA -0x7C00 /** Not possible to write early data */ #define MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA -0x7C80 /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /** Cache entry not found */ #define MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND -0x7E80 /** Memory allocation failed */ #define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /** Hardware acceleration function returned with error */ #define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /** Hardware acceleration function skipped / left alone data */ #define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /** Handshake protocol not within min/max boundaries */ #define MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION -0x6E80 /** The handshake negotiation failed. */ #define MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE -0x6E00 /** Session ticket has expired. */ #define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /** Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ #define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /** Unknown identity received (eg, PSK identity) */ #define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /** Internal error (eg, unexpected failure in lower-level module) */ #define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /** A counter would wrap (eg, too many messages exchanged). */ #define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /** Unexpected message at ServerHello in renegotiation. */ #define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /** DTLS client must retry for hello verification */ #define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /** A buffer is too small to receive or write a message */ #define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /* Error space gap */ /** No data of requested type currently available on underlying transport. */ #define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /** Connection requires a write call. */ #define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /** The operation timed out. */ #define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /** The client initiated a reconnect from the same port. */ #define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /** Record header looks valid but is not expected. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /** The alert message received indicates a non-fatal error. */ #define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /** A field in a message was incorrect or inconsistent with other fields. */ #define MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER -0x6600 /** Internal-only message signaling that further message-processing should be done */ #define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /** The asynchronous operation is not completed yet. */ #define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /** Internal-only message signaling that a message arrived early. */ #define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /** An encrypted DTLS-frame with an unexpected CID was received. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_CID -0x6000 /** An operation failed due to an unexpected version or configuration. */ #define MBEDTLS_ERR_SSL_VERSION_MISMATCH -0x5F00 /** Invalid value in SSL config */ #define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 /* * Constants from RFC 8446 for TLS 1.3 PSK modes * * Those are used in the Pre-Shared Key Exchange Modes extension. * See Section 4.2.9 in RFC 8446. */ #define MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE 0 /* Pure PSK-based exchange */ #define MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE 1 /* PSK+ECDHE-based exchange */ /* * TLS 1.3 NamedGroup values * * From RF 8446 * enum { * // Elliptic Curve Groups (ECDHE) * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), * x25519(0x001D), x448(0x001E), * // Finite Field Groups (DHE) * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), * ffdhe6144(0x0103), ffdhe8192(0x0104), * // Reserved Code Points * ffdhe_private_use(0x01FC..0x01FF), * ecdhe_private_use(0xFE00..0xFEFF), * (0xFFFF) * } NamedGroup; * */ /* Elliptic Curve Groups (ECDHE) */ #define MBEDTLS_SSL_IANA_TLS_GROUP_NONE 0 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 0x0012 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 0x0013 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 0x0014 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 0x0015 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 0x0016 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 0x0017 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 0x0018 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 0x0019 #define MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1 0x001A #define MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1 0x001B #define MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1 0x001C #define MBEDTLS_SSL_IANA_TLS_GROUP_X25519 0x001D #define MBEDTLS_SSL_IANA_TLS_GROUP_X448 0x001E /* Finite Field Groups (DHE) */ #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 0x0100 #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072 0x0101 #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096 0x0102 #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144 0x0103 #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192 0x0104 /* * TLS 1.3 Key Exchange Modes * * Mbed TLS internal identifiers for use with the SSL configuration API * mbedtls_ssl_conf_tls13_key_exchange_modes(). */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK (1u << 0) /*!< Pure-PSK TLS 1.3 key exchange, * encompassing both externally agreed PSKs * as well as resumption PSKs. */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL (1u << 1) /*!< Pure-Ephemeral TLS 1.3 key exchanges, * including for example ECDHE and DHE * key exchanges. */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL (1u << 2) /*!< PSK-Ephemeral TLS 1.3 key exchanges, * using both a PSK and an ephemeral * key exchange. */ /* Convenience macros for sets of key exchanges. */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL \ (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL | \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL) /*!< All TLS 1.3 key exchanges */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL \ (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) /*!< All PSK-based TLS 1.3 key exchanges */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL \ (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL | \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) /*!< All ephemeral TLS 1.3 key exchanges */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE (0) /* * Various constants */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) /* These are the high and low bytes of ProtocolVersion as defined by: * - RFC 5246: ProtocolVersion version = { 3, 3 }; // TLS v1.2 * - RFC 8446: see section 4.2.1 */ #define MBEDTLS_SSL_MAJOR_VERSION_3 3 #define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ #define MBEDTLS_SSL_MINOR_VERSION_4 4 /*!< TLS v1.3 */ #endif /* MBEDTLS_DEPRECATED_REMOVED */ #define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ #define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ #define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ #define MBEDTLS_SSL_MAX_ALPN_NAME_LEN 255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */ #define MBEDTLS_SSL_MAX_ALPN_LIST_LEN 65535 /*!< Maximum size in bytes of list in alpn ext., RFC 7301 */ /* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c * NONE must be zero so that memset()ing structure to zero works */ #define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ #define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ #define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ #define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ #define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ #define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ #define MBEDTLS_SSL_IS_CLIENT 0 #define MBEDTLS_SSL_IS_SERVER 1 #define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 #define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 #define MBEDTLS_SSL_CID_DISABLED 0 #define MBEDTLS_SSL_CID_ENABLED 1 #define MBEDTLS_SSL_ETM_DISABLED 0 #define MBEDTLS_SSL_ETM_ENABLED 1 #define MBEDTLS_SSL_COMPRESS_NULL 0 #define MBEDTLS_SSL_VERIFY_NONE 0 #define MBEDTLS_SSL_VERIFY_OPTIONAL 1 #define MBEDTLS_SSL_VERIFY_REQUIRED 2 #define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ #define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 #define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 #define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 #define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 #define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 #define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 #define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 #define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 #define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 #define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 #define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 #define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 #define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 #define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ #define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 #define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 #define MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED 0 #define MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED 1 #define MBEDTLS_SSL_PRESET_DEFAULT 0 #define MBEDTLS_SSL_PRESET_SUITEB 2 #define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 #define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 #define MBEDTLS_SSL_EARLY_DATA_DISABLED 0 #define MBEDTLS_SSL_EARLY_DATA_ENABLED 1 #define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED 0 #define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED 1 #define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT 1 #define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER 0 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(PSA_WANT_ALG_SHA_384) #define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 48 #elif defined(PSA_WANT_ALG_SHA_256) #define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 32 #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ /* * Default range for DTLS retransmission timer value, in milliseconds. * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. */ #define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 #define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 /* * Whether early data record should be discarded or not and how. * * The client has indicated early data and the server has rejected them. * The server has then to skip past early data by either: * - attempting to deprotect received records using the handshake traffic * key, discarding records which fail deprotection (up to the configured * max_early_data_size). Once a record is deprotected successfully, * it is treated as the start of the client's second flight and the * server proceeds as with an ordinary 1-RTT handshake. * - skipping all records with an external content type of * "application_data" (indicating that they are encrypted), up to the * configured max_early_data_size. This is the expected behavior if the * server has sent an HelloRetryRequest message. The server ignores * application data message before 2nd ClientHello. */ #define MBEDTLS_SSL_EARLY_DATA_NO_DISCARD 0 #define MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD 1 #define MBEDTLS_SSL_EARLY_DATA_DISCARD 2 /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ /* * Maximum fragment length in bytes, * determines the size of each of the two internal I/O buffers. * * Note: the RFC defines the default size of SSL / TLS messages. If you * change the value here, other clients / servers may not be able to * communicate with you anymore. Only change this value if you control * both sides of the connection and have it reduced at both sides, or * if you're using the Max Fragment Length extension and you know all your * peers are using it too! */ #if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) #define MBEDTLS_SSL_IN_CONTENT_LEN 16384 #endif #if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) #define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 #endif /* * Maximum number of heap-allocated bytes for the purpose of * DTLS handshake message reassembly and future message buffering. */ #if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) #define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 #endif /* * Maximum length of CIDs for incoming and outgoing messages. */ #if !defined(MBEDTLS_SSL_CID_IN_LEN_MAX) #define MBEDTLS_SSL_CID_IN_LEN_MAX 32 #endif #if !defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) #define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 #endif #if !defined(MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) #define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16 #endif #if !defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) #define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE 1024 #endif #if !defined(MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) #define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000 #endif #if !defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH) #define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32 #endif #if !defined(MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS) #define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1 #endif /** \} name SECTION: Module settings */ /* * Default to standard CID mode */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) #define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0 #endif /* * Length of the verify data for secure renegotiation */ #define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 /* * Signaling ciphersuite values (SCSV) */ #define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ /* * Supported Signature and Hash algorithms (For TLS 1.2) * RFC 5246 section 7.4.1.4.1 */ #define MBEDTLS_SSL_HASH_NONE 0 #define MBEDTLS_SSL_HASH_MD5 1 #define MBEDTLS_SSL_HASH_SHA1 2 #define MBEDTLS_SSL_HASH_SHA224 3 #define MBEDTLS_SSL_HASH_SHA256 4 #define MBEDTLS_SSL_HASH_SHA384 5 #define MBEDTLS_SSL_HASH_SHA512 6 #define MBEDTLS_SSL_SIG_ANON 0 #define MBEDTLS_SSL_SIG_RSA 1 #define MBEDTLS_SSL_SIG_ECDSA 3 /* * TLS 1.3 signature algorithms * RFC 8446, Section 4.2.3 */ /* RSASSA-PKCS1-v1_5 algorithms */ #define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256 0x0401 #define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384 0x0501 #define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512 0x0601 /* ECDSA algorithms */ #define MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256 0x0403 #define MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384 0x0503 #define MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512 0x0603 /* RSASSA-PSS algorithms with public key OID rsaEncryption */ #define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256 0x0804 #define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384 0x0805 #define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512 0x0806 /* EdDSA algorithms */ #define MBEDTLS_TLS1_3_SIG_ED25519 0x0807 #define MBEDTLS_TLS1_3_SIG_ED448 0x0808 /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */ #define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256 0x0809 #define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384 0x080A #define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512 0x080B /* LEGACY ALGORITHMS */ #define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1 0x0201 #define MBEDTLS_TLS1_3_SIG_ECDSA_SHA1 0x0203 #define MBEDTLS_TLS1_3_SIG_NONE 0x0 /* * Client Certificate Types * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 */ #define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 #define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 /* * Message, alert and handshake types */ #define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 #define MBEDTLS_SSL_MSG_ALERT 21 #define MBEDTLS_SSL_MSG_HANDSHAKE 22 #define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 #define MBEDTLS_SSL_MSG_CID 25 #define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 #define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 #define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ #define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ #define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ #define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ #define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ #define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ #define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ #define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ #define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ #define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ #define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ #define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ #define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ #define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ #define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ #define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ #define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ #define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ #define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ #define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ #define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ #define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ #define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ #define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ #define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ #define MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION 109 /* 0x6d -- new in TLS 1.3 */ #define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ #define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ #define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ #define MBEDTLS_SSL_ALERT_MSG_CERT_REQUIRED 116 /* 0x74 */ #define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ #define MBEDTLS_SSL_HS_HELLO_REQUEST 0 #define MBEDTLS_SSL_HS_CLIENT_HELLO 1 #define MBEDTLS_SSL_HS_SERVER_HELLO 2 #define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 #define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 #define MBEDTLS_SSL_HS_END_OF_EARLY_DATA 5 #define MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS 8 #define MBEDTLS_SSL_HS_CERTIFICATE 11 #define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 #define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 #define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 #define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 #define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 #define MBEDTLS_SSL_HS_FINISHED 20 #define MBEDTLS_SSL_HS_MESSAGE_HASH 254 /* * TLS extensions */ #define MBEDTLS_TLS_EXT_SERVERNAME 0 #define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 #define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 #define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 #define MBEDTLS_TLS_EXT_STATUS_REQUEST 5 /* RFC 6066 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 #define MBEDTLS_TLS_EXT_SUPPORTED_GROUPS 10 /* RFC 8422,7919 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 #define MBEDTLS_TLS_EXT_SIG_ALG 13 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_USE_SRTP 14 #define MBEDTLS_TLS_EXT_HEARTBEAT 15 /* RFC 6520 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_ALPN 16 #define MBEDTLS_TLS_EXT_SCT 18 /* RFC 6962 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_CLI_CERT_TYPE 19 /* RFC 7250 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_SERV_CERT_TYPE 20 /* RFC 7250 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_PADDING 21 /* RFC 7685 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ #define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ #define MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT 28 /* RFC 8449 (implemented for TLS 1.3 only) */ #define MBEDTLS_TLS_EXT_SESSION_TICKET 35 #define MBEDTLS_TLS_EXT_PRE_SHARED_KEY 41 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_EARLY_DATA 42 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS 43 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_COOKIE 44 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES 45 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_CERT_AUTH 47 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_OID_FILTERS 48 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH 49 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_SIG_ALG_CERT 50 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_KEY_SHARE 51 /* RFC 8446 TLS 1.3 */ #if MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 #define MBEDTLS_TLS_EXT_CID 54 /* RFC 9146 DTLS 1.2 CID */ #else #define MBEDTLS_TLS_EXT_CID 254 /* Pre-RFC 9146 DTLS 1.2 CID */ #endif #define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ #define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 /* * Size defines */ #if !defined(MBEDTLS_PSK_MAX_LEN) /* * If the library supports TLS 1.3 tickets and the cipher suite * TLS1-3-AES-256-GCM-SHA384, set the PSK maximum length to 48 instead of 32. * That way, the TLS 1.3 client and server are able to resume sessions where * the cipher suite is TLS1-3-AES-256-GCM-SHA384 (pre-shared keys are 48 * bytes long in that case). */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) && \ defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_PSK_MAX_LEN 48 /* 384 bits */ #else #define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ #endif #endif /* !MBEDTLS_PSK_MAX_LEN */ /* Dummy type used only for its size */ union mbedtls_ssl_premaster_secret { unsigned char dummy; /* Make the union non-empty even with SSL disabled */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ #endif }; #define MBEDTLS_PREMASTER_SIZE sizeof(union mbedtls_ssl_premaster_secret) #define MBEDTLS_TLS1_3_MD_MAX_SIZE PSA_HASH_MAX_SIZE /* Length in number of bytes of the TLS sequence number */ #define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8 #ifdef __cplusplus extern "C" { #endif /* * SSL state machine */ typedef enum { MBEDTLS_SSL_HELLO_REQUEST, MBEDTLS_SSL_CLIENT_HELLO, MBEDTLS_SSL_SERVER_HELLO, MBEDTLS_SSL_SERVER_CERTIFICATE, MBEDTLS_SSL_SERVER_KEY_EXCHANGE, MBEDTLS_SSL_CERTIFICATE_REQUEST, MBEDTLS_SSL_SERVER_HELLO_DONE, MBEDTLS_SSL_CLIENT_CERTIFICATE, MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, MBEDTLS_SSL_CERTIFICATE_VERIFY, MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, MBEDTLS_SSL_CLIENT_FINISHED, MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, MBEDTLS_SSL_SERVER_FINISHED, MBEDTLS_SSL_FLUSH_BUFFERS, MBEDTLS_SSL_HANDSHAKE_WRAPUP, MBEDTLS_SSL_NEW_SESSION_TICKET, MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, MBEDTLS_SSL_HELLO_RETRY_REQUEST, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS, MBEDTLS_SSL_END_OF_EARLY_DATA, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO, MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO, MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST, MBEDTLS_SSL_HANDSHAKE_OVER, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH, } mbedtls_ssl_states; /* * Early data status, client side only. */ #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) typedef enum { /* * See documentation of mbedtls_ssl_get_early_data_status(). */ MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED, MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED, } mbedtls_ssl_early_data_status; #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ /** * \brief Callback type: send data on the network. * * \note That callback may be either blocking or non-blocking. * * \param ctx Context for the send callback (typically a file descriptor) * \param buf Buffer holding the data to send * \param len Length of the data to send * * \return The callback must return the number of bytes sent if any, * or a non-zero error code. * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE * must be returned when the operation would block. * * \note The callback is allowed to send fewer bytes than requested. * It must always return the number of bytes actually sent. */ typedef int mbedtls_ssl_send_t(void *ctx, const unsigned char *buf, size_t len); /** * \brief Callback type: receive data from the network. * * \note That callback may be either blocking or non-blocking. * * \param ctx Context for the receive callback (typically a file * descriptor) * \param buf Buffer to write the received data to * \param len Length of the receive buffer * * \returns If data has been received, the positive number of bytes received. * \returns \c 0 if the connection has been closed. * \returns If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ * must be returned when the operation would block. * \returns Another negative error code on other kinds of failures. * * \note The callback may receive fewer bytes than the length of the * buffer. It must always return the number of bytes actually * received and written to the buffer. */ typedef int mbedtls_ssl_recv_t(void *ctx, unsigned char *buf, size_t len); /** * \brief Callback type: receive data from the network, with timeout * * \note That callback must block until data is received, or the * timeout delay expires, or the operation is interrupted by a * signal. * * \param ctx Context for the receive callback (typically a file descriptor) * \param buf Buffer to write the received data to * \param len Length of the receive buffer * \param timeout Maximum number of milliseconds to wait for data * 0 means no timeout (potentially waiting forever) * * \return The callback must return the number of bytes received, * or a non-zero error code: * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. * * \note The callback may receive fewer bytes than the length of the * buffer. It must always return the number of bytes actually * received and written to the buffer. */ typedef int mbedtls_ssl_recv_timeout_t(void *ctx, unsigned char *buf, size_t len, uint32_t timeout); /** * \brief Callback type: set a pair of timers/delays to watch * * \param ctx Context pointer * \param int_ms Intermediate delay in milliseconds * \param fin_ms Final delay in milliseconds * 0 cancels the current timer. * * \note This callback must at least store the necessary information * for the associated \c mbedtls_ssl_get_timer_t callback to * return correct information. * * \note If using an event-driven style of programming, an event must * be generated when the final delay is passed. The event must * cause a call to \c mbedtls_ssl_handshake() with the proper * SSL context to be scheduled. Care must be taken to ensure * that at most one such call happens at a time. * * \note Only one timer at a time must be running. Calling this * function while a timer is running must cancel it. Cancelled * timers must not generate any event. */ typedef void mbedtls_ssl_set_timer_t(void *ctx, uint32_t int_ms, uint32_t fin_ms); /** * \brief Callback type: get status of timers/delays * * \param ctx Context pointer * * \return This callback must return: * -1 if cancelled (fin_ms == 0), * 0 if none of the delays have passed, * 1 if only the intermediate delay has passed, * 2 if the final delay has passed. */ typedef int mbedtls_ssl_get_timer_t(void *ctx); /* Defined below */ typedef struct mbedtls_ssl_session mbedtls_ssl_session; typedef struct mbedtls_ssl_context mbedtls_ssl_context; typedef struct mbedtls_ssl_config mbedtls_ssl_config; /* Defined in library/ssl_misc.h */ typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; #if defined(MBEDTLS_X509_CRT_PARSE_C) typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK /* 1U << 0 */ #define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL /* 1U << 2 */ #define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA (1U << 3) #define MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK \ (MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION | \ MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION | \ MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA) #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ /** * \brief Callback type: server-side session cache getter * * The session cache is logically a key value store, with * keys being session IDs and values being instances of * mbedtls_ssl_session. * * This callback retrieves an entry in this key-value store. * * \param data The address of the session cache structure to query. * \param session_id The buffer holding the session ID to query. * \param session_id_len The length of \p session_id in Bytes. * \param session The address of the session structure to populate. * It is initialized with mbdtls_ssl_session_init(), * and the callback must always leave it in a state * where it can safely be freed via * mbedtls_ssl_session_free() independent of the * return code of this function. * * \return \c 0 on success * \return A non-zero return value on failure. * */ typedef int mbedtls_ssl_cache_get_t(void *data, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_session *session); /** * \brief Callback type: server-side session cache setter * * The session cache is logically a key value store, with * keys being session IDs and values being instances of * mbedtls_ssl_session. * * This callback sets an entry in this key-value store. * * \param data The address of the session cache structure to modify. * \param session_id The buffer holding the session ID to query. * \param session_id_len The length of \p session_id in Bytes. * \param session The address of the session to be stored in the * session cache. * * \return \c 0 on success * \return A non-zero return value on failure. */ typedef int mbedtls_ssl_cache_set_t(void *data, unsigned char const *session_id, size_t session_id_len, const mbedtls_ssl_session *session); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Callback type: start external signature operation. * * This callback is called during an SSL handshake to start * a signature decryption operation using an * external processor. The parameter \p cert contains * the public key; it is up to the callback function to * determine how to access the associated private key. * * This function typically sends or enqueues a request, and * does not wait for the operation to complete. This allows * the handshake step to be non-blocking. * * The parameters \p ssl and \p cert are guaranteed to remain * valid throughout the handshake. On the other hand, this * function must save the contents of \p hash if the value * is needed for later processing, because the \p hash buffer * is no longer valid after this function returns. * * This function may call mbedtls_ssl_set_async_operation_data() * to store an operation context for later retrieval * by the resume or cancel callback. * * \note For RSA signatures, this function must produce output * that is consistent with PKCS#1 v1.5 in the same way as * mbedtls_rsa_pkcs1_sign(). Before the private key operation, * apply the padding steps described in RFC 8017, section 9.2 * "EMSA-PKCS1-v1_5" as follows. * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5 * encoding, treating \p hash as the DigestInfo to be * padded. In other words, apply EMSA-PKCS1-v1_5 starting * from step 3, with `T = hash` and `tLen = hash_len`. * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5 * encoding, treating \p hash as the hash to be encoded and * padded. In other words, apply EMSA-PKCS1-v1_5 starting * from step 2, with `digestAlgorithm` obtained by calling * mbedtls_oid_get_oid_by_md() on \p md_alg. * * \note For ECDSA signatures, the output format is the DER encoding * `Ecdsa-Sig-Value` defined in * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4). * * \param ssl The SSL connection instance. It should not be * modified other than via * mbedtls_ssl_set_async_operation_data(). * \param cert Certificate containing the public key. * In simple cases, this is one of the pointers passed to * mbedtls_ssl_conf_own_cert() when configuring the SSL * connection. However, if other callbacks are used, this * property may not hold. For example, if an SNI callback * is registered with mbedtls_ssl_conf_sni(), then * this callback determines what certificate is used. * \param md_alg Hash algorithm. * \param hash Buffer containing the hash. This buffer is * no longer valid when the function returns. * \param hash_len Size of the \c hash buffer in bytes. * * \return 0 if the operation was started successfully and the SSL * stack should call the resume callback immediately. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation * was started successfully and the SSL stack should return * immediately without calling the resume callback yet. * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external * processor does not support this key. The SSL stack will * use the private key object instead. * \return Any other error indicates a fatal failure and is * propagated up the call chain. The callback should * use \c MBEDTLS_ERR_PK_xxx error codes, and must not * use \c MBEDTLS_ERR_SSL_xxx error codes except as * directed in the documentation of this callback. */ typedef int mbedtls_ssl_async_sign_t(mbedtls_ssl_context *ssl, mbedtls_x509_crt *cert, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len); /** * \brief Callback type: start external decryption operation. * * This callback is called during an SSL handshake to start * an RSA decryption operation using an * external processor. The parameter \p cert contains * the public key; it is up to the callback function to * determine how to access the associated private key. * * This function typically sends or enqueues a request, and * does not wait for the operation to complete. This allows * the handshake step to be non-blocking. * * The parameters \p ssl and \p cert are guaranteed to remain * valid throughout the handshake. On the other hand, this * function must save the contents of \p input if the value * is needed for later processing, because the \p input buffer * is no longer valid after this function returns. * * This function may call mbedtls_ssl_set_async_operation_data() * to store an operation context for later retrieval * by the resume or cancel callback. * * \warning RSA decryption as used in TLS is subject to a potential * timing side channel attack first discovered by Bleichenbacher * in 1998. This attack can be remotely exploitable * in practice. To avoid this attack, you must ensure that * if the callback performs an RSA decryption, the time it * takes to execute and return the result does not depend * on whether the RSA decryption succeeded or reported * invalid padding. * * \param ssl The SSL connection instance. It should not be * modified other than via * mbedtls_ssl_set_async_operation_data(). * \param cert Certificate containing the public key. * In simple cases, this is one of the pointers passed to * mbedtls_ssl_conf_own_cert() when configuring the SSL * connection. However, if other callbacks are used, this * property may not hold. For example, if an SNI callback * is registered with mbedtls_ssl_conf_sni(), then * this callback determines what certificate is used. * \param input Buffer containing the input ciphertext. This buffer * is no longer valid when the function returns. * \param input_len Size of the \p input buffer in bytes. * * \return 0 if the operation was started successfully and the SSL * stack should call the resume callback immediately. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation * was started successfully and the SSL stack should return * immediately without calling the resume callback yet. * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external * processor does not support this key. The SSL stack will * use the private key object instead. * \return Any other error indicates a fatal failure and is * propagated up the call chain. The callback should * use \c MBEDTLS_ERR_PK_xxx error codes, and must not * use \c MBEDTLS_ERR_SSL_xxx error codes except as * directed in the documentation of this callback. */ typedef int mbedtls_ssl_async_decrypt_t(mbedtls_ssl_context *ssl, mbedtls_x509_crt *cert, const unsigned char *input, size_t input_len); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** * \brief Callback type: resume external operation. * * This callback is called during an SSL handshake to resume * an external operation started by the * ::mbedtls_ssl_async_sign_t or * ::mbedtls_ssl_async_decrypt_t callback. * * This function typically checks the status of a pending * request or causes the request queue to make progress, and * does not wait for the operation to complete. This allows * the handshake step to be non-blocking. * * This function may call mbedtls_ssl_get_async_operation_data() * to retrieve an operation context set by the start callback. * It may call mbedtls_ssl_set_async_operation_data() to modify * this context. * * Note that when this function returns a status other than * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any * resources associated with the operation. * * \param ssl The SSL connection instance. It should not be * modified other than via * mbedtls_ssl_set_async_operation_data(). * \param output Buffer containing the output (signature or decrypted * data) on success. * \param output_len On success, number of bytes written to \p output. * \param output_size Size of the \p output buffer in bytes. * * \return 0 if output of the operation is available in the * \p output buffer. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation * is still in progress. Subsequent requests for progress * on the SSL connection will call the resume callback * again. * \return Any other error means that the operation is aborted. * The SSL handshake is aborted. The callback should * use \c MBEDTLS_ERR_PK_xxx error codes, and must not * use \c MBEDTLS_ERR_SSL_xxx error codes except as * directed in the documentation of this callback. */ typedef int mbedtls_ssl_async_resume_t(mbedtls_ssl_context *ssl, unsigned char *output, size_t *output_len, size_t output_size); /** * \brief Callback type: cancel external operation. * * This callback is called if an SSL connection is closed * while an asynchronous operation is in progress. Note that * this callback is not called if the * ::mbedtls_ssl_async_resume_t callback has run and has * returned a value other than * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case * the asynchronous operation has already completed. * * This function may call mbedtls_ssl_get_async_operation_data() * to retrieve an operation context set by the start callback. * * \param ssl The SSL connection instance. It should not be * modified. */ typedef void mbedtls_ssl_async_cancel_t(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) #define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN 48 #if defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 32 #elif defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 48 #elif defined(MBEDTLS_MD_CAN_SHA1) #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 20 #else /* This is already checked in check_config.h, but be sure. */ #error "Bad configuration - need SHA-1, SHA-256 or SHA-512 enabled to compute digest of peer CRT." #endif #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ typedef struct { unsigned char client_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char server_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char resumption_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; } mbedtls_ssl_tls13_application_secrets; #if defined(MBEDTLS_SSL_DTLS_SRTP) #define MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH 255 #define MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH 4 /* * For code readability use a typedef for DTLS-SRTP profiles * * Use_srtp extension protection profiles values as defined in * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml * * Reminder: if this list is expanded mbedtls_ssl_check_srtp_profile_value * must be updated too. */ #define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80 ((uint16_t) 0x0001) #define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32 ((uint16_t) 0x0002) #define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80 ((uint16_t) 0x0005) #define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32 ((uint16_t) 0x0006) /* This one is not iana defined, but for code readability. */ #define MBEDTLS_TLS_SRTP_UNSET ((uint16_t) 0x0000) typedef uint16_t mbedtls_ssl_srtp_profile; typedef struct mbedtls_dtls_srtp_info_t { /*! The SRTP profile that was negotiated. */ mbedtls_ssl_srtp_profile MBEDTLS_PRIVATE(chosen_dtls_srtp_profile); /*! The length of mki_value. */ uint16_t MBEDTLS_PRIVATE(mki_len); /*! The mki_value used, with max size of 256 bytes. */ unsigned char MBEDTLS_PRIVATE(mki_value)[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH]; } mbedtls_dtls_srtp_info; #endif /* MBEDTLS_SSL_DTLS_SRTP */ /** Human-friendly representation of the (D)TLS protocol version. */ typedef enum { MBEDTLS_SSL_VERSION_UNKNOWN, /*!< Context not in use or version not yet negotiated. */ MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303, /*!< (D)TLS 1.2 */ MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304, /*!< (D)TLS 1.3 */ } mbedtls_ssl_protocol_version; /* * This structure is used for storing current session data. * * Note: when changing this definition, we need to check and update: * - in tests/suites/test_suite_ssl.function: * ssl_populate_session() and ssl_serialize_session_save_load() * - in library/ssl_tls.c: * mbedtls_ssl_session_init() and mbedtls_ssl_session_free() * mbedtls_ssl_session_save() and ssl_session_load() * ssl_session_copy() */ struct mbedtls_ssl_session { #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) unsigned char MBEDTLS_PRIVATE(mfl_code); /*!< MaxFragmentLength negotiated by peer */ #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ /*!< RecordSizeLimit received from the peer */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) uint16_t MBEDTLS_PRIVATE(record_size_limit); #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ unsigned char MBEDTLS_PRIVATE(exported); uint8_t MBEDTLS_PRIVATE(endpoint); /*!< 0: client, 1: server */ /** TLS version negotiated in the session. Used if and when renegotiating * or resuming a session instead of the configured minor TLS version. */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t MBEDTLS_PRIVATE(start); /*!< start time of current session */ #endif int MBEDTLS_PRIVATE(ciphersuite); /*!< chosen ciphersuite */ size_t MBEDTLS_PRIVATE(id_len); /*!< session id length */ unsigned char MBEDTLS_PRIVATE(id)[32]; /*!< session identifier */ unsigned char MBEDTLS_PRIVATE(master)[48]; /*!< the master secret */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) mbedtls_x509_crt *MBEDTLS_PRIVATE(peer_cert); /*!< peer X.509 cert chain */ #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /*! The digest of the peer's end-CRT. This must be kept to detect CRT * changes during renegotiation, mitigating the triple handshake attack. */ unsigned char *MBEDTLS_PRIVATE(peer_cert_digest); size_t MBEDTLS_PRIVATE(peer_cert_digest_len); mbedtls_md_type_t MBEDTLS_PRIVATE(peer_cert_digest_type); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ uint32_t MBEDTLS_PRIVATE(verify_result); /*!< verification result */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) unsigned char *MBEDTLS_PRIVATE(ticket); /*!< RFC 5077 session ticket */ size_t MBEDTLS_PRIVATE(ticket_len); /*!< session ticket length */ uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< ticket lifetime hint */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_HAVE_TIME) /*! When a ticket is created by a TLS server as part of an established TLS * session, the ticket creation time may need to be saved for the ticket * module to be able to check the ticket age when the ticket is used. * That's the purpose of this field. * Before creating a new ticket, an Mbed TLS server set this field with * its current time in milliseconds. This time may then be saved in the * session ticket data by the session ticket writing function and * recovered by the ticket parsing function later when the ticket is used. * The ticket module may then use this time to compute the ticket age and * determine if it has expired or not. * The Mbed TLS implementations of the session ticket writing and parsing * functions save and retrieve the ticket creation time as part of the * session ticket data. The session ticket parsing function relies on * the mbedtls_ssl_session_get_ticket_creation_time() API to get the * ticket creation time from the session ticket data. */ mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_creation_time); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) uint32_t MBEDTLS_PRIVATE(ticket_age_add); /*!< Randomly generated value used to obscure the age of the ticket */ uint8_t MBEDTLS_PRIVATE(ticket_flags); /*!< Ticket flags */ uint8_t MBEDTLS_PRIVATE(resumption_key_len); /*!< resumption_key length */ unsigned char MBEDTLS_PRIVATE(resumption_key)[MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN]; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_CLI_C) char *MBEDTLS_PRIVATE(hostname); /*!< host name binded with tickets */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) char *ticket_alpn; /*!< ALPN negotiated in the session during which the ticket was generated. */ #endif #if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C) /*! Time in milliseconds when the last ticket was received. */ mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_reception_time); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_EARLY_DATA) uint32_t MBEDTLS_PRIVATE(max_early_data_size); /*!< maximum amount of early data in tickets */ #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) int MBEDTLS_PRIVATE(encrypt_then_mac); /*!< flag for EtM activation */ #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_application_secrets MBEDTLS_PRIVATE(app_secrets); #endif }; /* * Identifiers for PRFs used in various versions of TLS. */ typedef enum { MBEDTLS_SSL_TLS_PRF_NONE, MBEDTLS_SSL_TLS_PRF_SHA384, MBEDTLS_SSL_TLS_PRF_SHA256, MBEDTLS_SSL_HKDF_EXPAND_SHA384, MBEDTLS_SSL_HKDF_EXPAND_SHA256 } mbedtls_tls_prf_types; typedef enum { MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET = 0, #if defined(MBEDTLS_SSL_PROTO_TLS1_3) MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ } mbedtls_ssl_key_export_type; /** * \brief Callback type: Export key alongside random values for * session identification, and PRF for * implementation of TLS key exporters. * * \param p_expkey Context for the callback. * \param type The type of the key that is being exported. * \param secret The address of the buffer holding the secret * that's being exporterd. * \param secret_len The length of \p secret in bytes. * \param client_random The client random bytes. * \param server_random The server random bytes. * \param tls_prf_type The identifier for the PRF used in the handshake * to which the key belongs. */ typedef void mbedtls_ssl_export_keys_t(void *p_expkey, mbedtls_ssl_key_export_type type, const unsigned char *secret, size_t secret_len, const unsigned char client_random[32], const unsigned char server_random[32], mbedtls_tls_prf_types tls_prf_type); #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Callback type: generic handshake callback * * \note Callbacks may use user_data funcs to set/get app user data. * See \c mbedtls_ssl_get_user_data_p() * \c mbedtls_ssl_get_user_data_n() * \c mbedtls_ssl_conf_get_user_data_p() * \c mbedtls_ssl_conf_get_user_data_n() * * \param ssl \c mbedtls_ssl_context on which the callback is run * * \return The return value of the callback is 0 if successful, * or a specific MBEDTLS_ERR_XXX code, which will cause * the handshake to be aborted. */ typedef int (*mbedtls_ssl_hs_cb_t)(mbedtls_ssl_context *ssl); #endif /* A type for storing user data in a library structure. * * The representation of type may change in future versions of the library. * Only the behaviors guaranteed by documented accessor functions are * guaranteed to remain stable. */ typedef union { uintptr_t n; /* typically a handle to an associated object */ void *p; /* typically a pointer to extra data */ } mbedtls_ssl_user_data_t; /** * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. */ struct mbedtls_ssl_config { /* Group items mostly by size. This helps to reduce memory wasted to * padding. It also helps to keep smaller fields early in the structure, * so that elements tend to be in the 128-element direct access window * on Arm Thumb, which reduces the code size. */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(max_tls_version); /*!< max. TLS version used */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(min_tls_version); /*!< min. TLS version used */ /* * Flags (could be bit-fields to save RAM, but separate bytes make * the code smaller on architectures with an instruction for direct * byte access). */ uint8_t MBEDTLS_PRIVATE(endpoint); /*!< 0: client, 1: server */ uint8_t MBEDTLS_PRIVATE(transport); /*!< 0: stream (TLS), 1: datagram (DTLS) */ uint8_t MBEDTLS_PRIVATE(authmode); /*!< MBEDTLS_SSL_VERIFY_XXX */ /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ uint8_t MBEDTLS_PRIVATE(allow_legacy_renegotiation); /*!< MBEDTLS_LEGACY_XXX */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) uint8_t MBEDTLS_PRIVATE(mfl_code); /*!< desired fragment length indicator (MBEDTLS_SSL_MAX_FRAG_LEN_XXX) */ #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) uint8_t MBEDTLS_PRIVATE(encrypt_then_mac); /*!< negotiate encrypt-then-mac? */ #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) uint8_t MBEDTLS_PRIVATE(extended_ms); /*!< negotiate extended master secret? */ #endif #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) uint8_t MBEDTLS_PRIVATE(anti_replay); /*!< detect and prevent replay? */ #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) uint8_t MBEDTLS_PRIVATE(disable_renegotiation); /*!< disable renegotiation? */ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_CLI_C) /** Encodes two booleans, one stating whether TLS 1.2 session tickets are * enabled or not, the other one whether the handling of TLS 1.3 * NewSessionTicket messages is enabled or not. They are respectively set * by mbedtls_ssl_conf_session_tickets() and * mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(). */ uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_3) uint16_t MBEDTLS_PRIVATE(new_session_tickets_count); /*!< number of NewSessionTicket */ #endif #if defined(MBEDTLS_SSL_SRV_C) uint8_t MBEDTLS_PRIVATE(cert_req_ca_list); /*!< enable sending CA list in Certificate Request messages? */ uint8_t MBEDTLS_PRIVATE(respect_cli_pref); /*!< pick the ciphersuite according to the client's preferences rather than ours? */ #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) uint8_t MBEDTLS_PRIVATE(ignore_unexpected_cid); /*!< Should DTLS record with * unexpected CID * lead to failure? */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_DTLS_SRTP) uint8_t MBEDTLS_PRIVATE(dtls_srtp_mki_support); /* support having mki_value in the use_srtp extension? */ #endif /* * Pointers */ /** Allowed ciphersuites for (D)TLS 1.2 (0-terminated) */ const int *MBEDTLS_PRIVATE(ciphersuite_list); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /** Allowed TLS 1.3 key exchange modes. */ int MBEDTLS_PRIVATE(tls13_kex_modes); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /** Callback for printing debug output */ void(*MBEDTLS_PRIVATE(f_dbg))(void *, int, const char *, int, const char *); void *MBEDTLS_PRIVATE(p_dbg); /*!< context for the debug function */ /** Callback for getting (pseudo-)random numbers */ int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ /** Callback to retrieve a session from the cache */ mbedtls_ssl_cache_get_t *MBEDTLS_PRIVATE(f_get_cache); /** Callback to store a session into the cache */ mbedtls_ssl_cache_set_t *MBEDTLS_PRIVATE(f_set_cache); void *MBEDTLS_PRIVATE(p_cache); /*!< context for cache callbacks */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /** Callback for setting cert according to SNI extension */ int(*MBEDTLS_PRIVATE(f_sni))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_sni); /*!< context for SNI callback */ #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) /** Callback to customize X.509 certificate chain verification */ int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify calllback */ #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_SSL_SRV_C) /** Callback to retrieve PSK key from identity */ int(*MBEDTLS_PRIVATE(f_psk))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_psk); /*!< context for PSK callback */ #endif #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /** Callback to create & write a cookie for ClientHello verification */ int(*MBEDTLS_PRIVATE(f_cookie_write))(void *, unsigned char **, unsigned char *, const unsigned char *, size_t); /** Callback to verify validity of a ClientHello cookie */ int(*MBEDTLS_PRIVATE(f_cookie_check))(void *, const unsigned char *, size_t, const unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_cookie); /*!< context for the cookie callbacks */ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) /** Callback to create & write a session ticket */ int(*MBEDTLS_PRIVATE(f_ticket_write))(void *, const mbedtls_ssl_session *, unsigned char *, const unsigned char *, size_t *, uint32_t *); /** Callback to parse a session ticket into a session structure */ int(*MBEDTLS_PRIVATE(f_ticket_parse))(void *, mbedtls_ssl_session *, unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_ticket); /*!< context for the ticket callbacks */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) size_t MBEDTLS_PRIVATE(cid_len); /*!< The length of CIDs for incoming DTLS records. */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_X509_CRT_PARSE_C) const mbedtls_x509_crt_profile *MBEDTLS_PRIVATE(cert_profile); /*!< verification profile */ mbedtls_ssl_key_cert *MBEDTLS_PRIVATE(key_cert); /*!< own certificate/key pair(s) */ mbedtls_x509_crt *MBEDTLS_PRIVATE(ca_chain); /*!< trusted CAs */ mbedtls_x509_crl *MBEDTLS_PRIVATE(ca_crl); /*!< trusted CAs CRLs */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) mbedtls_x509_crt_ca_cb_t MBEDTLS_PRIVATE(f_ca_cb); void *MBEDTLS_PRIVATE(p_ca_cb); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_ssl_async_sign_t *MBEDTLS_PRIVATE(f_async_sign_start); /*!< start asynchronous signature operation */ mbedtls_ssl_async_decrypt_t *MBEDTLS_PRIVATE(f_async_decrypt_start); /*!< start asynchronous decryption operation */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ mbedtls_ssl_async_resume_t *MBEDTLS_PRIVATE(f_async_resume); /*!< resume asynchronous operation */ mbedtls_ssl_async_cancel_t *MBEDTLS_PRIVATE(f_async_cancel); /*!< cancel asynchronous operation */ void *MBEDTLS_PRIVATE(p_async_config_data); /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) const int *MBEDTLS_PRIVATE(sig_hashes); /*!< allowed signature hashes */ #endif const uint16_t *MBEDTLS_PRIVATE(sig_algs); /*!< allowed signature algorithms */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) const mbedtls_ecp_group_id *MBEDTLS_PRIVATE(curve_list); /*!< allowed curves */ #endif const uint16_t *MBEDTLS_PRIVATE(group_list); /*!< allowed IANA NamedGroups */ #if defined(MBEDTLS_DHM_C) mbedtls_mpi MBEDTLS_PRIVATE(dhm_P); /*!< prime modulus for DHM */ mbedtls_mpi MBEDTLS_PRIVATE(dhm_G); /*!< generator for DHM */ #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psk_opaque); /*!< PSA key slot holding opaque PSK. This field * should only be set via * mbedtls_ssl_conf_psk_opaque(). * If either no PSK or a raw PSK have been * configured, this has value \c 0. */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ unsigned char *MBEDTLS_PRIVATE(psk); /*!< The raw pre-shared key. This field should * only be set via mbedtls_ssl_conf_psk(). * If either no PSK or an opaque PSK * have been configured, this has value NULL. */ size_t MBEDTLS_PRIVATE(psk_len); /*!< The length of the raw pre-shared key. * This field should only be set via * mbedtls_ssl_conf_psk(). * Its value is non-zero if and only if * \c psk is not \c NULL. */ unsigned char *MBEDTLS_PRIVATE(psk_identity); /*!< The PSK identity for PSK negotiation. * This field should only be set via * mbedtls_ssl_conf_psk(). * This is set if and only if either * \c psk or \c psk_opaque are set. */ size_t MBEDTLS_PRIVATE(psk_identity_len);/*!< The length of PSK identity. * This field should only be set via * mbedtls_ssl_conf_psk(). * Its value is non-zero if and only if * \c psk is not \c NULL or \c psk_opaque * is not \c 0. */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_SSL_EARLY_DATA) int MBEDTLS_PRIVATE(early_data_enabled); /*!< Early data enablement: * - MBEDTLS_SSL_EARLY_DATA_DISABLED, * - MBEDTLS_SSL_EARLY_DATA_ENABLED */ #if defined(MBEDTLS_SSL_SRV_C) /* The maximum amount of 0-RTT data. RFC 8446 section 4.6.1 */ uint32_t MBEDTLS_PRIVATE(max_early_data_size); #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_ALPN) const char **MBEDTLS_PRIVATE(alpn_list); /*!< ordered list of protocols */ #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) /*! ordered list of supported srtp profile */ const mbedtls_ssl_srtp_profile *MBEDTLS_PRIVATE(dtls_srtp_profile_list); /*! number of supported profiles */ size_t MBEDTLS_PRIVATE(dtls_srtp_profile_list_len); #endif /* MBEDTLS_SSL_DTLS_SRTP */ /* * Numerical settings (int) */ uint32_t MBEDTLS_PRIVATE(read_timeout); /*!< timeout for mbedtls_ssl_read (ms) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) uint32_t MBEDTLS_PRIVATE(hs_timeout_min); /*!< initial value of the handshake retransmission timeout (ms) */ uint32_t MBEDTLS_PRIVATE(hs_timeout_max); /*!< maximum value of the handshake retransmission timeout (ms) */ #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) int MBEDTLS_PRIVATE(renego_max_records); /*!< grace period for renegotiation */ unsigned char MBEDTLS_PRIVATE(renego_period)[8]; /*!< value of the record counters that triggers renegotiation */ #endif unsigned int MBEDTLS_PRIVATE(badmac_limit); /*!< limit of records with a bad MAC */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) unsigned int MBEDTLS_PRIVATE(dhm_min_bitlen); /*!< min. bit length of the DHM prime */ #endif /** User data pointer or handle. * * The library sets this to \p 0 when creating a context and does not * access it afterwards. */ mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data); #if defined(MBEDTLS_SSL_SRV_C) mbedtls_ssl_hs_cb_t MBEDTLS_PRIVATE(f_cert_cb); /*!< certificate selection callback */ #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) const mbedtls_x509_crt *MBEDTLS_PRIVATE(dn_hints);/*!< acceptable client cert issuers */ #endif }; struct mbedtls_ssl_context { const mbedtls_ssl_config *MBEDTLS_PRIVATE(conf); /*!< configuration information */ /* * Miscellaneous */ int MBEDTLS_PRIVATE(state); /*!< SSL handshake: current state */ #if defined(MBEDTLS_SSL_RENEGOTIATION) int MBEDTLS_PRIVATE(renego_status); /*!< Initial, in progress, pending? */ int MBEDTLS_PRIVATE(renego_records_seen); /*!< Records since renego request, or with DTLS, number of retransmissions of request if renego_max_records is < 0 */ #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** * Maximum TLS version to be negotiated, then negotiated TLS version. * * It is initialized as the configured maximum TLS version to be * negotiated by mbedtls_ssl_setup(). * * When renegotiating or resuming a session, it is overwritten in the * ClientHello writing preparation stage with the previously negotiated * TLS version. * * On client side, it is updated to the TLS version selected by the server * for the handshake when the ServerHello is received. * * On server side, it is updated to the TLS version the server selects for * the handshake when the ClientHello is received. */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) /** * State of the negotiation and transfer of early data. Reset to * MBEDTLS_SSL_EARLY_DATA_STATE_IDLE when the context is reset. */ int MBEDTLS_PRIVATE(early_data_state); #endif unsigned MBEDTLS_PRIVATE(badmac_seen); /*!< records with a bad MAC received */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** Callback to customize X.509 certificate chain verification */ int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify callback */ #endif mbedtls_ssl_send_t *MBEDTLS_PRIVATE(f_send); /*!< Callback for network send */ mbedtls_ssl_recv_t *MBEDTLS_PRIVATE(f_recv); /*!< Callback for network receive */ mbedtls_ssl_recv_timeout_t *MBEDTLS_PRIVATE(f_recv_timeout); /*!< Callback for network receive with timeout */ void *MBEDTLS_PRIVATE(p_bio); /*!< context for I/O operations */ /* * Session layer */ mbedtls_ssl_session *MBEDTLS_PRIVATE(session_in); /*!< current session data (in) */ mbedtls_ssl_session *MBEDTLS_PRIVATE(session_out); /*!< current session data (out) */ mbedtls_ssl_session *MBEDTLS_PRIVATE(session); /*!< negotiated session data */ mbedtls_ssl_session *MBEDTLS_PRIVATE(session_negotiate); /*!< session data in negotiation */ mbedtls_ssl_handshake_params *MBEDTLS_PRIVATE(handshake); /*!< params required only during the handshake process */ /* * Record layer transformations */ mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_in); /*!< current transform params (in) * This is always a reference, * never an owning pointer. */ mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_out); /*!< current transform params (out) * This is always a reference, * never an owning pointer. */ mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform); /*!< negotiated transform params * This pointer owns the transform * it references. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_negotiate); /*!< transform params in negotiation * This pointer owns the transform * it references. */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /*! The application data transform in TLS 1.3. * This pointer owns the transform it references. */ mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_application); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /* * Timers */ void *MBEDTLS_PRIVATE(p_timer); /*!< context for the timer callbacks */ mbedtls_ssl_set_timer_t *MBEDTLS_PRIVATE(f_set_timer); /*!< set timer callback */ mbedtls_ssl_get_timer_t *MBEDTLS_PRIVATE(f_get_timer); /*!< get timer callback */ /* * Record layer (incoming data) */ unsigned char *MBEDTLS_PRIVATE(in_buf); /*!< input buffer */ unsigned char *MBEDTLS_PRIVATE(in_ctr); /*!< 64-bit incoming message counter TLS: maintained by us DTLS: read from peer */ unsigned char *MBEDTLS_PRIVATE(in_hdr); /*!< start of record header */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) unsigned char *MBEDTLS_PRIVATE(in_cid); /*!< The start of the CID; * (the end is marked by in_len). */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ unsigned char *MBEDTLS_PRIVATE(in_len); /*!< two-bytes message length field */ unsigned char *MBEDTLS_PRIVATE(in_iv); /*!< ivlen-byte IV */ unsigned char *MBEDTLS_PRIVATE(in_msg); /*!< message contents (in_iv+ivlen) */ unsigned char *MBEDTLS_PRIVATE(in_offt); /*!< read offset in application data */ int MBEDTLS_PRIVATE(in_msgtype); /*!< record header: message type */ size_t MBEDTLS_PRIVATE(in_msglen); /*!< record header: message length */ size_t MBEDTLS_PRIVATE(in_left); /*!< amount of data read so far */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t MBEDTLS_PRIVATE(in_buf_len); /*!< length of input buffer */ #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) uint16_t MBEDTLS_PRIVATE(in_epoch); /*!< DTLS epoch for incoming records */ size_t MBEDTLS_PRIVATE(next_record_offset); /*!< offset of the next record in datagram (equal to in_left if none) */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) uint64_t MBEDTLS_PRIVATE(in_window_top); /*!< last validated record seq_num */ uint64_t MBEDTLS_PRIVATE(in_window); /*!< bitmask for replay detection */ #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ size_t MBEDTLS_PRIVATE(in_hslen); /*!< current handshake message length, including the handshake header */ int MBEDTLS_PRIVATE(nb_zero); /*!< # of 0-length encrypted messages */ int MBEDTLS_PRIVATE(keep_current_message); /*!< drop or reuse current message on next call to record layer? */ /* The following three variables indicate if and, if yes, * what kind of alert is pending to be sent. */ unsigned char MBEDTLS_PRIVATE(send_alert); /*!< Determines if a fatal alert should be sent. Values: - \c 0 , no alert is to be sent. - \c 1 , alert is to be sent. */ unsigned char MBEDTLS_PRIVATE(alert_type); /*!< Type of alert if send_alert != 0 */ int MBEDTLS_PRIVATE(alert_reason); /*!< The error code to be returned to the user once the fatal alert has been sent. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) uint8_t MBEDTLS_PRIVATE(disable_datagram_packing); /*!< Disable packing multiple records * within a single datagram. */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_EARLY_DATA) #if defined(MBEDTLS_SSL_SRV_C) /* * One of: * MBEDTLS_SSL_EARLY_DATA_NO_DISCARD * MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD * MBEDTLS_SSL_EARLY_DATA_DISCARD */ uint8_t MBEDTLS_PRIVATE(discard_early_data_record); #endif uint32_t MBEDTLS_PRIVATE(total_early_data_size); /*!< Number of received/written early data bytes */ #endif /* MBEDTLS_SSL_EARLY_DATA */ /* * Record layer (outgoing data) */ unsigned char *MBEDTLS_PRIVATE(out_buf); /*!< output buffer */ unsigned char *MBEDTLS_PRIVATE(out_ctr); /*!< 64-bit outgoing message counter */ unsigned char *MBEDTLS_PRIVATE(out_hdr); /*!< start of record header */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) unsigned char *MBEDTLS_PRIVATE(out_cid); /*!< The start of the CID; * (the end is marked by in_len). */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ unsigned char *MBEDTLS_PRIVATE(out_len); /*!< two-bytes message length field */ unsigned char *MBEDTLS_PRIVATE(out_iv); /*!< ivlen-byte IV */ unsigned char *MBEDTLS_PRIVATE(out_msg); /*!< message contents (out_iv+ivlen) */ int MBEDTLS_PRIVATE(out_msgtype); /*!< record header: message type */ size_t MBEDTLS_PRIVATE(out_msglen); /*!< record header: message length */ size_t MBEDTLS_PRIVATE(out_left); /*!< amount of data not yet written */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t MBEDTLS_PRIVATE(out_buf_len); /*!< length of output buffer */ #endif unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Outgoing record sequence number. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) uint16_t MBEDTLS_PRIVATE(mtu); /*!< path mtu, used to fragment outgoing messages */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * User settings */ #if defined(MBEDTLS_X509_CRT_PARSE_C) char *MBEDTLS_PRIVATE(hostname); /*!< expected peer CN for verification (and SNI if available) */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_ALPN) const char *MBEDTLS_PRIVATE(alpn_chosen); /*!< negotiated protocol */ #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) /* * use_srtp extension */ mbedtls_dtls_srtp_info MBEDTLS_PRIVATE(dtls_srtp_info); #endif /* MBEDTLS_SSL_DTLS_SRTP */ /* * Information for DTLS hello verify */ #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) unsigned char *MBEDTLS_PRIVATE(cli_id); /*!< transport-level ID of the client */ size_t MBEDTLS_PRIVATE(cli_id_len); /*!< length of cli_id */ #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ /* * Secure renegotiation */ /* needed to know when to send extension on server */ int MBEDTLS_PRIVATE(secure_renegotiation); /*!< does peer support legacy or secure renegotiation */ #if defined(MBEDTLS_SSL_RENEGOTIATION) size_t MBEDTLS_PRIVATE(verify_data_len); /*!< length of verify data stored */ char MBEDTLS_PRIVATE(own_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ char MBEDTLS_PRIVATE(peer_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* CID configuration to use in subsequent handshakes. */ /*! The next incoming CID, chosen by the user and applying to * all subsequent handshakes. This may be different from the * CID currently used in case the user has re-configured the CID * after an initial handshake. */ unsigned char MBEDTLS_PRIVATE(own_cid)[MBEDTLS_SSL_CID_IN_LEN_MAX]; uint8_t MBEDTLS_PRIVATE(own_cid_len); /*!< The length of \c own_cid. */ uint8_t MBEDTLS_PRIVATE(negotiate_cid); /*!< This indicates whether the CID extension should * be negotiated in the next handshake or not. * Possible values are #MBEDTLS_SSL_CID_ENABLED * and #MBEDTLS_SSL_CID_DISABLED. */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /** Callback to export key block and master secret */ mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys); void *MBEDTLS_PRIVATE(p_export_keys); /*!< context for key export callback */ /** User data pointer or handle. * * The library sets this to \p 0 when creating a context and does not * access it afterwards. * * \warning Serializing and restoring an SSL context with * mbedtls_ssl_context_save() and mbedtls_ssl_context_load() * does not currently restore the user data. */ mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data); }; /** * \brief Return the name of the ciphersuite associated with the * given ID * * \param ciphersuite_id SSL ciphersuite ID * * \return a string containing the ciphersuite name */ const char *mbedtls_ssl_get_ciphersuite_name(const int ciphersuite_id); /** * \brief Return the ID of the ciphersuite associated with the * given name * * \param ciphersuite_name SSL ciphersuite name * * \return the ID with the ciphersuite or 0 if not found */ int mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name); /** * \brief Initialize an SSL context * Just makes the context ready for mbedtls_ssl_setup() or * mbedtls_ssl_free() * * \param ssl SSL context */ void mbedtls_ssl_init(mbedtls_ssl_context *ssl); /** * \brief Set up an SSL context for use * * \note No copy of the configuration context is made, it can be * shared by many mbedtls_ssl_context structures. * * \warning The conf structure will be accessed during the session. * It must not be modified or freed as long as the session * is active. * * \warning This function must be called exactly once per context. * Calling mbedtls_ssl_setup again is not supported, even * if no session is active. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param ssl SSL context * \param conf SSL configuration to use * * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if * memory allocation failed */ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf); /** * \brief Reset an already initialized SSL context for re-use * while retaining application-set variables, function * pointers and data. * * \param ssl SSL context * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED or MBEDTLS_ERR_SSL_HW_ACCEL_FAILED */ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl); /** * \brief Set the current endpoint type * * \param conf SSL configuration * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER */ void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint); /** * \brief Get the current endpoint type * * \param conf SSL configuration * * \return Endpoint type, either MBEDTLS_SSL_IS_CLIENT * or MBEDTLS_SSL_IS_SERVER */ static inline int mbedtls_ssl_conf_get_endpoint(const mbedtls_ssl_config *conf) { return conf->MBEDTLS_PRIVATE(endpoint); } /** * \brief Set the transport type (TLS or DTLS). * Default: TLS * * \note For DTLS, you must either provide a recv callback that * doesn't block, or one that handles timeouts, see * \c mbedtls_ssl_set_bio(). You also need to provide timer * callbacks with \c mbedtls_ssl_set_timer_cb(). * * \param conf SSL configuration * \param transport transport type: * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. */ void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport); /** * \brief Set the certificate verification mode * Default: NONE on server, REQUIRED on client * * \param conf SSL configuration * \param authmode can be: * * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked * (default on server) * (insecure on client) * * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the * handshake continues even if verification failed; * mbedtls_ssl_get_verify_result() can be called after the * handshake is complete. * * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, * handshake is aborted if verification failed. * (default on client) * * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at * the right time(s), which may not be obvious, while REQUIRED always perform * the verification as soon as possible. For example, REQUIRED was protecting * against the "triple handshake" attack even before it was found. */ void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode); #if defined(MBEDTLS_SSL_EARLY_DATA) /** * \brief Set the early data mode * Default: disabled on server and client * * \param conf The SSL configuration to use. * \param early_data_enabled can be: * * MBEDTLS_SSL_EARLY_DATA_DISABLED: * Early data functionality is disabled. This is the default on client and * server. * * MBEDTLS_SSL_EARLY_DATA_ENABLED: * Early data functionality is enabled and may be negotiated in the handshake. * Application using early data functionality needs to be aware that the * security properties for early data (also refered to as 0-RTT data) are * weaker than those for other kinds of TLS data. See the documentation of * mbedtls_ssl_write_early_data() and mbedtls_ssl_read_early_data() for more * information. * When early data functionality is enabled on server and only in that case, * the call to one of the APIs that trigger or resume an handshake sequence, * namely mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), * mbedtls_ssl_read() or mbedtls_ssl_write() may return with the error code * MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA indicating that some early data have * been received. To read the early data, call mbedtls_ssl_read_early_data() * before calling the original function again. */ void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf, int early_data_enabled); #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the maximum amount of 0-RTT data in bytes * Default: #MBEDTLS_SSL_MAX_EARLY_DATA_SIZE * * This function sets the value of the max_early_data_size * field of the early data indication extension included in * the NewSessionTicket messages that the server may send. * * The value defines the maximum amount of 0-RTT data * in bytes that a client will be allowed to send when using * one of the tickets defined by the NewSessionTicket messages. * * \note When resuming a session using a ticket, if the server receives more * early data than allowed for the ticket, it terminates the connection. * The maximum amount of 0-RTT data should thus be large enough * to allow a minimum of early data to be exchanged. * * \param[in] conf The SSL configuration to use. * \param[in] max_early_data_size The maximum amount of 0-RTT data. * * \warning This interface DOES NOT influence/limit the amount of early data * that can be received through previously created and issued tickets, * which clients may have stored. */ void mbedtls_ssl_conf_max_early_data_size( mbedtls_ssl_config *conf, uint32_t max_early_data_size); #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set the verification callback (Optional). * * If set, the provided verify callback is called for each * certificate in the peer's CRT chain, including the trusted * root. For more information, please see the documentation of * \c mbedtls_x509_crt_verify(). * * \note For per context callbacks and contexts, please use * mbedtls_ssl_set_verify() instead. * * \param conf The SSL configuration to use. * \param f_vrfy The verification callback to use during CRT verification. * \param p_vrfy The opaque context to be passed to the callback. */ void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** * \brief Set the random number generator callback * * \param conf SSL configuration * \param f_rng RNG function (mandatory) * \param p_rng RNG parameter */ void mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Set the debug callback * * The callback has the following argument: * void * opaque context for the callback * int debug level * const char * file name * int line number * const char * message * * \param conf SSL configuration * \param f_dbg debug function * \param p_dbg debug parameter */ void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf, void (*f_dbg)(void *, int, const char *, int, const char *), void *p_dbg); /** * \brief Return the SSL configuration structure associated * with the given SSL context. * * \note The pointer returned by this function is guaranteed to * remain valid until the context is freed. * * \param ssl The SSL context to query. * \return Pointer to the SSL configuration associated with \p ssl. */ static inline const mbedtls_ssl_config *mbedtls_ssl_context_get_config( const mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(conf); } /** * \brief Set the underlying BIO callbacks for write, read and * read-with-timeout. * * \param ssl SSL context * \param p_bio parameter (context) shared by BIO callbacks * \param f_send write callback * \param f_recv read callback * \param f_recv_timeout blocking read callback with timeout. * * \note One of f_recv or f_recv_timeout can be NULL, in which case * the other is used. If both are non-NULL, f_recv_timeout is * used and f_recv is ignored (as if it were NULL). * * \note The two most common use cases are: * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL * - blocking I/O, f_recv == NULL, f_recv_timeout != NULL * * \note For DTLS, you need to provide either a non-NULL * f_recv_timeout callback, or a f_recv that doesn't block. * * \note See the documentations of \c mbedtls_ssl_send_t, * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for * the conventions those callbacks must follow. * * \note On some platforms, net_sockets.c provides * \c mbedtls_net_send(), \c mbedtls_net_recv() and * \c mbedtls_net_recv_timeout() that are suitable to be used * here. */ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, void *p_bio, mbedtls_ssl_send_t *f_send, mbedtls_ssl_recv_t *f_recv, mbedtls_ssl_recv_timeout_t *f_recv_timeout); #if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /** * \brief Configure the use of the Connection ID (CID) * extension in the next handshake. * * Reference: RFC 9146 (or draft-ietf-tls-dtls-connection-id-05 * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 * for legacy version) * * The DTLS CID extension allows the reliable association of * DTLS records to DTLS connections across changes in the * underlying transport (changed IP and Port metadata) by * adding explicit connection identifiers (CIDs) to the * headers of encrypted DTLS records. The desired CIDs are * configured by the application layer and are exchanged in * new `ClientHello` / `ServerHello` extensions during the * handshake, where each side indicates the CID it wants the * peer to use when writing encrypted messages. The CIDs are * put to use once records get encrypted: the stack discards * any incoming records that don't include the configured CID * in their header, and adds the peer's requested CID to the * headers of outgoing messages. * * This API enables or disables the use of the CID extension * in the next handshake and sets the value of the CID to * be used for incoming messages. * * \param ssl The SSL context to configure. This must be initialized. * \param enable This value determines whether the CID extension should * be used or not. Possible values are: * - MBEDTLS_SSL_CID_ENABLED to enable the use of the CID. * - MBEDTLS_SSL_CID_DISABLED (default) to disable the use * of the CID. * \param own_cid The address of the readable buffer holding the CID we want * the peer to use when sending encrypted messages to us. * This may be \c NULL if \p own_cid_len is \c 0. * This parameter is unused if \p enable is set to * MBEDTLS_SSL_CID_DISABLED. * \param own_cid_len The length of \p own_cid. * This parameter is unused if \p enable is set to * MBEDTLS_SSL_CID_DISABLED. * * \note The value of \p own_cid_len must match the value of the * \c len parameter passed to mbedtls_ssl_conf_cid() * when configuring the ::mbedtls_ssl_config that \p ssl * is bound to. * * \note This CID configuration applies to subsequent handshakes * performed on the SSL context \p ssl, but does not trigger * one. You still have to call `mbedtls_ssl_handshake()` * (for the initial handshake) or `mbedtls_ssl_renegotiate()` * (for a renegotiation handshake) explicitly after a * successful call to this function to run the handshake. * * \note This call cannot guarantee that the use of the CID * will be successfully negotiated in the next handshake, * because the peer might not support it. Specifically: * - On the Client, enabling the use of the CID through * this call implies that the `ClientHello` in the next * handshake will include the CID extension, thereby * offering the use of the CID to the server. Only if * the `ServerHello` contains the CID extension, too, * the CID extension will actually be put to use. * - On the Server, enabling the use of the CID through * this call implies that the server will look for * the CID extension in a `ClientHello` from the client, * and, if present, reply with a CID extension in its * `ServerHello`. * * \note To check whether the use of the CID was negotiated * after the subsequent handshake has completed, please * use the API mbedtls_ssl_get_peer_cid(). * * \warning If the use of the CID extension is enabled in this call * and the subsequent handshake negotiates its use, Mbed TLS * will silently drop every packet whose CID does not match * the CID configured in \p own_cid. It is the responsibility * of the user to adapt the underlying transport to take care * of CID-based demultiplexing before handing datagrams to * Mbed TLS. * * \return \c 0 on success. In this case, the CID configuration * applies to the next handshake. * \return A negative error code on failure. */ int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl, int enable, unsigned char const *own_cid, size_t own_cid_len); /** * \brief Get information about our request for usage of the CID * extension in the current connection. * * \param ssl The SSL context to query. * \param enabled The address at which to store whether the CID extension * is requested to be used or not. If the CID is * requested, `*enabled` is set to * MBEDTLS_SSL_CID_ENABLED; otherwise, it is set to * MBEDTLS_SSL_CID_DISABLED. * \param own_cid The address of the buffer in which to store our own * CID (if the CID extension is requested). This may be * \c NULL in case the value of our CID isn't needed. If * it is not \c NULL, \p own_cid_len must not be \c NULL. * \param own_cid_len The address at which to store the size of our own CID * (if the CID extension is requested). This is also the * number of Bytes in \p own_cid that have been written. * This may be \c NULL in case the length of our own CID * isn't needed. If it is \c NULL, \p own_cid must be * \c NULL, too. * *\note If we are requesting an empty CID this function sets * `*enabled` to #MBEDTLS_SSL_CID_DISABLED (the rationale * for this is that the resulting outcome is the * same as if the CID extensions wasn't requested). * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl, int *enabled, unsigned char own_cid[MBEDTLS_SSL_CID_IN_LEN_MAX], size_t *own_cid_len); /** * \brief Get information about the use of the CID extension * in the current connection. * * \param ssl The SSL context to query. * \param enabled The address at which to store whether the CID extension * is currently in use or not. If the CID is in use, * `*enabled` is set to MBEDTLS_SSL_CID_ENABLED; * otherwise, it is set to MBEDTLS_SSL_CID_DISABLED. * \param peer_cid The address of the buffer in which to store the CID * chosen by the peer (if the CID extension is used). * This may be \c NULL in case the value of peer CID * isn't needed. If it is not \c NULL, \p peer_cid_len * must not be \c NULL. * \param peer_cid_len The address at which to store the size of the CID * chosen by the peer (if the CID extension is used). * This is also the number of Bytes in \p peer_cid that * have been written. * This may be \c NULL in case the length of the peer CID * isn't needed. If it is \c NULL, \p peer_cid must be * \c NULL, too. * * \note This applies to the state of the CID negotiated in * the last complete handshake. If a handshake is in * progress, this function will attempt to complete * the handshake first. * * \note If CID extensions have been exchanged but both client * and server chose to use an empty CID, this function * sets `*enabled` to #MBEDTLS_SSL_CID_DISABLED * (the rationale for this is that the resulting * communication is the same as if the CID extensions * hadn't been used). * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl, int *enabled, unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], size_t *peer_cid_len); #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /** * \brief Set the Maximum Transport Unit (MTU). * Special value: 0 means unset (no limit). * This represents the maximum size of a datagram payload * handled by the transport layer (usually UDP) as determined * by the network link and stack. In practice, this controls * the maximum size datagram the DTLS layer will pass to the * \c f_send() callback set using \c mbedtls_ssl_set_bio(). * * \note The limit on datagram size is converted to a limit on * record payload by subtracting the current overhead of * encapsulation and encryption/authentication if any. * * \note This can be called at any point during the connection, for * example when a Path Maximum Transfer Unit (PMTU) * estimate becomes available from other sources, * such as lower (or higher) protocol layers. * * \note This setting only controls the size of the packets we send, * and does not restrict the size of the datagrams we're * willing to receive. Client-side, you can request the * server to use smaller records with \c * mbedtls_ssl_conf_max_frag_len(). * * \note If both a MTU and a maximum fragment length have been * configured (or negotiated with the peer), the resulting * lower limit on record payload (see first note) is used. * * \note This can only be used to decrease the maximum size * of datagrams (hence records, see first note) sent. It * cannot be used to increase the maximum size of records over * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN. * * \note Values lower than the current record layer expansion will * result in an error when trying to send data. * * \param ssl SSL context * \param mtu Value of the path MTU in bytes */ void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu); #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set a connection-specific verification callback (optional). * * If set, the provided verify callback is called for each * certificate in the peer's CRT chain, including the trusted * root. For more information, please see the documentation of * \c mbedtls_x509_crt_verify(). * * \note This call is analogous to mbedtls_ssl_conf_verify() but * binds the verification callback and context to an SSL context * as opposed to an SSL configuration. * If mbedtls_ssl_conf_verify() and mbedtls_ssl_set_verify() * are both used, mbedtls_ssl_set_verify() takes precedence. * * \param ssl The SSL context to use. * \param f_vrfy The verification callback to use during CRT verification. * \param p_vrfy The opaque context to be passed to the callback. */ void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** * \brief Set the timeout period for mbedtls_ssl_read() * (Default: no timeout.) * * \param conf SSL configuration context * \param timeout Timeout value in milliseconds. * Use 0 for no timeout (default). * * \note With blocking I/O, this will only work if a non-NULL * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). * With non-blocking I/O, this will only work if timer * callbacks were set with \c mbedtls_ssl_set_timer_cb(). * * \note With non-blocking I/O, you may also skip this function * altogether and handle timeouts at the application layer. */ void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout); /** * \brief Check whether a buffer contains a valid and authentic record * that has not been seen before. (DTLS only). * * This function does not change the user-visible state * of the SSL context. Its sole purpose is to provide * an indication of the legitimacy of an incoming record. * * This can be useful e.g. in distributed server environments * using the DTLS Connection ID feature, in which connections * might need to be passed between service instances on a change * of peer address, but where such disruptive operations should * only happen after the validity of incoming records has been * confirmed. * * \param ssl The SSL context to use. * \param buf The address of the buffer holding the record to be checked. * This must be a read/write buffer of length \p buflen Bytes. * \param buflen The length of \p buf in Bytes. * * \note This routine only checks whether the provided buffer begins * with a valid and authentic record that has not been seen * before, but does not check potential data following the * initial record. In particular, it is possible to pass DTLS * datagrams containing multiple records, in which case only * the first record is checked. * * \note This function modifies the input buffer \p buf. If you need * to preserve the original record, you have to maintain a copy. * * \return \c 0 if the record is valid and authentic and has not been * seen before. * \return MBEDTLS_ERR_SSL_INVALID_MAC if the check completed * successfully but the record was found to be not authentic. * \return MBEDTLS_ERR_SSL_INVALID_RECORD if the check completed * successfully but the record was found to be invalid for * a reason different from authenticity checking. * \return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD if the check completed * successfully but the record was found to be unexpected * in the state of the SSL context, including replayed records. * \return Another negative error code on different kinds of failure. * In this case, the SSL context becomes unusable and needs * to be freed or reset before reuse. */ int mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl, unsigned char *buf, size_t buflen); /** * \brief Set the timer callbacks (Mandatory for DTLS.) * * \param ssl SSL context * \param p_timer parameter (context) shared by timer callbacks * \param f_set_timer set timer callback * \param f_get_timer get timer callback. Must return: * * \note See the documentation of \c mbedtls_ssl_set_timer_t and * \c mbedtls_ssl_get_timer_t for the conventions this pair of * callbacks must follow. * * \note On some platforms, timing.c provides * \c mbedtls_timing_set_delay() and * \c mbedtls_timing_get_delay() that are suitable for using * here, except if using an event-driven style. * * \note See also the "DTLS tutorial" article in our knowledge base. * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/dtls-tutorial */ void mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl, void *p_timer, mbedtls_ssl_set_timer_t *f_set_timer, mbedtls_ssl_get_timer_t *f_get_timer); #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the certificate selection callback (server-side only). * * If set, the callback is always called for each handshake, * after `ClientHello` processing has finished. * * \param conf The SSL configuration to register the callback with. * \param f_cert_cb The callback for selecting server certificate after * `ClientHello` processing has finished. */ static inline void mbedtls_ssl_conf_cert_cb(mbedtls_ssl_config *conf, mbedtls_ssl_hs_cb_t f_cert_cb) { conf->MBEDTLS_PRIVATE(f_cert_cb) = f_cert_cb; } #endif /* MBEDTLS_SSL_SRV_C */ /** * \brief Callback type: generate and write session ticket * * \note This describes what a callback implementation should do. * This callback should generate an encrypted and * authenticated ticket for the session and write it to the * output buffer. Here, ticket means the opaque ticket part * of the NewSessionTicket structure of RFC 5077. * * \param p_ticket Context for the callback * \param session SSL session to be written in the ticket * \param start Start of the output buffer * \param end End of the output buffer * \param tlen On exit, holds the length written * \param lifetime On exit, holds the lifetime of the ticket in seconds * * \return 0 if successful, or * a specific MBEDTLS_ERR_XXX code. */ typedef int mbedtls_ssl_ticket_write_t(void *p_ticket, const mbedtls_ssl_session *session, unsigned char *start, const unsigned char *end, size_t *tlen, uint32_t *lifetime); /** * \brief Callback type: parse and load session ticket * * \note This describes what a callback implementation should do. * This callback should parse a session ticket as generated * by the corresponding mbedtls_ssl_ticket_write_t function, * and, if the ticket is authentic and valid, load the * session. * * \note The implementation is allowed to modify the first len * bytes of the input buffer, eg to use it as a temporary * area for the decrypted ticket contents. * * \param p_ticket Context for the callback * \param session SSL session to be loaded * \param buf Start of the buffer containing the ticket * \param len Length of the ticket. * * \return 0 if successful, or * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or * any other non-zero code for other failures. */ typedef int mbedtls_ssl_ticket_parse_t(void *p_ticket, mbedtls_ssl_session *session, unsigned char *buf, size_t len); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) /** * \brief Configure SSL session ticket callbacks (server only). * (Default: none.) * * \note On server, session tickets are enabled by providing * non-NULL callbacks. * * \note On client, use \c mbedtls_ssl_conf_session_tickets(). * * \param conf SSL configuration context * \param f_ticket_write Callback for writing a ticket * \param f_ticket_parse Callback for parsing a ticket * \param p_ticket Context shared by the two callbacks */ void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf, mbedtls_ssl_ticket_write_t *f_ticket_write, mbedtls_ssl_ticket_parse_t *f_ticket_parse, void *p_ticket); #if defined(MBEDTLS_HAVE_TIME) /** * \brief Get the creation time of a session ticket. * * \note See the documentation of \c ticket_creation_time for information about * the intended usage of this function. * * \param session SSL session * \param ticket_creation_time On exit, holds the ticket creation time in * milliseconds. * * \return 0 on success, * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if an input is not valid. */ static inline int mbedtls_ssl_session_get_ticket_creation_time( mbedtls_ssl_session *session, mbedtls_ms_time_t *ticket_creation_time) { if (session == NULL || ticket_creation_time == NULL || session->MBEDTLS_PRIVATE(endpoint) != MBEDTLS_SSL_IS_SERVER) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } *ticket_creation_time = session->MBEDTLS_PRIVATE(ticket_creation_time); return 0; } #endif /* MBEDTLS_HAVE_TIME */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ /** * \brief Get the session-id buffer. * * \param session SSL session. * * \return The address of the session-id buffer. */ static inline unsigned const char (*mbedtls_ssl_session_get_id(const mbedtls_ssl_session * session))[32] { return &session->MBEDTLS_PRIVATE(id); } /** * \brief Get the size of the session-id. * * \param session SSL session. * * \return size_t size of session-id buffer. */ static inline size_t mbedtls_ssl_session_get_id_len(const mbedtls_ssl_session *session) { return session->MBEDTLS_PRIVATE(id_len); } /** * \brief Get the ciphersuite-id. * * \param session SSL session. * * \return int represetation for ciphersuite. */ static inline int mbedtls_ssl_session_get_ciphersuite_id(const mbedtls_ssl_session *session) { return session->MBEDTLS_PRIVATE(ciphersuite); } /** * \brief Configure a key export callback. * (Default: none.) * * This API can be used for two purposes: * - Debugging: Use this API to e.g. generate an NSSKeylog * file and use it to inspect encrypted traffic in tools * such as Wireshark. * - Application-specific export: Use this API to implement * key exporters, e.g. for EAP-TLS or DTLS-SRTP. * * * \param ssl The SSL context to which the export * callback should be attached. * \param f_export_keys The callback for the key export. * \param p_export_keys The opaque context pointer to be passed to the * callback \p f_export_keys. */ void mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl, mbedtls_ssl_export_keys_t *f_export_keys, void *p_export_keys); /** \brief Set the user data in an SSL configuration to a pointer. * * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_p(). * * \note The library stores \c p without accessing it. It is the responsibility * of the caller to ensure that the pointer remains valid. * * \param conf The SSL configuration context to modify. * \param p The new value of the user data. */ static inline void mbedtls_ssl_conf_set_user_data_p( mbedtls_ssl_config *conf, void *p) { conf->MBEDTLS_PRIVATE(user_data).p = p; } /** \brief Set the user data in an SSL configuration to an integer. * * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_n(). * * \param conf The SSL configuration context to modify. * \param n The new value of the user data. */ static inline void mbedtls_ssl_conf_set_user_data_n( mbedtls_ssl_config *conf, uintptr_t n) { conf->MBEDTLS_PRIVATE(user_data).n = n; } /** \brief Retrieve the user data in an SSL configuration as a pointer. * * This is the value last set with mbedtls_ssl_conf_set_user_data_p(), or * \c NULL if mbedtls_ssl_conf_set_user_data_p() has not previously been * called. The value is undefined if mbedtls_ssl_conf_set_user_data_n() has * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_p(). * * \param conf The SSL configuration context to modify. * \return The current value of the user data. */ static inline void *mbedtls_ssl_conf_get_user_data_p( mbedtls_ssl_config *conf) { return conf->MBEDTLS_PRIVATE(user_data).p; } /** \brief Retrieve the user data in an SSL configuration as an integer. * * This is the value last set with mbedtls_ssl_conf_set_user_data_n(), or * \c 0 if mbedtls_ssl_conf_set_user_data_n() has not previously been * called. The value is undefined if mbedtls_ssl_conf_set_user_data_p() has * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_n(). * * \param conf The SSL configuration context to modify. * \return The current value of the user data. */ static inline uintptr_t mbedtls_ssl_conf_get_user_data_n( mbedtls_ssl_config *conf) { return conf->MBEDTLS_PRIVATE(user_data).n; } /** \brief Set the user data in an SSL context to a pointer. * * You can retrieve this value later with mbedtls_ssl_get_user_data_p(). * * \note The library stores \c p without accessing it. It is the responsibility * of the caller to ensure that the pointer remains valid. * * \param ssl The SSL context to modify. * \param p The new value of the user data. */ static inline void mbedtls_ssl_set_user_data_p( mbedtls_ssl_context *ssl, void *p) { ssl->MBEDTLS_PRIVATE(user_data).p = p; } /** \brief Set the user data in an SSL context to an integer. * * You can retrieve this value later with mbedtls_ssl_get_user_data_n(). * * \param ssl The SSL context to modify. * \param n The new value of the user data. */ static inline void mbedtls_ssl_set_user_data_n( mbedtls_ssl_context *ssl, uintptr_t n) { ssl->MBEDTLS_PRIVATE(user_data).n = n; } /** \brief Retrieve the user data in an SSL context as a pointer. * * This is the value last set with mbedtls_ssl_set_user_data_p(), or * \c NULL if mbedtls_ssl_set_user_data_p() has not previously been * called. The value is undefined if mbedtls_ssl_set_user_data_n() has * been called without a subsequent call to mbedtls_ssl_set_user_data_p(). * * \param ssl The SSL context to modify. * \return The current value of the user data. */ static inline void *mbedtls_ssl_get_user_data_p( mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(user_data).p; } /** \brief Retrieve the user data in an SSL context as an integer. * * This is the value last set with mbedtls_ssl_set_user_data_n(), or * \c 0 if mbedtls_ssl_set_user_data_n() has not previously been * called. The value is undefined if mbedtls_ssl_set_user_data_p() has * been called without a subsequent call to mbedtls_ssl_set_user_data_n(). * * \param ssl The SSL context to modify. * \return The current value of the user data. */ static inline uintptr_t mbedtls_ssl_get_user_data_n( mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(user_data).n; } #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) /** * \brief Configure asynchronous private key operation callbacks. * * \param conf SSL configuration context * \param f_async_sign Callback to start a signature operation. See * the description of ::mbedtls_ssl_async_sign_t * for more information. This may be \c NULL if the * external processor does not support any signature * operation; in this case the private key object * associated with the certificate will be used. * \param f_async_decrypt Callback to start a decryption operation. See * the description of ::mbedtls_ssl_async_decrypt_t * for more information. This may be \c NULL if the * external processor does not support any decryption * operation; in this case the private key object * associated with the certificate will be used. * \param f_async_resume Callback to resume an asynchronous operation. See * the description of ::mbedtls_ssl_async_resume_t * for more information. This may not be \c NULL unless * \p f_async_sign and \p f_async_decrypt are both * \c NULL. * \param f_async_cancel Callback to cancel an asynchronous operation. See * the description of ::mbedtls_ssl_async_cancel_t * for more information. This may be \c NULL if * no cleanup is needed. * \param config_data A pointer to configuration data which can be * retrieved with * mbedtls_ssl_conf_get_async_config_data(). The * library stores this value without dereferencing it. */ void mbedtls_ssl_conf_async_private_cb(mbedtls_ssl_config *conf, mbedtls_ssl_async_sign_t *f_async_sign, mbedtls_ssl_async_decrypt_t *f_async_decrypt, mbedtls_ssl_async_resume_t *f_async_resume, mbedtls_ssl_async_cancel_t *f_async_cancel, void *config_data); /** * \brief Retrieve the configuration data set by * mbedtls_ssl_conf_async_private_cb(). * * \param conf SSL configuration context * \return The configuration data set by * mbedtls_ssl_conf_async_private_cb(). */ void *mbedtls_ssl_conf_get_async_config_data(const mbedtls_ssl_config *conf); /** * \brief Retrieve the asynchronous operation user context. * * \note This function may only be called while a handshake * is in progress. * * \param ssl The SSL context to access. * * \return The asynchronous operation user context that was last * set during the current handshake. If * mbedtls_ssl_set_async_operation_data() has not yet been * called during the current handshake, this function returns * \c NULL. */ void *mbedtls_ssl_get_async_operation_data(const mbedtls_ssl_context *ssl); /** * \brief Retrieve the asynchronous operation user context. * * \note This function may only be called while a handshake * is in progress. * * \param ssl The SSL context to access. * \param ctx The new value of the asynchronous operation user context. * Call mbedtls_ssl_get_async_operation_data() later during the * same handshake to retrieve this value. */ void mbedtls_ssl_set_async_operation_data(mbedtls_ssl_context *ssl, void *ctx); #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ /** * \brief Callback type: generate a cookie * * \param ctx Context for the callback * \param p Buffer to write to, * must be updated to point right after the cookie * \param end Pointer to one past the end of the output buffer * \param info Client ID info that was passed to * \c mbedtls_ssl_set_client_transport_id() * \param ilen Length of info in bytes * * \return The callback must return 0 on success, * or a negative error code. */ typedef int mbedtls_ssl_cookie_write_t(void *ctx, unsigned char **p, unsigned char *end, const unsigned char *info, size_t ilen); /** * \brief Callback type: verify a cookie * * \param ctx Context for the callback * \param cookie Cookie to verify * \param clen Length of cookie * \param info Client ID info that was passed to * \c mbedtls_ssl_set_client_transport_id() * \param ilen Length of info in bytes * * \return The callback must return 0 if cookie is valid, * or a negative error code. */ typedef int mbedtls_ssl_cookie_check_t(void *ctx, const unsigned char *cookie, size_t clen, const unsigned char *info, size_t ilen); #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /** * \brief Register callbacks for DTLS cookies * (Server only. DTLS only.) * * Default: dummy callbacks that fail, in order to force you to * register working callbacks (and initialize their context). * * To disable HelloVerifyRequest, register NULL callbacks. * * \warning Disabling hello verification allows your server to be used * for amplification in DoS attacks against other hosts. * Only disable if you known this can't happen in your * particular environment. * * \note See comments on \c mbedtls_ssl_handshake() about handling * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected * on the first handshake attempt when this is enabled. * * \note This is also necessary to handle client reconnection from * the same port as described in RFC 6347 section 4.2.8 (only * the variant with cookies is supported currently). See * comments on \c mbedtls_ssl_read() for details. * * \param conf SSL configuration * \param f_cookie_write Cookie write callback * \param f_cookie_check Cookie check callback * \param p_cookie Context for both callbacks */ void mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf, mbedtls_ssl_cookie_write_t *f_cookie_write, mbedtls_ssl_cookie_check_t *f_cookie_check, void *p_cookie); /** * \brief Set client's transport-level identification info. * (Server only. DTLS only.) * * This is usually the IP address (and port), but could be * anything identify the client depending on the underlying * network stack. Used for HelloVerifyRequest with DTLS. * This is *not* used to route the actual packets. * * \param ssl SSL context * \param info Transport-level info identifying the client (eg IP + port) * \param ilen Length of info in bytes * * \note An internal copy is made, so the info buffer can be reused. * * \return 0 on success, * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. */ int mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl, const unsigned char *info, size_t ilen); #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) /** * \brief Enable or disable anti-replay protection for DTLS. * (DTLS only, no effect on TLS.) * Default: enabled. * * \param conf SSL configuration * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. * * \warning Disabling this is a security risk unless the application * protocol handles duplicated packets in a safe way. You * should not disable this without careful consideration. * However, if your application already detects duplicated * packets and needs information about them to adjust its * transmission strategy, then you'll want to disable this. */ void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode); #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ /** * \brief Set a limit on the number of records with a bad MAC * before terminating the connection. * (DTLS only, no effect on TLS.) * Default: 0 (disabled). * * \param conf SSL configuration * \param limit Limit, or 0 to disable. * * \note If the limit is N, then the connection is terminated when * the Nth non-authentic record is seen. * * \note Records with an invalid header are not counted, only the * ones going through the authentication-decryption phase. * * \note This is a security trade-off related to the fact that it's * often relatively easy for an active attacker to inject UDP * datagrams. On one hand, setting a low limit here makes it * easier for such an attacker to forcibly terminated a * connection. On the other hand, a high limit or no limit * might make us waste resources checking authentication on * many bogus packets. */ void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit); #if defined(MBEDTLS_SSL_PROTO_DTLS) /** * \brief Allow or disallow packing of multiple handshake records * within a single datagram. * * \param ssl The SSL context to configure. * \param allow_packing This determines whether datagram packing may * be used or not. A value of \c 0 means that every * record will be sent in a separate datagram; a * value of \c 1 means that, if space permits, * multiple handshake messages (including CCS) belonging to * a single flight may be packed within a single datagram. * * \note This is enabled by default and should only be disabled * for test purposes, or if datagram packing causes * interoperability issues with peers that don't support it. * * \note Allowing datagram packing reduces the network load since * there's less overhead if multiple messages share the same * datagram. Also, it increases the handshake efficiency * since messages belonging to a single datagram will not * be reordered in transit, and so future message buffering * or flight retransmission (if no buffering is used) as * means to deal with reordering are needed less frequently. * * \note Application records are not affected by this option and * are currently always sent in separate datagrams. * */ void mbedtls_ssl_set_datagram_packing(mbedtls_ssl_context *ssl, unsigned allow_packing); /** * \brief Set retransmit timeout values for the DTLS handshake. * (DTLS only, no effect on TLS.) * * \param conf SSL configuration * \param min Initial timeout value in milliseconds. * Default: 1000 (1 second). * \param max Maximum timeout value in milliseconds. * Default: 60000 (60 seconds). * * \note Default values are from RFC 6347 section 4.2.4.1. * * \note The 'min' value should typically be slightly above the * expected round-trip time to your peer, plus whatever time * it takes for the peer to process the message. For example, * if your RTT is about 600ms and you peer needs up to 1s to * do the cryptographic operations in the handshake, then you * should set 'min' slightly above 1600. Lower values of 'min' * might cause spurious resends which waste network resources, * while larger value of 'min' will increase overall latency * on unreliable network links. * * \note The more unreliable your network connection is, the larger * your max / min ratio needs to be in order to achieve * reliable handshakes. * * \note Messages are retransmitted up to log2(ceil(max/min)) times. * For example, if min = 1s and max = 5s, the retransmit plan * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> * resend ... 5s -> give up and return a timeout error. */ void mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf, uint32_t min, uint32_t max); #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the session cache callbacks (server-side only) * If not set, no session resuming is done (except if session * tickets are enabled too). * * The session cache has the responsibility to check for stale * entries based on timeout. See RFC 5246 for recommendations. * * Warning: session.peer_cert is cleared by the SSL/TLS layer on * connection shutdown, so do not cache the pointer! Either set * it to NULL or make a full copy of the certificate. * * The get callback is called once during the initial handshake * to enable session resuming. The get function has the * following parameters: (void *parameter, mbedtls_ssl_session *session) * If a valid entry is found, it should fill the master of * the session object with the cached values and return 0, * return 1 otherwise. Optionally peer_cert can be set as well * if it is properly present in cache entry. * * The set callback is called once during the initial handshake * to enable session resuming after the entire handshake has * been finished. The set function has the following parameters: * (void *parameter, const mbedtls_ssl_session *session). The function * should create a cache entry for future retrieval based on * the data in the session structure and should keep in mind * that the mbedtls_ssl_session object presented (and all its referenced * data) is cleared by the SSL/TLS layer when the connection is * terminated. It is recommended to add metadata to determine if * an entry is still valid in the future. Return 0 if * successfully cached, return 1 otherwise. * * \param conf SSL configuration * \param p_cache parameter (context) for both callbacks * \param f_get_cache session get callback * \param f_set_cache session set callback */ void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf, void *p_cache, mbedtls_ssl_cache_get_t *f_get_cache, mbedtls_ssl_cache_set_t *f_set_cache); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) /** * \brief Load a session for session resumption. * * Sessions loaded through this call will be considered * for session resumption in the next handshake. * * \note Even if this call succeeds, it is not guaranteed that * the next handshake will indeed be shortened through the * use of session resumption: The server is always free * to reject any attempt for resumption and fall back to * a full handshake. * * \note This function can handle a variety of mechanisms for session * resumption: For TLS 1.2, both session ID-based resumption * and ticket-based resumption will be considered. For TLS 1.3, * sessions equate to tickets, and loading one session by * calling this function will lead to its corresponding ticket * being advertised as resumption PSK by the client. This * depends on session tickets being enabled (see * #MBEDTLS_SSL_SESSION_TICKETS configuration option) though. * If session tickets are disabled, a call to this function * with a TLS 1.3 session, will not have any effect on the next * handshake for the SSL context \p ssl. * * \param ssl The SSL context representing the connection which should * be attempted to be setup using session resumption. This * must be initialized via mbedtls_ssl_init() and bound to * an SSL configuration via mbedtls_ssl_setup(), but * the handshake must not yet have been started. * \param session The session to be considered for session resumption. * This must be a session previously exported via * mbedtls_ssl_get_session(), and potentially serialized and * deserialized through mbedtls_ssl_session_save() and * mbedtls_ssl_session_load() in the meantime. * * \return \c 0 if successful. * \return \c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session * could not be loaded because one session has already been * loaded. This error is non-fatal, and has no observable * effect on the SSL context or the session that was attempted * to be loaded. * \return Another negative error code on other kinds of failure. * * \sa mbedtls_ssl_get_session() * \sa mbedtls_ssl_session_load() */ int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session); #endif /* MBEDTLS_SSL_CLI_C */ /** * \brief Load serialized session data into a session structure. * On client, this can be used for loading saved sessions * before resuming them with mbedtls_ssl_set_session(). * On server, this can be used for alternative implementations * of session cache or session tickets. * * \warning If a peer certificate chain is associated with the session, * the serialized state will only contain the peer's * end-entity certificate and the result of the chain * verification (unless verification was disabled), but not * the rest of the chain. * * \see mbedtls_ssl_session_save() * \see mbedtls_ssl_set_session() * * \param session The session structure to be populated. It must have been * initialised with mbedtls_ssl_session_init() but not * populated yet. * \param buf The buffer holding the serialized session data. It must be a * readable buffer of at least \p len bytes. * \param len The size of the serialized data in bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data * was generated in a different version or configuration of * Mbed TLS. * \return Another negative value for other kinds of errors (for * example, unsupported features in the embedded certificate). */ int mbedtls_ssl_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len); /** * \brief Save session structure as serialized data in a buffer. * On client, this can be used for saving session data, * potentially in non-volatile storage, for resuming later. * On server, this can be used for alternative implementations * of session cache or session tickets. * * \see mbedtls_ssl_session_load() * * \param session The session structure to be saved. * \param buf The buffer to write the serialized data to. It must be a * writeable buffer of at least \p buf_len bytes, or may be \c * NULL if \p buf_len is \c 0. * \param buf_len The number of bytes available for writing in \p buf. * \param olen The size in bytes of the data that has been or would have * been written. It must point to a valid \c size_t. * * \note \p olen is updated to the correct value regardless of * whether \p buf_len was large enough. This makes it possible * to determine the necessary size by calling this function * with \p buf set to \c NULL and \p buf_len to \c 0. * * \note For TLS 1.3 sessions, this feature is supported only if the * MBEDTLS_SSL_SESSION_TICKETS configuration option is enabled, * as in TLS 1.3 session resumption is possible only with * tickets. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the * MBEDTLS_SSL_SESSION_TICKETS configuration option is disabled * and the session is a TLS 1.3 session. */ int mbedtls_ssl_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len, size_t *olen); /** * \brief Set the list of allowed ciphersuites and the preference * order. First in the list has the highest preference. * * For TLS 1.2, the notion of ciphersuite determines both * the key exchange mechanism and the suite of symmetric * algorithms to be used during and after the handshake. * * For TLS 1.3 (in development), the notion of ciphersuite * only determines the suite of symmetric algorithms to be * used during and after the handshake, while key exchange * mechanisms are configured separately. * * In Mbed TLS, ciphersuites for both TLS 1.2 and TLS 1.3 * are configured via this function. For users of TLS 1.3, * there will be separate API for the configuration of key * exchange mechanisms. * * The list of ciphersuites passed to this function may * contain a mixture of TLS 1.2 and TLS 1.3 ciphersuite * identifiers. This is useful if negotiation of TLS 1.3 * should be attempted, but a fallback to TLS 1.2 would * be tolerated. * * \note By default, the server chooses its preferred * ciphersuite among those that the client supports. If * mbedtls_ssl_conf_preference_order() is called to prefer * the client's preferences, the server instead chooses * the client's preferred ciphersuite among those that * the server supports. * * \warning The ciphersuites array \p ciphersuites is not copied. * It must remain valid for the lifetime of the SSL * configuration \p conf. * * \param conf The SSL configuration to modify. * \param ciphersuites A 0-terminated list of IANA identifiers of supported * ciphersuites, accessible through \c MBEDTLS_TLS_XXX * and \c MBEDTLS_TLS1_3_XXX macros defined in * ssl_ciphersuites.h. */ void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, const int *ciphersuites); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /** * \brief Set the supported key exchange modes for TLS 1.3 connections. * * In contrast to TLS 1.2, the ciphersuite concept in TLS 1.3 does not * include the choice of key exchange mechanism. It is therefore not * covered by the API mbedtls_ssl_conf_ciphersuites(). See the * documentation of mbedtls_ssl_conf_ciphersuites() for more * information on the ciphersuite concept in TLS 1.2 and TLS 1.3. * * The present function is specific to TLS 1.3 and allows users to * configure the set of supported key exchange mechanisms in TLS 1.3. * * \param conf The SSL configuration the change should apply to. * \param kex_modes A bitwise combination of one or more of the following: * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK * This flag enables pure-PSK key exchanges. * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL * This flag enables combined PSK-ephemeral key exchanges. * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL * This flag enables pure-ephemeral key exchanges. * For convenience, the following pre-defined macros are * available for combinations of the above: * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL * Includes all of pure-PSK, PSK-ephemeral and pure-ephemeral. * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL * Includes both pure-PSK and combined PSK-ephemeral * key exchanges, but excludes pure-ephemeral key exchanges. * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL * Includes both pure-ephemeral and combined PSK-ephemeral * key exchanges. * * \note If a PSK-based key exchange mode shall be supported, applications * must also use the APIs mbedtls_ssl_conf_psk() or * mbedtls_ssl_conf_psk_cb() or mbedtls_ssl_conf_psk_opaque() * to configure the PSKs to be used. * * \note If a pure-ephemeral key exchange mode shall be supported, * server-side applications must also provide a certificate via * mbedtls_ssl_conf_own_cert(). * */ void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf, const int kex_modes); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_UNEXPECTED_CID_IGNORE 0 #define MBEDTLS_SSL_UNEXPECTED_CID_FAIL 1 /** * \brief Specify the length of Connection IDs for incoming * encrypted DTLS records, as well as the behaviour * on unexpected CIDs. * * By default, the CID length is set to \c 0, * and unexpected CIDs are silently ignored. * * \param conf The SSL configuration to modify. * \param len The length in Bytes of the CID fields in encrypted * DTLS records using the CID mechanism. This must * not be larger than #MBEDTLS_SSL_CID_OUT_LEN_MAX. * \param ignore_other_cids This determines the stack's behaviour when * receiving a record with an unexpected CID. * Possible values are: * - #MBEDTLS_SSL_UNEXPECTED_CID_IGNORE * In this case, the record is silently ignored. * - #MBEDTLS_SSL_UNEXPECTED_CID_FAIL * In this case, the stack fails with the specific * error code #MBEDTLS_ERR_SSL_UNEXPECTED_CID. * * \note The CID specification allows implementations to either * use a common length for all incoming connection IDs or * allow variable-length incoming IDs. Mbed TLS currently * requires a common length for all connections sharing the * same SSL configuration; this allows simpler parsing of * record headers. * * \return \c 0 on success. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p len * is too large. */ int mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf, size_t len, int ignore_other_cids); #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set the X.509 security profile used for verification * * \note The restrictions are enforced for all certificates in the * chain. However, signatures in the handshake are not covered * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). * * \param conf SSL configuration * \param profile Profile to use */ void mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf, const mbedtls_x509_crt_profile *profile); /** * \brief Set the data required to verify peer certificate * * \note See \c mbedtls_x509_crt_verify() for notes regarding the * parameters ca_chain (maps to trust_ca for that function) * and ca_crl. * * \param conf SSL configuration * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) * \param ca_crl trusted CA CRLs */ void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl); #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) /** * \brief Set DN hints sent to client in CertificateRequest message * * \note If not set, subject distinguished names (DNs) are taken * from \c mbedtls_ssl_conf_ca_chain() * or \c mbedtls_ssl_set_hs_ca_chain()) * * \param conf SSL configuration * \param crt crt chain whose subject DNs are issuer DNs of client certs * from which the client should select client peer certificate. */ static inline void mbedtls_ssl_conf_dn_hints(mbedtls_ssl_config *conf, const mbedtls_x509_crt *crt) { conf->MBEDTLS_PRIVATE(dn_hints) = crt; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /** * \brief Set the trusted certificate callback. * * This API allows to register the set of trusted certificates * through a callback, instead of a linked list as configured * by mbedtls_ssl_conf_ca_chain(). * * This is useful for example in contexts where a large number * of CAs are used, and the inefficiency of maintaining them * in a linked list cannot be tolerated. It is also useful when * the set of trusted CAs needs to be modified frequently. * * See the documentation of `mbedtls_x509_crt_ca_cb_t` for * more information. * * \param conf The SSL configuration to register the callback with. * \param f_ca_cb The trusted certificate callback to use when verifying * certificate chains. * \param p_ca_cb The context to be passed to \p f_ca_cb (for example, * a reference to a trusted CA database). * * \note This API is incompatible with mbedtls_ssl_conf_ca_chain(): * Any call to this function overwrites the values set through * earlier calls to mbedtls_ssl_conf_ca_chain() or * mbedtls_ssl_conf_ca_cb(). * * \note This API is incompatible with CA indication in * CertificateRequest messages: A server-side SSL context which * is bound to an SSL configuration that uses a CA callback * configured via mbedtls_ssl_conf_ca_cb(), and which requires * client authentication, will send an empty CA list in the * corresponding CertificateRequest message. * * \note This API is incompatible with mbedtls_ssl_set_hs_ca_chain(): * If an SSL context is bound to an SSL configuration which uses * CA callbacks configured via mbedtls_ssl_conf_ca_cb(), then * calls to mbedtls_ssl_set_hs_ca_chain() have no effect. * * \note The use of this API disables the use of restartable ECC * during X.509 CRT signature verification (but doesn't affect * other uses). * * \warning This API is incompatible with the use of CRLs. Any call to * mbedtls_ssl_conf_ca_cb() unsets CRLs configured through * earlier calls to mbedtls_ssl_conf_ca_chain(). * * \warning In multi-threaded environments, the callback \p f_ca_cb * must be thread-safe, and it is the user's responsibility * to guarantee this (for example through a mutex * contained in the callback context pointed to by \p p_ca_cb). */ void mbedtls_ssl_conf_ca_cb(mbedtls_ssl_config *conf, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ /** * \brief Set own certificate chain and private key * * \note own_cert should contain in order from the bottom up your * certificate chain. The top certificate (self-signed) * can be omitted. * * \note On server, this function can be called multiple times to * provision more than one cert/key pair (eg one ECDSA, one * RSA with SHA-256, one RSA with SHA-1). An adequate * certificate will be selected according to the client's * advertised capabilities. In case multiple certificates are * adequate, preference is given to the one set by the first * call to this function, then second, etc. * * \note On client, only the first call has any effect. That is, * only one client certificate can be provisioned. The * server's preferences in its CertificateRequest message will * be ignored and our only cert will be sent regardless of * whether it matches those preferences - the server can then * decide what it wants to do with it. * * \note The provided \p pk_key needs to match the public key in the * first certificate in \p own_cert, or all handshakes using * that certificate will fail. It is your responsibility * to ensure that; this function will not perform any check. * You may use mbedtls_pk_check_pair() in order to perform * this check yourself, but be aware that this function can * be computationally expensive on some key types. * * \param conf SSL configuration * \param own_cert own public certificate chain * \param pk_key own private key * * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED */ int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key); #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) /** * \brief Configure pre-shared keys (PSKs) and their * identities to be used in PSK-based ciphersuites. * * Only one PSK can be registered, through either * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). * If you attempt to register more than one PSK, this function * fails, though this may change in future versions, which * may add support for multiple PSKs. * * \note This is mainly useful for clients. Servers will usually * want to use \c mbedtls_ssl_conf_psk_cb() instead. * * \note A PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback * takes precedence over a PSK configured by this function. * * \param conf The SSL configuration to register the PSK with. * \param psk The pointer to the pre-shared key to use. * \param psk_len The length of the pre-shared key in bytes. * \param psk_identity The pointer to the pre-shared key identity. * \param psk_identity_len The length of the pre-shared key identity * in bytes. * * \note The PSK and its identity are copied internally and * hence need not be preserved by the caller for the lifetime * of the SSL configuration. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs * can be configured. In this case, the old PSK(s) remain intact. * \return Another negative error code on other kinds of failure. */ int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, const unsigned char *psk, size_t psk_len, const unsigned char *psk_identity, size_t psk_identity_len); #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * \brief Configure one or more opaque pre-shared keys (PSKs) and * their identities to be used in PSK-based ciphersuites. * * Only one PSK can be registered, through either * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). * If you attempt to register more than one PSK, this function * fails, though this may change in future versions, which * may add support for multiple PSKs. * * \note This is mainly useful for clients. Servers will usually * want to use \c mbedtls_ssl_conf_psk_cb() instead. * * \note An opaque PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in * the PSK callback takes precedence over an opaque PSK * configured by this function. * * \param conf The SSL configuration to register the PSK with. * \param psk The identifier of the key slot holding the PSK. * Until \p conf is destroyed or this function is successfully * called again, the key slot \p psk must be populated with a * key of type PSA_ALG_CATEGORY_KEY_DERIVATION whose policy * allows its use for the key derivation algorithm applied * in the handshake. * \param psk_identity The pointer to the pre-shared key identity. * \param psk_identity_len The length of the pre-shared key identity * in bytes. * * \note The PSK identity hint is copied internally and hence need * not be preserved by the caller for the lifetime of the * SSL configuration. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs * can be configured. In this case, the old PSK(s) remain intact. * \return Another negative error code on other kinds of failure. */ int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf, mbedtls_svc_key_id_t psk, const unsigned char *psk_identity, size_t psk_identity_len); #endif /* MBEDTLS_USE_PSA_CRYPTO */ /** * \brief Set the pre-shared Key (PSK) for the current handshake. * * \note This should only be called inside the PSK callback, * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). * * \note A PSK set by this function takes precedence over a PSK * configured by \c mbedtls_ssl_conf_psk(). * * \param ssl The SSL context to configure a PSK for. * \param psk The pointer to the pre-shared key. * \param psk_len The length of the pre-shared key in bytes. * * \return \c 0 if successful. * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. */ int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl, const unsigned char *psk, size_t psk_len); #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * \brief Set an opaque pre-shared Key (PSK) for the current handshake. * * \note This should only be called inside the PSK callback, * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). * * \note An opaque PSK set by this function takes precedence over an * opaque PSK configured by \c mbedtls_ssl_conf_psk_opaque(). * * \param ssl The SSL context to configure a PSK for. * \param psk The identifier of the key slot holding the PSK. * For the duration of the current handshake, the key slot * must be populated with a key of type * PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows its * use for the key derivation algorithm * applied in the handshake. * * \return \c 0 if successful. * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. */ int mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t psk); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the PSK callback (server-side only). * * If set, the PSK callback is called for each * handshake where a PSK-based ciphersuite was negotiated. * The caller provides the identity received and wants to * receive the actual PSK data and length. * * The callback has the following parameters: * - \c void*: The opaque pointer \p p_psk. * - \c mbedtls_ssl_context*: The SSL context to which * the operation applies. * - \c const unsigned char*: The PSK identity * selected by the client. * - \c size_t: The length of the PSK identity * selected by the client. * * If a valid PSK identity is found, the callback should use * \c mbedtls_ssl_set_hs_psk() or * \c mbedtls_ssl_set_hs_psk_opaque() * on the SSL context to set the correct PSK and return \c 0. * Any other return value will result in a denied PSK identity. * * \note A dynamic PSK (i.e. set by the PSK callback) takes * precedence over a static PSK (i.e. set by * \c mbedtls_ssl_conf_psk() or * \c mbedtls_ssl_conf_psk_opaque()). * This means that if you set a PSK callback using this * function, you don't need to set a PSK using * \c mbedtls_ssl_conf_psk() or * \c mbedtls_ssl_conf_psk_opaque()). * * \param conf The SSL configuration to register the callback with. * \param f_psk The callback for selecting and setting the PSK based * in the PSK identity chosen by the client. * \param p_psk A pointer to an opaque structure to be passed to * the callback, for example a PSK store. */ void mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_psk); #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the Diffie-Hellman public P and G values * from big-endian binary presentations. * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) * * \param conf SSL configuration * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form * \param P_len Length of DHM modulus * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form * \param G_len Length of DHM generator * * \return 0 if successful */ int mbedtls_ssl_conf_dh_param_bin(mbedtls_ssl_config *conf, const unsigned char *dhm_P, size_t P_len, const unsigned char *dhm_G, size_t G_len); /** * \brief Set the Diffie-Hellman public P and G values, * read from existing context (server-side only) * * \param conf SSL configuration * \param dhm_ctx Diffie-Hellman-Merkle context * * \return 0 if successful */ int mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx); #endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) /** * \brief Set the minimum length for Diffie-Hellman parameters. * (Client-side only.) * (Default: 1024 bits.) * * \param conf SSL configuration * \param bitlen Minimum bit length of the DHM prime */ void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, unsigned int bitlen); #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_ECP_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the allowed curves in order of preference. * * On server: this only affects selection of the ECDHE curve; * the curves used for ECDH and ECDSA are determined by the * list of available certificates instead. * * On client: this affects the list of curves offered for any * use. The server can override our preference order. * * Both sides: limits the set of curves accepted for use in * ECDHE and in the peer's end-entity certificate. * * \deprecated Superseded by mbedtls_ssl_conf_groups(). * * \note This has no influence on which curves are allowed inside the * certificate chains, see \c mbedtls_ssl_conf_cert_profile() * for that. For the end-entity certificate however, the key * will be accepted only if it is allowed both by this list * and by the cert profile. * * \note This list should be ordered by decreasing preference * (preferred curve first). * * \note The default list is the same set of curves that * #mbedtls_x509_crt_profile_default allows, plus * ECDHE-only curves selected according to the same criteria. * The order favors curves with the lowest resource usage. * * \note New minor versions of Mbed TLS may extend this list, * for example if new curves are added to the library. * New minor versions of Mbed TLS will not remove items * from this list unless serious security concerns require it. * New minor versions of Mbed TLS may change the order in * keeping with the general principle of favoring the lowest * resource usage. * * \param conf SSL configuration * \param curves Ordered list of allowed curves, * terminated by MBEDTLS_ECP_DP_NONE. */ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, const mbedtls_ecp_group_id *curves); #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_ECP_C */ /** * \brief Set the allowed groups in order of preference. * * On server: This only affects the choice of key agreement mechanism * * On client: this affects the list of groups offered for any * use. The server can override our preference order. * * Both sides: limits the set of groups accepted for use in * key sharing. * * \note This function replaces the deprecated mbedtls_ssl_conf_curves(), * which only allows ECP curves to be configured. * * \note The most recent invocation of either mbedtls_ssl_conf_curves() * or mbedtls_ssl_conf_groups() nullifies all previous invocations * of both. * * \note This list should be ordered by decreasing preference * (preferred group first). * * \note When this function is not called, a default list is used, * consisting of all supported curves at 255 bits and above, * and all supported finite fields at 2048 bits and above. * The order favors groups with the lowest resource usage. * * \note New minor versions of Mbed TLS will not remove items * from the default list unless serious security concerns require it. * New minor versions of Mbed TLS may change the order in * keeping with the general principle of favoring the lowest * resource usage. * * \param conf SSL configuration * \param groups List of allowed groups ordered by preference, terminated by 0. * Must contain valid IANA NamedGroup IDs (provided via either an integer * or using MBEDTLS_TLS1_3_NAMED_GROUP_XXX macros). */ void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, const uint16_t *groups); #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2) /** * \brief Set the allowed hashes for signatures during the handshake. * * \note This only affects which hashes are offered and can be used * for signatures during the handshake. Hashes for message * authentication and the TLS PRF are controlled by the * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes * used for certificate signature are controlled by the * verification profile, see \c mbedtls_ssl_conf_cert_profile(). * * \deprecated Superseded by mbedtls_ssl_conf_sig_algs(). * * \note This list should be ordered by decreasing preference * (preferred hash first). * * \note By default, all supported hashes whose length is at least * 256 bits are allowed. This is the same set as the default * for certificate verification * (#mbedtls_x509_crt_profile_default). * The preference order is currently unspecified and may * change in future versions. * * \note New minor versions of Mbed TLS may extend this list, * for example if new curves are added to the library. * New minor versions of Mbed TLS will not remove items * from this list unless serious security concerns require it. * * \param conf SSL configuration * \param hashes Ordered list of allowed signature hashes, * terminated by \c MBEDTLS_MD_NONE. */ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, const int *hashes); #endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */ /** * \brief Configure allowed signature algorithms for use in TLS * * \param conf The SSL configuration to use. * \param sig_algs List of allowed IANA values for TLS 1.3 signature algorithms, * terminated by #MBEDTLS_TLS1_3_SIG_NONE. The list must remain * available throughout the lifetime of the conf object. * - For TLS 1.3, values of \c MBEDTLS_TLS1_3_SIG_XXXX should be * used. * - For TLS 1.2, values should be given as * "(HashAlgorithm << 8) | SignatureAlgorithm". */ void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf, const uint16_t *sig_algs); #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set or reset the hostname to check against the received * server certificate. It sets the ServerName TLS extension, * too, if that extension is enabled. (client-side only) * * \param ssl SSL context * \param hostname the server hostname, may be NULL to clear hostname * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. * * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on * too long input hostname. * * Hostname set to the one provided on success (cleared * when NULL). On allocation failure hostname is cleared. * On too long input failure, old hostname is unchanged. */ int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname); /** * \brief Get the hostname that checked against the received * server certificate. It is used to set the ServerName * TLS extension, too, if that extension is enabled. * (client-side only) * * \param ssl SSL context * * \return const pointer to the hostname value */ static inline const char *mbedtls_ssl_get_hostname(mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(hostname); } #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /** * \brief Retrieve SNI extension value for the current handshake. * Available in \c f_cert_cb of \c mbedtls_ssl_conf_cert_cb(), * this is the same value passed to \c f_sni callback of * \c mbedtls_ssl_conf_sni() and may be used instead of * \c mbedtls_ssl_conf_sni(). * * \param ssl SSL context * \param name_len pointer into which to store length of returned value. * 0 if SNI extension is not present or not yet processed. * * \return const pointer to SNI extension value. * - value is valid only when called in \c f_cert_cb * registered with \c mbedtls_ssl_conf_cert_cb(). * - value is NULL if SNI extension is not present. * - value is not '\0'-terminated. Use \c name_len for len. * - value must not be freed. */ const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl, size_t *name_len); /** * \brief Set own certificate and key for the current handshake * * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within * the SNI callback or the certificate selection callback. * * \note Passing null \c own_cert clears the certificate list for * the current handshake. * * \param ssl SSL context * \param own_cert own public certificate chain * \param pk_key own private key * * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED */ int mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key); /** * \brief Set the data required to verify peer certificate for the * current handshake * * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within * the SNI callback or the certificate selection callback. * * \param ssl SSL context * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) * \param ca_crl trusted CA CRLs */ void mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl); #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) /** * \brief Set DN hints sent to client in CertificateRequest message * * \note Same as \c mbedtls_ssl_conf_dn_hints() but for use within * the SNI callback or the certificate selection callback. * * \param ssl SSL context * \param crt crt chain whose subject DNs are issuer DNs of client certs * from which the client should select client peer certificate. */ void mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl, const mbedtls_x509_crt *crt); #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ /** * \brief Set authmode for the current handshake. * * \note Same as \c mbedtls_ssl_conf_authmode() but for use within * the SNI callback or the certificate selection callback. * * \param ssl SSL context * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or * MBEDTLS_SSL_VERIFY_REQUIRED */ void mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl, int authmode); /** * \brief Set server side ServerName TLS extension callback * (optional, server-side only). * * If set, the ServerName callback is called whenever the * server receives a ServerName TLS extension from the client * during a handshake. The ServerName callback has the * following parameters: (void *parameter, mbedtls_ssl_context *ssl, * const unsigned char *hostname, size_t len). If a suitable * certificate is found, the callback must set the * certificate(s) and key(s) to use with \c * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), * and may optionally adjust the CA and associated CRL with \c * mbedtls_ssl_set_hs_ca_chain() as well as the client * authentication mode with \c mbedtls_ssl_set_hs_authmode(), * then must return 0. If no matching name is found, the * callback may return non-zero to abort the handshake. * * \param conf SSL configuration * \param f_sni verification function * \param p_sni verification parameter */ void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf, int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_sni); #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) /** * \brief Set the EC J-PAKE password for current handshake. * * \note An internal copy is made, and destroyed as soon as the * handshake is completed, or when the SSL context is reset or * freed. * * \note The SSL context needs to be already set up. The right place * to call this function is between \c mbedtls_ssl_setup() or * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). * Password cannot be empty (see RFC 8236). * * \param ssl SSL context * \param pw EC J-PAKE password (pre-shared secret). It cannot be empty * \param pw_len length of pw in bytes * * \return 0 on success, or a negative error code. */ int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, const unsigned char *pw, size_t pw_len); /** * \brief Set the EC J-PAKE opaque password for current handshake. * * \note The key must remain valid until the handshake is over. * * \note The SSL context needs to be already set up. The right place * to call this function is between \c mbedtls_ssl_setup() or * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). * * \param ssl SSL context * \param pwd EC J-PAKE opaque password * * \return 0 on success, or a negative error code. */ int mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t pwd); #endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) /** * \brief Set the supported Application Layer Protocols. * * \param conf SSL configuration * \param protos Pointer to a NULL-terminated list of supported protocols, * in decreasing preference order. The pointer to the list is * recorded by the library for later reference as required, so * the lifetime of the table must be at least as long as the * lifetime of the SSL configuration structure. * * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. */ int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos); /** * \brief Get the name of the negotiated Application Layer Protocol. * This function should be called after the handshake is * completed. * * \param ssl SSL context * * \return Protocol name, or NULL if no protocol was negotiated. */ const char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) #if defined(MBEDTLS_DEBUG_C) static inline const char *mbedtls_ssl_get_srtp_profile_as_string(mbedtls_ssl_srtp_profile profile) { switch (profile) { case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: return "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80"; case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: return "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32"; case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: return "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80"; case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: return "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32"; default: break; } return ""; } #endif /* MBEDTLS_DEBUG_C */ /** * \brief Manage support for mki(master key id) value * in use_srtp extension. * MKI is an optional part of SRTP used for key management * and re-keying. See RFC3711 section 3.1 for details. * The default value is * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED. * * \param conf The SSL configuration to manage mki support. * \param support_mki_value Enable or disable mki usage. Values are * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED * or #MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED. */ void mbedtls_ssl_conf_srtp_mki_value_supported(mbedtls_ssl_config *conf, int support_mki_value); /** * \brief Set the supported DTLS-SRTP protection profiles. * * \param conf SSL configuration * \param profiles Pointer to a List of MBEDTLS_TLS_SRTP_UNSET terminated * supported protection profiles * in decreasing preference order. * The pointer to the list is recorded by the library * for later reference as required, so the lifetime * of the table must be at least as long as the lifetime * of the SSL configuration structure. * The list must not hold more than * MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH elements * (excluding the terminating MBEDTLS_TLS_SRTP_UNSET). * * \return 0 on success * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA when the list of * protection profiles is incorrect. */ int mbedtls_ssl_conf_dtls_srtp_protection_profiles (mbedtls_ssl_config *conf, const mbedtls_ssl_srtp_profile *profiles); /** * \brief Set the mki_value for the current DTLS-SRTP session. * * \param ssl SSL context to use. * \param mki_value The MKI value to set. * \param mki_len The length of the MKI value. * * \note This function is relevant on client side only. * The server discovers the mki value during handshake. * A mki value set on server side using this function * is ignored. * * \return 0 on success * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE */ int mbedtls_ssl_dtls_srtp_set_mki_value(mbedtls_ssl_context *ssl, unsigned char *mki_value, uint16_t mki_len); /** * \brief Get the negotiated DTLS-SRTP information: * Protection profile and MKI value. * * \warning This function must be called after the handshake is * completed. The value returned by this function must * not be trusted or acted upon before the handshake completes. * * \param ssl The SSL context to query. * \param dtls_srtp_info The negotiated DTLS-SRTP information: * - Protection profile in use. * A direct mapping of the iana defined value for protection * profile on an uint16_t. http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml * #MBEDTLS_TLS_SRTP_UNSET if the use of SRTP was not negotiated * or peer's Hello packet was not parsed yet. * - mki size and value( if size is > 0 ). */ void mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl, mbedtls_dtls_srtp_info *dtls_srtp_info); #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the maximum supported version sent from the client side * and/or accepted at the server side. * * See also the documentation of mbedtls_ssl_conf_min_version(). * * \note This ignores ciphersuites from higher versions. * * \note This function is deprecated and has been replaced by * \c mbedtls_ssl_conf_max_tls_version(). * * \param conf SSL configuration * \param major Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3) * \param minor Minor version number * (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2, * #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3) */ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor); #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Set the maximum supported version sent from the client side * and/or accepted at the server side. * * \note After the handshake, you can call * mbedtls_ssl_get_version_number() to see what version was * negotiated. * * \param conf SSL configuration * \param tls_version TLS protocol version number (\c mbedtls_ssl_protocol_version) * (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid) */ static inline void mbedtls_ssl_conf_max_tls_version(mbedtls_ssl_config *conf, mbedtls_ssl_protocol_version tls_version) { conf->MBEDTLS_PRIVATE(max_tls_version) = tls_version; } #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the minimum accepted SSL/TLS protocol version * * \note By default, all supported versions are accepted. * Future versions of the library may disable older * protocol versions by default if they become deprecated. * * \note The following versions are supported (if enabled at * compile time): * - (D)TLS 1.2: \p major = #MBEDTLS_SSL_MAJOR_VERSION_3, * \p minor = #MBEDTLS_SSL_MINOR_VERSION_3 * - TLS 1.3: \p major = #MBEDTLS_SSL_MAJOR_VERSION_3, * \p minor = #MBEDTLS_SSL_MINOR_VERSION_4 * * Note that the numbers in the constant names are the * TLS internal protocol numbers, and the minor versions * differ by one from the human-readable versions! * * \note Input outside of the SSL_MAX_XXXXX_VERSION and * SSL_MIN_XXXXX_VERSION range is ignored. * * \note After the handshake, you can call * mbedtls_ssl_get_version_number() to see what version was * negotiated. * * \note This function is deprecated and has been replaced by * \c mbedtls_ssl_conf_min_tls_version(). * * \param conf SSL configuration * \param major Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3) * \param minor Minor version number * (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2, * #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3) */ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor); #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Set the minimum supported version sent from the client side * and/or accepted at the server side. * * \note After the handshake, you can call * mbedtls_ssl_get_version_number() to see what version was * negotiated. * * \param conf SSL configuration * \param tls_version TLS protocol version number (\c mbedtls_ssl_protocol_version) * (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid) */ static inline void mbedtls_ssl_conf_min_tls_version(mbedtls_ssl_config *conf, mbedtls_ssl_protocol_version tls_version) { conf->MBEDTLS_PRIVATE(min_tls_version) = tls_version; } #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) /** * \brief Enable or disable Encrypt-then-MAC * (Default: MBEDTLS_SSL_ETM_ENABLED) * * \note This should always be enabled, it is a security * improvement, and should not cause any interoperability * issue (used only if the peer supports it too). * * \param conf SSL configuration * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED */ void mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm); #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) /** * \brief Enable or disable Extended Master Secret negotiation. * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) * * \note This should always be enabled, it is a security fix to the * protocol, and should not cause any interoperability issue * (used only if the peer supports it too). * * \param conf SSL configuration * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED */ void mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems); #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Whether to send a list of acceptable CAs in * CertificateRequest messages. * (Default: do send) * * \param conf SSL configuration * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED */ void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf, char cert_req_ca_list); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** * \brief Set the maximum fragment length to emit and/or negotiate. * (Typical: the smaller of #MBEDTLS_SSL_IN_CONTENT_LEN and * #MBEDTLS_SSL_OUT_CONTENT_LEN, usually `2^14` bytes) * (Server: set maximum fragment length to emit, * usually negotiated by the client during handshake) * (Client: set maximum fragment length to emit *and* * negotiate with the server during handshake) * (Default: #MBEDTLS_SSL_MAX_FRAG_LEN_NONE) * * \note On the client side, the maximum fragment length extension * *will not* be used, unless the maximum fragment length has * been set via this function to a value different than * #MBEDTLS_SSL_MAX_FRAG_LEN_NONE. * * \note With TLS, this currently only affects ApplicationData (sent * with \c mbedtls_ssl_read()), not handshake messages. * With DTLS, this affects both ApplicationData and handshake. * * \note This sets the maximum length for a record's payload, * excluding record overhead that will be added to it, see * \c mbedtls_ssl_get_record_expansion(). * * \note For DTLS, it is also possible to set a limit for the total * size of datagrams passed to the transport layer, including * record overhead, see \c mbedtls_ssl_set_mtu(). * * \param conf SSL configuration * \param mfl_code Code for maximum fragment length (allowed values: * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) * * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA */ int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code); #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Pick the ciphersuites order according to the second parameter * in the SSL Server module (MBEDTLS_SSL_SRV_C). * (Default, if never called: MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER) * * \param conf SSL configuration * \param order Server or client (MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER * or MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) */ void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) /** * \brief Enable / Disable TLS 1.2 session tickets (client only, * TLS 1.2 only). Enabled by default. * * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). * * \param conf SSL configuration * \param use_tickets Enable or disable (#MBEDTLS_SSL_SESSION_TICKETS_ENABLED or * #MBEDTLS_SSL_SESSION_TICKETS_DISABLED) */ void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /** * \brief Enable / Disable handling of TLS 1.3 NewSessionTicket messages * (client only, TLS 1.3 only). * * The handling of TLS 1.3 NewSessionTicket messages is disabled by * default. * * In TLS 1.3, servers may send a NewSessionTicket message at any time, * and may send multiple NewSessionTicket messages. By default, TLS 1.3 * clients ignore NewSessionTicket messages. * * To support session tickets in TLS 1.3 clients, call this function * with #MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED. When * this is enabled, when a client receives a NewSessionTicket message, * the next call to a message processing functions (notably * mbedtls_ssl_handshake() and mbedtls_ssl_read()) will return * #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET. The client should then * call mbedtls_ssl_get_session() to retrieve the session ticket before * calling the same message processing function again. * * \param conf SSL configuration * \param signal_new_session_tickets Enable or disable * (#MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED or * #MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED) */ void mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets( mbedtls_ssl_config *conf, int signal_new_session_tickets); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_3) /** * \brief Number of NewSessionTicket messages for the server to send * after handshake completion. * * \note The default value is * \c MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS. * * \note In case of a session resumption, this setting only partially apply. * At most one ticket is sent in that case to just renew the pool of * tickets of the client. The rationale is to avoid the number of * tickets on the server to become rapidly out of control when the * server has the same configuration for all its connection instances. * * \param conf SSL configuration * \param num_tickets Number of NewSessionTicket. * */ void mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf, uint16_t num_tickets); #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_3*/ #if defined(MBEDTLS_SSL_RENEGOTIATION) /** * \brief Enable / Disable renegotiation support for connection when * initiated by peer * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) * * \warning It is recommended to always disable renegotiation unless you * know you need it and you know what you're doing. In the * past, there have been several issues associated with * renegotiation or a poor understanding of its properties. * * \note Server-side, enabling renegotiation also makes the server * susceptible to a resource DoS by a malicious client. * * \param conf SSL configuration * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or * MBEDTLS_SSL_RENEGOTIATION_DISABLED) */ void mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** * \brief Prevent or allow legacy renegotiation. * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) * * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to * be established even if the peer does not support * secure renegotiation, but does not allow renegotiation * to take place if not secure. * (Interoperable and secure option) * * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations * with non-upgraded peers. Allowing legacy renegotiation * makes the connection vulnerable to specific man in the * middle attacks. (See RFC 5746) * (Most interoperable and least secure option) * * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections * if peer does not support secure renegotiation. Results * in interoperability issues with non-upgraded peers * that do not support renegotiation altogether. * (Most secure option, interoperability issues) * * \param conf SSL configuration * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, * SSL_ALLOW_LEGACY_RENEGOTIATION or * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) */ void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy); #if defined(MBEDTLS_SSL_RENEGOTIATION) /** * \brief Enforce renegotiation requests. * (Default: enforced, max_records = 16) * * When we request a renegotiation, the peer can comply or * ignore the request. This function allows us to decide * whether to enforce our renegotiation requests by closing * the connection if the peer doesn't comply. * * However, records could already be in transit from the peer * when the request is emitted. In order to increase * reliability, we can accept a number of records before the * expected handshake records. * * The optimal value is highly dependent on the specific usage * scenario. * * \note With DTLS and server-initiated renegotiation, the * HelloRequest is retransmitted every time mbedtls_ssl_read() times * out or receives Application Data, until: * - max_records records have beens seen, if it is >= 0, or * - the number of retransmits that would happen during an * actual handshake has been reached. * Please remember the request might be lost a few times * if you consider setting max_records to a really low value. * * \warning On client, the grace period can only happen during * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() * which always behave as if max_record was 0. The reason is, * if we receive application data from the server, we need a * place to write it, which only happens during mbedtls_ssl_read(). * * \param conf SSL configuration * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to * enforce renegotiation, or a non-negative value to enforce * it but allow for a grace period of max_records records. */ void mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records); /** * \brief Set record counter threshold for periodic renegotiation. * (Default: 2^48 - 1) * * Renegotiation is automatically triggered when a record * counter (outgoing or incoming) crosses the defined * threshold. The default value is meant to prevent the * connection from being closed when the counter is about to * reached its maximal value (it is not allowed to wrap). * * Lower values can be used to enforce policies such as "keys * must be refreshed every N packets with cipher X". * * The renegotiation period can be disabled by setting * conf->disable_renegotiation to * MBEDTLS_SSL_RENEGOTIATION_DISABLED. * * \note When the configured transport is * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, * the maximum renegotiation period is 2^64 - 1. * * \param conf SSL configuration * \param period The threshold value: a big-endian 64-bit number. */ void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf, const unsigned char period[8]); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** * \brief Check if there is data already read from the * underlying transport but not yet processed. * * \param ssl SSL context * * \return 0 if nothing's pending, 1 otherwise. * * \note This is different in purpose and behaviour from * \c mbedtls_ssl_get_bytes_avail in that it considers * any kind of unprocessed data, not only unread * application data. If \c mbedtls_ssl_get_bytes * returns a non-zero value, this function will * also signal pending data, but the converse does * not hold. For example, in DTLS there might be * further records waiting to be processed from * the current underlying transport's datagram. * * \note If this function returns 1 (data pending), this * does not imply that a subsequent call to * \c mbedtls_ssl_read will provide any data; * e.g., the unprocessed data might turn out * to be an alert or a handshake message. * * \note This function is useful in the following situation: * If the SSL/TLS module successfully returns from an * operation - e.g. a handshake or an application record * read - and you're awaiting incoming data next, you * must not immediately idle on the underlying transport * to have data ready, but you need to check the value * of this function first. The reason is that the desired * data might already be read but not yet processed. * If, in contrast, a previous call to the SSL/TLS module * returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary * to call this function, as the latter error code entails * that all internal data has been processed. * */ int mbedtls_ssl_check_pending(const mbedtls_ssl_context *ssl); /** * \brief Return the number of application data bytes * remaining to be read from the current record. * * \param ssl SSL context * * \return How many bytes are available in the application * data record read buffer. * * \note When working over a datagram transport, this is * useful to detect the current datagram's boundary * in case \c mbedtls_ssl_read has written the maximal * amount of data fitting into the input buffer. * */ size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl); /** * \brief Return the result of the certificate verification * * \param ssl The SSL context to use. * * \return \c 0 if the certificate verification was successful. * \return \c -1u if the result is not available. This may happen * e.g. if the handshake aborts early, or a verification * callback returned a fatal error. * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h. */ uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl); /** * \brief Return the id of the current ciphersuite * * \param ssl SSL context * * \return a ciphersuite id */ int mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl); /** * \brief Return the name of the current ciphersuite * * \param ssl SSL context * * \return a string containing the ciphersuite name */ const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl); /** * \brief Return the (D)TLS protocol version negotiated in the * given connection. * * \note If you call this function too early during the initial * handshake, before the two sides have agreed on a version, * this function returns #MBEDTLS_SSL_VERSION_UNKNOWN. * * \param ssl The SSL context to query. * \return The negotiated protocol version. */ static inline mbedtls_ssl_protocol_version mbedtls_ssl_get_version_number( const mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(tls_version); } /** * \brief Return the current TLS version * * \param ssl SSL context * * \return a string containing the TLS version */ const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl); /** * \brief Return the (maximum) number of bytes added by the record * layer: header + encryption/MAC overhead (inc. padding) * * \param ssl SSL context * * \return Current maximum record expansion in bytes */ int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl); /** * \brief Return the current maximum outgoing record payload in bytes. * * \note The logic to determine the maximum outgoing record payload is * version-specific. It takes into account various factors, such as * the mbedtls_config.h setting \c MBEDTLS_SSL_OUT_CONTENT_LEN, extensions * such as the max fragment length or record size limit extension if * used, and for DTLS the path MTU as configured and current * record expansion. * * \note With DTLS, \c mbedtls_ssl_write() will return an error if * called with a larger length value. * With TLS, \c mbedtls_ssl_write() will fragment the input if * necessary and return the number of bytes written; it is up * to the caller to call \c mbedtls_ssl_write() again in * order to send the remaining bytes if any. * * \sa mbedtls_ssl_get_max_out_record_payload() * \sa mbedtls_ssl_get_record_expansion() * * \param ssl SSL context * * \return Current maximum payload for an outgoing record, * or a negative error code. */ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl); /** * \brief Return the current maximum incoming record payload in bytes. * * \note The logic to determine the maximum incoming record payload is * version-specific. It takes into account various factors, such as * the mbedtls_config.h setting \c MBEDTLS_SSL_IN_CONTENT_LEN, extensions * such as the max fragment length extension or record size limit * extension if used, and the current record expansion. * * \sa mbedtls_ssl_set_mtu() * \sa mbedtls_ssl_get_max_in_record_payload() * \sa mbedtls_ssl_get_record_expansion() * * \param ssl SSL context * * \return Current maximum payload for an incoming record, * or a negative error code. */ int mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl); #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Return the peer certificate from the current connection. * * \param ssl The SSL context to use. This must be initialized and setup. * * \return The current peer certificate, if available. * The returned certificate is owned by the SSL context and * is valid only until the next call to the SSL API. * \return \c NULL if no peer certificate is available. This might * be because the chosen ciphersuite doesn't use CRTs * (PSK-based ciphersuites, for example), or because * #MBEDTLS_SSL_KEEP_PEER_CERTIFICATE has been disabled, * allowing the stack to free the peer's CRT to save memory. * * \note For one-time inspection of the peer's certificate during * the handshake, consider registering an X.509 CRT verification * callback through mbedtls_ssl_conf_verify() instead of calling * this function. Using mbedtls_ssl_conf_verify() also comes at * the benefit of allowing you to influence the verification * process, for example by masking expected and tolerated * verification failures. * * \warning You must not use the pointer returned by this function * after any further call to the SSL API, including * mbedtls_ssl_read() and mbedtls_ssl_write(); this is * because the pointer might change during renegotiation, * which happens transparently to the user. * If you want to use the certificate across API calls, * you must make a copy. */ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_CLI_C) /** * \brief Export a session in order to resume it later. * * \param ssl The SSL context representing the connection for which to * to export a session structure for later resumption. * \param session The target structure in which to store the exported session. * This must have been initialized with mbedtls_ssl_session_init() * but otherwise be unused. * * \note This function can handle a variety of mechanisms for session * resumption: For TLS 1.2, both session ID-based resumption and * ticket-based resumption will be considered. For TLS 1.3, * sessions equate to tickets, and if session tickets are * enabled (see #MBEDTLS_SSL_SESSION_TICKETS configuration * option), this function exports the last received ticket and * the exported session may be used to resume the TLS 1.3 * session. If session tickets are disabled, exported sessions * cannot be used to resume a TLS 1.3 session. * * \return \c 0 if successful. In this case, \p session can be used for * session resumption by passing it to mbedtls_ssl_set_session(), * and serialized for storage via mbedtls_ssl_session_save(). * \return Another negative error code on other kinds of failure. * * \sa mbedtls_ssl_set_session() * \sa mbedtls_ssl_session_save() */ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session); #endif /* MBEDTLS_SSL_CLI_C */ /** * \brief Perform the SSL handshake * * \param ssl SSL context * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE * if the handshake is incomplete and waiting for data to * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous * operation is in progress (see * mbedtls_ssl_conf_async_private_cb()) - in this case you * must call this function again when the operation is ready. * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic * operation is in progress (see mbedtls_ecp_set_max_ops()) - * in this case you must call this function again to complete * the handshake when you're done attending other tasks. * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use * and the client did not demonstrate reachability yet - in * this case you must stop using the context (see below). * \return #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3 * NewSessionTicket message has been received. See the * documentation of mbedtls_ssl_read() for more information * about this error code. * \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as * defined in RFC 8446 (TLS 1.3 specification), has been * received as part of the handshake. This is server specific * and may occur only if the early data feature has been * enabled on server (see mbedtls_ssl_conf_early_data() * documentation). You must call mbedtls_ssl_read_early_data() * to read the early data before resuming the handshake. * \return Another SSL error code - in this case you must stop using * the context (see below). * * \warning If this function returns something other than * \c 0, * #MBEDTLS_ERR_SSL_WANT_READ, * #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or * #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, * you must stop using the SSL context for reading or writing, * and either free it or call \c mbedtls_ssl_session_reset() * on it before re-using it for a new connection; the current * connection must be closed. * * \note If DTLS is in use, then you may choose to handle * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging * purposes, as it is an expected return value rather than an * actual error, but you still need to reset/free the context. * * \note Remarks regarding event-driven DTLS: * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram * from the underlying transport layer is currently being processed, * and it is safe to idle until the timer or the underlying transport * signal a new event. This is not true for a successful handshake, * in which case the datagram of the underlying transport that is * currently being processed might or might not contain further * DTLS records. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * Otherwise, the handshake may call psa_crypto_init() * if a negotiation involving TLS 1.3 takes place (this may * be the case even if TLS 1.3 is offered but eventually * not selected). */ int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl); /** * \brief After calling mbedtls_ssl_handshake() to start the SSL * handshake you can call this function to check whether the * handshake is over for a given SSL context. This function * should be also used to determine when to stop calling * mbedtls_handshake_step() for that context. * * \param ssl SSL context * * \return \c 1 if handshake is over, \c 0 if it is still ongoing. */ static inline int mbedtls_ssl_is_handshake_over(mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(state) >= MBEDTLS_SSL_HANDSHAKE_OVER; } /** * \brief Perform a single step of the SSL handshake * * \note The state of the context (ssl->state) will be at * the next state after this function returns \c 0. Do not * call this function if mbedtls_ssl_is_handshake_over() * returns \c 1. * * \warning Whilst in the past you may have used direct access to the * context state (ssl->state) in order to ascertain when to * stop calling this function and although you can still do * so with something like ssl->MBEDTLS_PRIVATE(state) or by * defining MBEDTLS_ALLOW_PRIVATE_ACCESS, this is now * considered deprecated and could be broken in any future * release. If you still find you have good reason for such * direct access, then please do contact the team to explain * this (raise an issue or post to the mailing list), so that * we can add a solution to your problem that will be * guaranteed to work in the future. * * \param ssl SSL context * * \return See mbedtls_ssl_handshake(). * * \warning If this function returns something other than \c 0, * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or * #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, you must stop using * the SSL context for reading or writing, and either free it * or call \c mbedtls_ssl_session_reset() on it before * re-using it for a new connection; the current connection * must be closed. */ int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_RENEGOTIATION) /** * \brief Initiate an SSL renegotiation on the running connection. * Client: perform the renegotiation right now. * Server: request renegotiation, which will be performed * during the next call to mbedtls_ssl_read() if honored by * client. * * \param ssl SSL context * * \return 0 if successful, or any mbedtls_ssl_handshake() return * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't * happen during a renegotiation. * * \warning If this function returns something other than \c 0, * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using * the SSL context for reading or writing, and either free it * or call \c mbedtls_ssl_session_reset() on it before * re-using it for a new connection; the current connection * must be closed. * */ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** * \brief Read at most 'len' application data bytes * * \param ssl SSL context * \param buf buffer that will hold the data * \param len maximum number of bytes to read * * \return The (positive) number of bytes read if successful. * \return \c 0 if the read end of the underlying transport was closed * without sending a CloseNotify beforehand, which might happen * because of various reasons (internal error of an underlying * stack, non-conformant peer not sending a CloseNotify and * such) - in this case you must stop using the context * (see below). * \return #MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY if the underlying * transport is still functional, but the peer has * acknowledged to not send anything anymore. * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE * if the handshake is incomplete and waiting for data to * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous * operation is in progress (see * mbedtls_ssl_conf_async_private_cb()) - in this case you * must call this function again when the operation is ready. * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic * operation is in progress (see mbedtls_ecp_set_max_ops()) - * in this case you must call this function again to complete * the handshake when you're done attending other tasks. * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server * side of a DTLS connection and the client is initiating a * new connection using the same source port. See below. * \return #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3 * NewSessionTicket message has been received. * This error code is only returned on the client side. It is * only returned if handling of TLS 1.3 NewSessionTicket * messages has been enabled through * mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(). * This error code indicates that a TLS 1.3 NewSessionTicket * message has been received and parsed successfully by the * client. The ticket data can be retrieved from the SSL * context by calling mbedtls_ssl_get_session(). It remains * available until the next call to mbedtls_ssl_read(). * \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as * defined in RFC 8446 (TLS 1.3 specification), has been * received as part of the handshake. This is server specific * and may occur only if the early data feature has been * enabled on server (see mbedtls_ssl_conf_early_data() * documentation). You must call mbedtls_ssl_read_early_data() * to read the early data before resuming the handshake. * \return Another SSL error code - in this case you must stop using * the context (see below). * * \warning If this function returns something other than * a positive value, * #MBEDTLS_ERR_SSL_WANT_READ, * #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT or * #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, * you must stop using the SSL context for reading or writing, * and either free it or call \c mbedtls_ssl_session_reset() * on it before re-using it for a new connection; the current * connection must be closed. * * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT * (which can only happen server-side), it means that a client * is initiating a new connection using the same source port. * You can either treat that as a connection close and wait * for the client to resend a ClientHello, or directly * continue with \c mbedtls_ssl_handshake() with the same * context (as it has been reset internally). Either way, you * must make sure this is seen by the application as a new * connection: application state, if any, should be reset, and * most importantly the identity of the client must be checked * again. WARNING: not validating the identity of the client * again, or not transmitting the new identity to the * application layer, would allow authentication bypass! * * \note Remarks regarding event-driven DTLS: * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram * from the underlying transport layer is currently being processed, * and it is safe to idle until the timer or the underlying transport * signal a new event. * - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was * initially available on the underlying transport, as this data may have * been only e.g. duplicated messages or a renegotiation request. * Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even * when reacting to an incoming-data event from the underlying transport. * - On success, the datagram of the underlying transport that is currently * being processed may contain further DTLS records. You should call * \c mbedtls_ssl_check_pending to check for remaining records. * */ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); /** * \brief Try to write exactly 'len' application data bytes * * \warning This function will do partial writes in some cases. If the * return value is non-negative but less than length, the * function must be called again with updated arguments: * buf + ret, len - ret (if ret is the return value) until * it returns a value equal to the last 'len' argument. * * \param ssl SSL context * \param buf buffer holding the data * \param len how many bytes must be written * * \return The (non-negative) number of bytes actually written if * successful (may be less than \p len). * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE * if the handshake is incomplete and waiting for data to * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous * operation is in progress (see * mbedtls_ssl_conf_async_private_cb()) - in this case you * must call this function again when the operation is ready. * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic * operation is in progress (see mbedtls_ecp_set_max_ops()) - * in this case you must call this function again to complete * the handshake when you're done attending other tasks. * \return #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3 * NewSessionTicket message has been received. See the * documentation of mbedtls_ssl_read() for more information * about this error code. * \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as * defined in RFC 8446 (TLS 1.3 specification), has been * received as part of the handshake. This is server specific * and may occur only if the early data feature has been * enabled on server (see mbedtls_ssl_conf_early_data() * documentation). You must call mbedtls_ssl_read_early_data() * to read the early data before resuming the handshake. * \return Another SSL error code - in this case you must stop using * the context (see below). * * \warning If this function returns something other than * a non-negative value, * #MBEDTLS_ERR_SSL_WANT_READ, * #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or * #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, * you must stop using the SSL context for reading or writing, * and either free it or call \c mbedtls_ssl_session_reset() * on it before re-using it for a new connection; the current * connection must be closed. * * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, * it must be called later with the *same* arguments, * until it returns a value greater than or equal to 0. When * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be * some partial data in the output buffer, however this is not * yet sent. * * \note If the requested length is greater than the maximum * fragment length (either the built-in limit or the one set * or negotiated with the peer), then: * - with TLS, less bytes than requested are written. * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. * \c mbedtls_ssl_get_max_out_record_payload() may be used to * query the active maximum fragment length. * * \note Attempting to write 0 bytes will result in an empty TLS * application record being sent. */ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len); /** * \brief Send an alert message * * \param ssl SSL context * \param level The alert level of the message * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) * \param message The alert message (SSL_ALERT_MSG_*) * * \return 0 if successful, or a specific SSL error code. * * \note If this function returns something other than 0 or * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using * the SSL context for reading or writing, and either free it or * call \c mbedtls_ssl_session_reset() on it before re-using it * for a new connection; the current connection must be closed. */ int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, unsigned char level, unsigned char message); /** * \brief Notify the peer that the connection is being closed * * \param ssl SSL context * * \return 0 if successful, or a specific SSL error code. * * \note If this function returns something other than 0 or * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using * the SSL context for reading or writing, and either free it or * call \c mbedtls_ssl_session_reset() on it before re-using it * for a new connection; the current connection must be closed. */ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_EARLY_DATA) #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Read at most 'len' bytes of early data * * \note This API is server specific. * * \warning Early data is defined in the TLS 1.3 specification, RFC 8446. * IMPORTANT NOTE from section 2.3 of the specification: * * The security properties for 0-RTT data are weaker than * those for other kinds of TLS data. Specifically: * - This data is not forward secret, as it is encrypted * solely under keys derived using the offered PSK. * - There are no guarantees of non-replay between connections. * Protection against replay for ordinary TLS 1.3 1-RTT data * is provided via the server's Random value, but 0-RTT data * does not depend on the ServerHello and therefore has * weaker guarantees. This is especially relevant if the * data is authenticated either with TLS client * authentication or inside the application protocol. The * same warnings apply to any use of the * early_exporter_master_secret. * * \warning Mbed TLS does not implement any of the anti-replay defenses * defined in section 8 of the TLS 1.3 specification: * single-use of tickets or ClientHello recording within a * given time window. * * \note This function is used in conjunction with * mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), * mbedtls_ssl_read() and mbedtls_ssl_write() to read early * data when these functions return * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA. * * \param ssl SSL context, it must have been initialized and set up. * \param buf buffer that will hold the data * \param len maximum number of bytes to read * * \return The (positive) number of bytes read if successful. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. * \return #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA if it is not * possible to read early data for the SSL context \p ssl. Note * that this function is intended to be called for an SSL * context \p ssl only after a call to mbedtls_ssl_handshake(), * mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or * mbedtls_ssl_write() for \p ssl that has returned * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA. */ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) /** * \brief Try to write exactly 'len' application data bytes while * performing the handshake (early data). * * \warning Early data is defined in the TLS 1.3 specification, RFC 8446. * IMPORTANT NOTE from section 2.3 of the specification: * * The security properties for 0-RTT data are weaker than * those for other kinds of TLS data. Specifically: * - This data is not forward secret, as it is encrypted * solely under keys derived using the offered PSK. * - There are no guarantees of non-replay between connections. * Protection against replay for ordinary TLS 1.3 1-RTT data * is provided via the server's Random value, but 0-RTT data * does not depend on the ServerHello and therefore has * weaker guarantees. This is especially relevant if the * data is authenticated either with TLS client * authentication or inside the application protocol. The * same warnings apply to any use of the * early_exporter_master_secret. * * \note This function behaves mainly as mbedtls_ssl_write(). The * specification of mbedtls_ssl_write() relevant to TLS 1.3 * (thus not the parts specific to (D)TLS1.2) applies to this * function and the present documentation is mainly restricted * to the differences with mbedtls_ssl_write(). One noticeable * difference though is that mbedtls_ssl_write() aims to * complete the handshake before to write application data * while mbedtls_ssl_write_early() aims to drive the handshake * just past the point where it is not possible to send early * data anymore. * * \param ssl SSL context * \param buf buffer holding the data * \param len how many bytes must be written * * \return The (non-negative) number of bytes actually written if * successful (may be less than \p len). * * \return One additional specific error code compared to * mbedtls_ssl_write(): * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA. * * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it * is not possible to write early data for the SSL context * \p ssl. * * It may have been possible and it is not possible * anymore because the client received the server Finished * message, the server rejected early data or the maximum * number of allowed early data for the PSK in use has been * reached. * * It may never have been possible and will never be possible * for the SSL context \p ssl because the use of early data * is disabled for that context or more generally the context * is not suitably configured to enable early data or the first * call to the function was done while the handshake was * already completed. * * It is not possible to write early data for the SSL context * \p ssl and any subsequent call to this API will return this * error code. But this does not preclude for using it with * mbedtls_ssl_write(), mbedtls_ssl_read() or * mbedtls_ssl_handshake() and the handshake can be * completed by calling one of these APIs. * * \note This function may write early data only if the SSL context * has been configured for the handshake with a PSK for which * early data is allowed. * * \note To maximize the number of early data that can be written in * the course of the handshake, it is expected that this * function starts the handshake for the SSL context \p ssl. * But this is not mandatory. * * \note This function does not provide any information on whether * the server has accepted or will accept early data or not. * When it returns a positive value, it just means that it * has written early data to the server. To know whether the * server has accepted early data or not, you should call * mbedtls_ssl_get_early_data_status() with the handshake * completed. */ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len); /** * \brief Get the status of the negotiation of the use of early data. * * \param ssl The SSL context to query * * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called * from the server-side. * * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called * prior to completion of the handshake. * * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED if the client * has not indicated the use of early data to the server. * * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has * indicated the use of early data and the server has accepted * it. * * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED if the client has * indicated the use of early data but the server has rejected * it. In this situation, the client may want to re-send the * early data it may have tried to send by calling * mbedtls_ssl_write_early_data() as ordinary post-handshake * application data by calling mbedtls_ssl_write(). * */ int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_CLI_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ /** * \brief Free referenced items in an SSL context and clear memory * * \param ssl SSL context */ void mbedtls_ssl_free(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) /** * \brief Save an active connection as serialized data in a buffer. * This allows the freeing or re-using of the SSL context * while still picking up the connection later in a way that * it entirely transparent to the peer. * * \see mbedtls_ssl_context_load() * * \note The serialized data only contains the data that is * necessary to resume the connection: negotiated protocol * options, session identifier, keys, etc. * Loading a saved SSL context does not restore settings and * state related to how the application accesses the context, * such as configured callback functions, user data, pending * incoming or outgoing data, etc. * * \note This feature is currently only available under certain * conditions, see the documentation of the return value * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. * * \note When this function succeeds, it calls * mbedtls_ssl_session_reset() on \p ssl which as a result is * no longer associated with the connection that has been * serialized. This avoids creating copies of the connection * state. You're then free to either re-use the context * structure for a different connection, or call * mbedtls_ssl_free() on it. See the documentation of * mbedtls_ssl_session_reset() for more details. * * \param ssl The SSL context to save. On success, it is no longer * associated with the connection that has been serialized. * \param buf The buffer to write the serialized data to. It must be a * writeable buffer of at least \p buf_len bytes, or may be \c * NULL if \p buf_len is \c 0. * \param buf_len The number of bytes available for writing in \p buf. * \param olen The size in bytes of the data that has been or would have * been written. It must point to a valid \c size_t. * * \note \p olen is updated to the correct value regardless of * whether \p buf_len was large enough. This makes it possible * to determine the necessary size by calling this function * with \p buf set to \c NULL and \p buf_len to \c 0. However, * the value of \p olen is only guaranteed to be correct when * the function returns #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL or * \c 0. If the return value is different, then the value of * \p olen is undefined. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed * while resetting the context. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in * progress, or there is pending data for reading or sending, * or the connection does not use DTLS 1.2 with an AEAD * ciphersuite, or renegotiation is enabled. */ int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl, unsigned char *buf, size_t buf_len, size_t *olen); /** * \brief Load serialized connection data to an SSL context. * * \see mbedtls_ssl_context_save() * * \warning The same serialized data must never be loaded into more * that one context. In order to ensure that, after * successfully loading serialized data to an SSL context, you * should immediately destroy or invalidate all copies of the * serialized data that was loaded. Loading the same data in * more than one context would cause severe security failures * including but not limited to loss of confidentiality. * * \note Before calling this function, the SSL context must be * prepared in one of the two following ways. The first way is * to take a context freshly initialised with * mbedtls_ssl_init() and call mbedtls_ssl_setup() on it with * the same ::mbedtls_ssl_config structure that was used in * the original connection. The second way is to * call mbedtls_ssl_session_reset() on a context that was * previously prepared as above but used in the meantime. * Either way, you must not use the context to perform a * handshake between calling mbedtls_ssl_setup() or * mbedtls_ssl_session_reset() and calling this function. You * may however call other setter functions in that time frame * as indicated in the note below. * * \note Before or after calling this function successfully, you * also need to configure some connection-specific callbacks * and settings before you can use the connection again * (unless they were already set before calling * mbedtls_ssl_session_reset() and the values are suitable for * the present connection). Specifically, you want to call * at least mbedtls_ssl_set_bio(), * mbedtls_ssl_set_timer_cb(), and * mbedtls_ssl_set_user_data_n() or * mbedtls_ssl_set_user_data_p() if they were set originally. * All other SSL setter functions * are not necessary to call, either because they're only used * in handshakes, or because the setting is already saved. You * might choose to call them anyway, for example in order to * share code between the cases of establishing a new * connection and the case of loading an already-established * connection. * * \note If you have new information about the path MTU, you want to * call mbedtls_ssl_set_mtu() after calling this function, as * otherwise this function would overwrite your * newly-configured value with the value that was active when * the context was saved. * * \note When this function returns an error code, it calls * mbedtls_ssl_free() on \p ssl. In this case, you need to * prepare the context with the usual sequence starting with a * call to mbedtls_ssl_init() if you want to use it again. * * \param ssl The SSL context structure to be populated. It must have * been prepared as described in the note above. * \param buf The buffer holding the serialized connection data. It must * be a readable buffer of at least \p len bytes. * \param len The size of the serialized data in bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data * comes from a different Mbed TLS version or build. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. */ int mbedtls_ssl_context_load(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len); #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /** * \brief Initialize an SSL configuration context * Just makes the context ready for * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). * * \note You need to call mbedtls_ssl_config_defaults() unless you * manually set all of the relevant fields yourself. * * \param conf SSL configuration context */ void mbedtls_ssl_config_init(mbedtls_ssl_config *conf); /** * \brief Load reasonable default SSL configuration values. * (You need to call mbedtls_ssl_config_init() first.) * * \param conf SSL configuration context * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS * \param preset a MBEDTLS_SSL_PRESET_XXX value * * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. * * \return 0 if successful, or * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. */ int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf, int endpoint, int transport, int preset); /** * \brief Free an SSL configuration context * * \param conf SSL configuration context */ void mbedtls_ssl_config_free(mbedtls_ssl_config *conf); /** * \brief Initialize SSL session structure * * \param session SSL session */ void mbedtls_ssl_session_init(mbedtls_ssl_session *session); /** * \brief Free referenced items in an SSL session including the * peer certificate and clear memory * * \note A session object can be freed even if the SSL context * that was used to retrieve the session is still in use. * * \param session SSL session */ void mbedtls_ssl_session_free(mbedtls_ssl_session *session); /** * \brief TLS-PRF function for key derivation. * * \param prf The tls_prf type function type to be used. * \param secret Secret for the key derivation function. * \param slen Length of the secret. * \param label String label for the key derivation function, * terminated with null character. * \param random Random bytes. * \param rlen Length of the random bytes buffer. * \param dstbuf The buffer holding the derived key. * \param dlen Length of the output buffer. * * \return 0 on success. An SSL specific error on failure. */ int mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf, const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); #ifdef __cplusplus } #endif #endif /* ssl.h */ webfakes/src/mbedtls/include/mbedtls/camellia.h0000644000176200001440000003210014740737024021263 0ustar liggesusers/** * \file camellia.h * * \brief Camellia block cipher */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CAMELLIA_H #define MBEDTLS_CAMELLIA_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #include "mbedtls/platform_util.h" #define MBEDTLS_CAMELLIA_ENCRYPT 1 #define MBEDTLS_CAMELLIA_DECRYPT 0 /** Bad input data. */ #define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /** Invalid data input length. */ #define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_CAMELLIA_ALT) // Regular implementation // /** * \brief CAMELLIA context structure */ typedef struct mbedtls_camellia_context { int MBEDTLS_PRIVATE(nr); /*!< number of rounds */ uint32_t MBEDTLS_PRIVATE(rk)[68]; /*!< CAMELLIA round keys */ } mbedtls_camellia_context; #else /* MBEDTLS_CAMELLIA_ALT */ #include "camellia_alt.h" #endif /* MBEDTLS_CAMELLIA_ALT */ /** * \brief Initialize a CAMELLIA context. * * \param ctx The CAMELLIA context to be initialized. * This must not be \c NULL. */ void mbedtls_camellia_init(mbedtls_camellia_context *ctx); /** * \brief Clear a CAMELLIA context. * * \param ctx The CAMELLIA context to be cleared. This may be \c NULL, * in which case this function returns immediately. If it is not * \c NULL, it must be initialized. */ void mbedtls_camellia_free(mbedtls_camellia_context *ctx); /** * \brief Perform a CAMELLIA key schedule operation for encryption. * * \param ctx The CAMELLIA context to use. This must be initialized. * \param key The encryption key to use. This must be a readable buffer * of size \p keybits Bits. * \param keybits The length of \p key in Bits. This must be either \c 128, * \c 192 or \c 256. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Perform a CAMELLIA key schedule operation for decryption. * * \param ctx The CAMELLIA context to use. This must be initialized. * \param key The decryption key. This must be a readable buffer * of size \p keybits Bits. * \param keybits The length of \p key in Bits. This must be either \c 128, * \c 192 or \c 256. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. * * \param ctx The CAMELLIA context to use. This must be initialized * and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * \param input The input block. This must be a readable buffer * of size \c 16 Bytes. * \param output The output block. This must be a writable buffer * of size \c 16 Bytes. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If on the other hand you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * \param ctx The CAMELLIA context to use. This must be initialized * and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * \param length The length in Bytes of the input data \p input. * This must be a multiple of \c 16 Bytes. * \param iv The initialization vector. This must be a read/write buffer * of length \c 16 Bytes. It is updated to allow streaming * use as explained above. * \param input The buffer holding the input data. This must point to a * readable buffer of length \p length Bytes. * \param output The buffer holding the output data. This must point to a * writable buffer of length \p length Bytes. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /** * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption * operation. * * \note Due to the nature of CFB mode, you should use the same * key for both encryption and decryption. In particular, calls * to this function should be preceded by a key-schedule via * mbedtls_camellia_setkey_enc() regardless of whether \p mode * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If on the other hand you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * \param ctx The CAMELLIA context to use. This must be initialized * and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * \param length The length of the input data \p input. Any value is allowed. * \param iv_off The current offset in the IV. This must be smaller * than \c 16 Bytes. It is updated after this call to allow * the aforementioned streaming usage. * \param iv The initialization vector. This must be a read/write buffer * of length \c 16 Bytes. It is updated after this call to * allow the aforementioned streaming usage. * \param input The buffer holding the input data. This must be a readable * buffer of size \p length Bytes. * \param output The buffer to hold the output data. This must be a writable * buffer of length \p length Bytes. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /** * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation. * * *note Due to the nature of CTR mode, you should use the same * key for both encryption and decryption. In particular, calls * to this function should be preceded by a key-schedule via * mbedtls_camellia_setkey_enc() regardless of whether the mode * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * * \warning You must never reuse a nonce value with the same key. Doing so * would void the encryption for the two messages encrypted with * the same nonce and key. * * There are two common strategies for managing nonces with CTR: * * 1. You can handle everything as a single message processed over * successive calls to this function. In that case, you want to * set \p nonce_counter and \p nc_off to 0 for the first call, and * then preserve the values of \p nonce_counter, \p nc_off and \p * stream_block across calls to this function as they will be * updated by this function. * * With this strategy, you must not encrypt more than 2**128 * blocks of data with the same key. * * 2. You can encrypt separate messages by dividing the \p * nonce_counter buffer in two areas: the first one used for a * per-message nonce, handled by yourself, and the second one * updated by this function internally. * * For example, you might reserve the first \c 12 Bytes for the * per-message nonce, and the last \c 4 Bytes for internal use. * In that case, before calling this function on a new message you * need to set the first \c 12 Bytes of \p nonce_counter to your * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0 * (which will cause \p stream_block to be ignored). That way, you * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks * each with the same key. * * The per-message nonce (or information sufficient to reconstruct * it) needs to be communicated with the ciphertext and must be * unique. The recommended way to ensure uniqueness is to use a * message counter. An alternative is to generate random nonces, * but this limits the number of messages that can be securely * encrypted: for example, with 96-bit random nonces, you should * not encrypt more than 2**32 messages with the same key. * * Note that for both strategies, sizes are measured in blocks and * that a CAMELLIA block is \c 16 Bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its * content must not be written to insecure storage and should be * securely discarded as soon as it's no longer needed. * * \param ctx The CAMELLIA context to use. This must be initialized * and bound to a key. * \param length The length of the input data \p input in Bytes. * Any value is allowed. * \param nc_off The offset in the current \p stream_block (for resuming * within current cipher stream). The offset pointer to * should be \c 0 at the start of a stream. It is updated * at the end of this call. * \param nonce_counter The 128-bit nonce and counter. This must be a read/write * buffer of length \c 16 Bytes. * \param stream_block The saved stream-block for resuming. This must be a * read/write buffer of length \c 16 Bytes. * \param input The input data stream. This must be a readable buffer of * size \p length Bytes. * \param output The output data stream. This must be a writable buffer * of size \p length Bytes. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_crypt_ctr(mbedtls_camellia_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_camellia_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* camellia.h */ webfakes/src/mbedtls/include/mbedtls/oid.h0000644000176200001440000011641414740737024020302 0ustar liggesusers/** * \file oid.h * * \brief Object Identifier (OID) database */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_OID_H #define MBEDTLS_OID_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #include "mbedtls/pk.h" #include #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif #include "mbedtls/md.h" /** OID is not found. */ #define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /** output buffer is too small */ #define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /* This is for the benefit of X.509, but defined here in order to avoid * having a "backwards" include of x.509.h here */ /* * X.509 extension types (internal, arbitrary values for bitsets) */ #define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) #define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) #define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) #define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) #define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) #define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) #define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) #define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) #define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) #define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) #define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) #define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) #define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) #define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) #define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) #define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) /* * Maximum number of OID components allowed */ #define MBEDTLS_OID_MAX_COMPONENTS 128 /* * Top level OID tuples */ #define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ #define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ #define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ #define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ /* * ISO Member bodies OID parts */ #define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ #define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ #define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ #define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ #define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ MBEDTLS_OID_ORG_ANSI_X9_62 /* * ISO Identified organization OID parts */ #define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ #define MBEDTLS_OID_ORG_OIW "\x0e" #define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" #define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" #define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" #define MBEDTLS_OID_ORG_THAWTE "\x65" /* thawte(101) */ #define MBEDTLS_OID_THAWTE MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_THAWTE #define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ #define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_CERTICOM #define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ #define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_TELETRUST /* * ISO ITU OID parts */ #define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ #define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US \ MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ #define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ #define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ #define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ #define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ /* ISO arc for standard certificate and CRL extensions */ #define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ #define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ /** * Private Internet Extensions * { iso(1) identified-organization(3) dod(6) internet(1) * security(5) mechanisms(5) pkix(7) } */ #define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD \ "\x01" #define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" /* * Arc for standard naming attributes */ #define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ #define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ #define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ #define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ #define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ #define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ #define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ #define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ #define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ #define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ #define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ #define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ #define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ #define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ #define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ #define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */ #define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ #define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ #define MBEDTLS_OID_UID "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) uid(1)} */ #define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ /* * OIDs for standard certificate extensions */ #define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ #define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ #define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ #define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ #define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ #define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ #define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ #define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ #define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ #define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ #define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ #define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ #define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ #define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ #define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ /* * Certificate policies */ #define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */ /* * Netscape certificate extensions */ #define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" #define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" #define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" #define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" #define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" #define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" #define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" #define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" #define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" #define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" #define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" /* * OIDs for CRL extensions */ #define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" #define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ /* * X.509 v3 Extended key usage OIDs */ #define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ #define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ #define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ #define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ #define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ #define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ #define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ #define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ /** * Wi-SUN Alliance Field Area Network * { iso(1) identified-organization(3) dod(6) internet(1) * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) } */ #define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" #define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ #define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */ /* * PKCS definition OIDs */ #define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ #define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ #define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ #define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } */ #define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ #define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ /* * PKCS#1 OIDs */ #define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ #define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ #define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ #define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ #define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ #define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ #define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ #define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" #define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ /* RFC 4055 */ #define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ #define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ /* * Digest algorithms */ #define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ #define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ #define MBEDTLS_OID_DIGEST_ALG_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x07" /**< id-sha3-224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-224(7) } */ #define MBEDTLS_OID_DIGEST_ALG_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x08" /**< id-sha3-256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-256(8) } */ #define MBEDTLS_OID_DIGEST_ALG_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x09" /**< id-sha3-384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-384(9) } */ #define MBEDTLS_OID_DIGEST_ALG_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x0a" /**< id-sha3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-512(10) } */ #define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ #define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ #define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ #define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ #define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ #define MBEDTLS_OID_HMAC_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x0d" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-224(13) } */ #define MBEDTLS_OID_HMAC_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x0e" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-256(14) } */ #define MBEDTLS_OID_HMAC_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x0f" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-384(15) } */ #define MBEDTLS_OID_HMAC_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x10" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-512(16) } */ #define MBEDTLS_OID_HMAC_RIPEMD160 MBEDTLS_OID_INTERNET "\x05\x05\x08\x01\x04" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= {iso(1) iso-identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1) hmacRIPEMD160(4)} */ /* * Encryption algorithms, * the following standardized object identifiers are specified at * https://datatracker.ietf.org/doc/html/rfc8018#appendix-C. */ #define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ #define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ #define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ #define MBEDTLS_OID_AES_128_CBC MBEDTLS_OID_AES "\x02" /** aes128-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes128-CBC-PAD(2) } */ #define MBEDTLS_OID_AES_192_CBC MBEDTLS_OID_AES "\x16" /** aes192-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes192-CBC-PAD(22) } */ #define MBEDTLS_OID_AES_256_CBC MBEDTLS_OID_AES "\x2a" /** aes256-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes256-CBC-PAD(42) } */ /* * Key Wrapping algorithms */ /* * RFC 5649 */ #define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ #define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ #define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ #define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ #define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ #define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ /* * PKCS#5 OIDs */ #define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ #define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ #define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ /* * PKCS#5 PBES1 algorithms */ #define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ #define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ #define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ #define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ /* * PKCS#7 OIDs */ #define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01" /**< Content type is Data OBJECT IDENTIFIER ::= {pkcs-7 1} */ #define MBEDTLS_OID_PKCS7_SIGNED_DATA MBEDTLS_OID_PKCS7 "\x02" /**< Content type is Signed Data OBJECT IDENTIFIER ::= {pkcs-7 2} */ #define MBEDTLS_OID_PKCS7_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x03" /**< Content type is Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 3} */ #define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x04" /**< Content type is Signed and Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 4} */ #define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05" /**< Content type is Digested Data OBJECT IDENTIFIER ::= {pkcs-7 5} */ #define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" /**< Content type is Encrypted Data OBJECT IDENTIFIER ::= {pkcs-7 6} */ /* * PKCS#8 OIDs */ #define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ /* * PKCS#12 PBE OIDs */ #define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ /* * EC key algorithms from RFC 5480 */ /* id-ecPublicKey OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ #define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" /* id-ecDH OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) * schemes(1) ecdh(12) } */ #define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" /* * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 */ /* secp192r1 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ #define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" /* secp224r1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ #define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" /* secp256r1 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ #define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" /* secp384r1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ #define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" /* secp521r1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ #define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" /* secp192k1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ #define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" /* secp224k1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ #define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" /* secp256k1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ #define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" /* RFC 5639 4.1 * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) * identified-organization(3) teletrust(36) algorithm(3) signature- * algorithm(3) ecSign(2) 8} * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ #define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" /* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ #define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" /* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ #define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" /* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ #define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" /* * SEC1 C.1 * * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} */ #define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" #define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" /* * ECDSA signature identifiers, from RFC 5480 */ #define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ #define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ /* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ #define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" /* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) * ecdsa-with-SHA2(3) 1 } */ #define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" /* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) * ecdsa-with-SHA2(3) 2 } */ #define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" /* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) * ecdsa-with-SHA2(3) 3 } */ #define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" /* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) * ecdsa-with-SHA2(3) 4 } */ #define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" /* * EC key algorithms from RFC 8410 */ #define MBEDTLS_OID_X25519 MBEDTLS_OID_THAWTE "\x6e" /**< id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } */ #define MBEDTLS_OID_X448 MBEDTLS_OID_THAWTE "\x6f" /**< id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 } */ #define MBEDTLS_OID_ED25519 MBEDTLS_OID_THAWTE "\x70" /**< id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } */ #define MBEDTLS_OID_ED448 MBEDTLS_OID_THAWTE "\x71" /**< id-Ed448 OBJECT IDENTIFIER ::= { 1 3 101 113 } */ #ifdef __cplusplus extern "C" { #endif /** * \brief Base OID descriptor structure */ typedef struct mbedtls_oid_descriptor_t { const char *MBEDTLS_PRIVATE(asn1); /*!< OID ASN.1 representation */ size_t MBEDTLS_PRIVATE(asn1_len); /*!< length of asn1 */ #if !defined(MBEDTLS_X509_REMOVE_INFO) const char *MBEDTLS_PRIVATE(name); /*!< official name (e.g. from RFC) */ const char *MBEDTLS_PRIVATE(description); /*!< human friendly description */ #endif } mbedtls_oid_descriptor_t; /** * \brief Translate an ASN.1 OID into its numeric representation * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") * * \param buf buffer to put representation in * \param size size of the buffer * \param oid OID to translate * * \return Length of the string written (excluding final NULL) or * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error */ int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid); /** * \brief Translate a string containing a dotted-decimal * representation of an ASN.1 OID into its encoded form * (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D"). * On success, this function allocates oid->buf from the * heap. It must be freed by the caller using mbedtls_free(). * * \param oid #mbedtls_asn1_buf to populate with the DER-encoded OID * \param oid_str string representation of the OID to parse * \param size length of the OID string, not including any null terminator * * \return 0 if successful * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not * represent a valid OID * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to * allocate oid->buf */ int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size); /** * \brief Translate an X.509 extension OID into local values * * \param oid OID to use * \param ext_type place to store the extension type * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_x509_ext_type(const mbedtls_asn1_buf *oid, int *ext_type); /** * \brief Translate an X.509 attribute type OID into the short name * (e.g. the OID for an X520 Common Name into "CN") * * \param oid OID to use * \param short_name place to store the string pointer * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **short_name); /** * \brief Translate PublicKeyAlgorithm OID into pk_type * * \param oid OID to use * \param pk_alg place to store public key algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg); /** * \brief Translate pk_type into PublicKeyAlgorithm OID * * \param pk_alg Public key type to look for * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg, const char **oid, size_t *olen); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /** * \brief Translate NamedCurve OID into an EC group identifier * * \param oid OID to use * \param grp_id place to store group id * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); /** * \brief Translate EC group identifier into NamedCurve OID * * \param grp_id EC group identifier * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id, const char **oid, size_t *olen); /** * \brief Translate AlgorithmIdentifier OID into an EC group identifier, * for curves that are directly encoded at this level * * \param oid OID to use * \param grp_id place to store group id * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_ec_grp_algid(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); /** * \brief Translate EC group identifier into AlgorithmIdentifier OID, * for curves that are directly encoded at this level * * \param grp_id EC group identifier * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_ec_grp_algid(mbedtls_ecp_group_id grp_id, const char **oid, size_t *olen); #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /** * \brief Translate SignatureAlgorithm OID into md_type and pk_type * * \param oid OID to use * \param md_alg place to store message digest algorithm * \param pk_alg place to store public key algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg); /** * \brief Translate SignatureAlgorithm OID into description * * \param oid OID to use * \param desc place to store string pointer * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf *oid, const char **desc); /** * \brief Translate md_type and pk_type into SignatureAlgorithm OID * * \param md_alg message digest algorithm * \param pk_alg public key algorithm * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, const char **oid, size_t *olen); /** * \brief Translate hmac algorithm OID into md_type * * \param oid OID to use * \param md_hmac place to store message hmac algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac); /** * \brief Translate hash algorithm OID into md_type * * \param oid OID to use * \param md_alg place to store message digest algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg); #if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Translate Extended Key Usage OID into description * * \param oid OID to use * \param desc place to store string pointer * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char **desc); #endif /** * \brief Translate certificate policies OID into description * * \param oid OID to use * \param desc place to store string pointer * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_certificate_policies(const mbedtls_asn1_buf *oid, const char **desc); /** * \brief Translate md_type into hash algorithm OID * * \param md_alg message digest algorithm * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t *olen); #if defined(MBEDTLS_CIPHER_C) /** * \brief Translate encryption algorithm OID into cipher_type * * \param oid OID to use * \param cipher_alg place to store cipher algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg); #if defined(MBEDTLS_PKCS12_C) /** * \brief Translate PKCS#12 PBE algorithm OID into md_type and * cipher_type * * \param oid OID to use * \param md_alg place to store message digest algorithm * \param cipher_alg place to store cipher algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, mbedtls_cipher_type_t *cipher_alg); #endif /* MBEDTLS_PKCS12_C */ #endif /* MBEDTLS_CIPHER_C */ #ifdef __cplusplus } #endif #endif /* oid.h */ webfakes/src/mbedtls/include/mbedtls/cipher.h0000644000176200001440000015003414740737024020775 0ustar liggesusers/** * \file cipher.h * * \brief This file contains an abstraction interface for use with the cipher * primitives provided by the library. It provides a common interface to all of * the available cipher operations. * * \author Adriaan de Jong */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CIPHER_H #define MBEDTLS_CIPHER_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include "mbedtls/platform_util.h" #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) #define MBEDTLS_CIPHER_MODE_AEAD #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) #define MBEDTLS_CIPHER_MODE_WITH_PADDING #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ defined(MBEDTLS_CHACHA20_C) #define MBEDTLS_CIPHER_MODE_STREAM #endif /** The selected feature is not available. */ #define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /** Bad input parameters. */ #define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /** Failed to allocate memory. */ #define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /** Input data contains invalid padding and is rejected. */ #define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /** Decryption of block requires a full block. */ #define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /** Authentication failed (for AEAD modes). */ #define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /** The context is invalid. For example, because it was freed. */ #define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 #define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ #define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ #ifdef __cplusplus extern "C" { #endif /** * \brief Supported cipher types. * * \warning DES/3DES are considered weak ciphers and their use * constitutes a security risk. We recommend considering stronger * ciphers instead. */ typedef enum { MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. \warning DES is considered weak. */ MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ } mbedtls_cipher_id_t; /** * \brief Supported {cipher type, cipher mode} pairs. * * \warning DES/3DES are considered weak ciphers and their use * constitutes a security risk. We recommend considering stronger * ciphers instead. */ typedef enum { MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. \warning DES is considered weak. */ MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. \warning DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, /**< AES cipher with 128-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, /**< AES cipher with 192-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, /**< AES cipher with 256-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, /**< Camellia cipher with 128-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, /**< Camellia cipher with 192-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, /**< Camellia cipher with 256-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, /**< Aria cipher with 128-bit key and CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, /**< Aria cipher with 192-bit key and CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, /**< Aria cipher with 256-bit key and CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */ MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */ MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */ MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */ MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */ MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */ } mbedtls_cipher_type_t; /** Supported cipher modes. */ typedef enum { MBEDTLS_MODE_NONE = 0, /**< None. */ MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ MBEDTLS_MODE_CCM_STAR_NO_TAG, /**< The CCM*-no-tag cipher mode. */ MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */ MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */ } mbedtls_cipher_mode_t; /** Supported cipher padding types. */ typedef enum { MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ } mbedtls_cipher_padding_t; /** Type of operation. */ typedef enum { MBEDTLS_OPERATION_NONE = -1, MBEDTLS_DECRYPT = 0, MBEDTLS_ENCRYPT, } mbedtls_operation_t; enum { /** Undefined key length. */ MBEDTLS_KEY_LENGTH_NONE = 0, /** Key length, in bits (including parity), for DES keys. \warning DES is considered weak. */ MBEDTLS_KEY_LENGTH_DES = 64, /** Key length in bits, including parity, for DES in two-key EDE. \warning 3DES is considered weak. */ MBEDTLS_KEY_LENGTH_DES_EDE = 128, /** Key length in bits, including parity, for DES in three-key EDE. \warning 3DES is considered weak. */ MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, }; /** Maximum length of any IV, in Bytes. */ /* This should ideally be derived automatically from list of ciphers. * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined * in library/ssl_misc.h. */ #define MBEDTLS_MAX_IV_LENGTH 16 /** Maximum block size of any cipher, in Bytes. */ /* This should ideally be derived automatically from list of ciphers. * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined * in library/ssl_misc.h. */ #define MBEDTLS_MAX_BLOCK_LENGTH 16 /** Maximum key length, in Bytes. */ /* This should ideally be derived automatically from list of ciphers. * For now, only check whether XTS is enabled which uses 64 Byte keys, * and use 32 Bytes as an upper bound for the maximum key length otherwise. * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined * in library/ssl_misc.h, which however deliberately ignores the case of XTS * since the latter isn't used in SSL/TLS. */ #if defined(MBEDTLS_CIPHER_MODE_XTS) #define MBEDTLS_MAX_KEY_LENGTH 64 #else #define MBEDTLS_MAX_KEY_LENGTH 32 #endif /* MBEDTLS_CIPHER_MODE_XTS */ /** * Base cipher information (opaque struct). */ typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; /** * CMAC context (opaque struct). */ typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; /** * Cipher information. Allows calling cipher functions * in a generic way. * * \note The library does not support custom cipher info structures, * only built-in structures returned by the functions * mbedtls_cipher_info_from_string(), * mbedtls_cipher_info_from_type(), * mbedtls_cipher_info_from_values(), * mbedtls_cipher_info_from_psa(). * * \note Some fields store a value that has been right-shifted to save * code-size, so should not be used directly. The accessor * functions adjust for this and return the "natural" value. */ typedef struct mbedtls_cipher_info_t { /** Name of the cipher. */ const char *MBEDTLS_PRIVATE(name); /** The block size, in bytes. */ unsigned int MBEDTLS_PRIVATE(block_size) : 5; /** IV or nonce size, in bytes (right shifted by #MBEDTLS_IV_SIZE_SHIFT). * For ciphers that accept variable IV sizes, * this is the recommended size. */ unsigned int MBEDTLS_PRIVATE(iv_size) : 3; /** The cipher key length, in bits (right shifted by #MBEDTLS_KEY_BITLEN_SHIFT). * This is the default length for variable sized ciphers. * Includes parity bits for ciphers like DES. */ unsigned int MBEDTLS_PRIVATE(key_bitlen) : 4; /** The cipher mode (as per mbedtls_cipher_mode_t). * For example, MBEDTLS_MODE_CBC. */ unsigned int MBEDTLS_PRIVATE(mode) : 4; /** Full cipher identifier (as per mbedtls_cipher_type_t). * For example, MBEDTLS_CIPHER_AES_256_CBC. * * This could be 7 bits, but 8 bits retains byte alignment for the * next field, which reduces code size to access that field. */ unsigned int MBEDTLS_PRIVATE(type) : 8; /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the * cipher supports variable IV or variable key sizes, respectively. */ unsigned int MBEDTLS_PRIVATE(flags) : 2; /** Index to LUT for base cipher information and functions. */ unsigned int MBEDTLS_PRIVATE(base_idx) : 5; } mbedtls_cipher_info_t; /* For internal use only. * These are used to more compactly represent the fields above. */ #define MBEDTLS_KEY_BITLEN_SHIFT 6 #define MBEDTLS_IV_SIZE_SHIFT 2 /** * Generic cipher context. */ typedef struct mbedtls_cipher_context_t { /** Information about the associated cipher. */ const mbedtls_cipher_info_t *MBEDTLS_PRIVATE(cipher_info); /** Key length to use. */ int MBEDTLS_PRIVATE(key_bitlen); /** Operation that the key of the context has been * initialized for. */ mbedtls_operation_t MBEDTLS_PRIVATE(operation); #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /** Padding functions to use, if relevant for * the specific cipher mode. */ void(*MBEDTLS_PRIVATE(add_padding))(unsigned char *output, size_t olen, size_t data_len); int(*MBEDTLS_PRIVATE(get_padding))(unsigned char *input, size_t ilen, size_t *data_len); #endif /** Buffer for input that has not been processed yet. */ unsigned char MBEDTLS_PRIVATE(unprocessed_data)[MBEDTLS_MAX_BLOCK_LENGTH]; /** Number of Bytes that have not been processed yet. */ size_t MBEDTLS_PRIVATE(unprocessed_len); /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number * for XTS-mode. */ unsigned char MBEDTLS_PRIVATE(iv)[MBEDTLS_MAX_IV_LENGTH]; /** IV size in Bytes, for ciphers with variable-length IVs. */ size_t MBEDTLS_PRIVATE(iv_size); /** The cipher-specific context. */ void *MBEDTLS_PRIVATE(cipher_ctx); #if defined(MBEDTLS_CMAC_C) /** CMAC-specific context. */ mbedtls_cmac_context_t *MBEDTLS_PRIVATE(cmac_ctx); #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) /** Indicates whether the cipher operations should be performed * by Mbed TLS' own crypto library or an external implementation * of the PSA Crypto API. * This is unset if the cipher context was established through * mbedtls_cipher_setup(), and set if it was established through * mbedtls_cipher_setup_psa(). */ unsigned char MBEDTLS_PRIVATE(psa_enabled); #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ } mbedtls_cipher_context_t; /** * \brief This function retrieves the list of ciphers supported * by the generic cipher module. * * For any cipher identifier in the returned list, you can * obtain the corresponding generic cipher information structure * via mbedtls_cipher_info_from_type(), which can then be used * to prepare a cipher context via mbedtls_cipher_setup(). * * * \return A statically-allocated array of cipher identifiers * of type cipher_type_t. The last entry is zero. */ const int *mbedtls_cipher_list(void); /** * \brief This function retrieves the cipher-information * structure associated with the given cipher name. * * \param cipher_name Name of the cipher to search for. This must not be * \c NULL. * * \return The cipher information structure associated with the * given \p cipher_name. * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(const char *cipher_name); /** * \brief This function retrieves the cipher-information * structure associated with the given cipher type. * * \param cipher_type Type of the cipher to search for. * * \return The cipher information structure associated with the * given \p cipher_type. * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(const mbedtls_cipher_type_t cipher_type); /** * \brief This function retrieves the cipher-information * structure associated with the given cipher ID, * key size and mode. * * \param cipher_id The ID of the cipher to search for. For example, * #MBEDTLS_CIPHER_ID_AES. * \param key_bitlen The length of the key in bits. * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. * * \return The cipher information structure associated with the * given \p cipher_id. * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(const mbedtls_cipher_id_t cipher_id, int key_bitlen, const mbedtls_cipher_mode_t mode); /** * \brief Retrieve the identifier for a cipher info structure. * * \param[in] info The cipher info structure to query. * This may be \c NULL. * * \return The full cipher identifier (\c MBEDTLS_CIPHER_xxx). * \return #MBEDTLS_CIPHER_NONE if \p info is \c NULL. */ static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type( const mbedtls_cipher_info_t *info) { if (info == NULL) { return MBEDTLS_CIPHER_NONE; } else { return (mbedtls_cipher_type_t) info->MBEDTLS_PRIVATE(type); } } /** * \brief Retrieve the operation mode for a cipher info structure. * * \param[in] info The cipher info structure to query. * This may be \c NULL. * * \return The cipher mode (\c MBEDTLS_MODE_xxx). * \return #MBEDTLS_MODE_NONE if \p info is \c NULL. */ static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode( const mbedtls_cipher_info_t *info) { if (info == NULL) { return MBEDTLS_MODE_NONE; } else { return (mbedtls_cipher_mode_t) info->MBEDTLS_PRIVATE(mode); } } /** * \brief Retrieve the key size for a cipher info structure. * * \param[in] info The cipher info structure to query. * This may be \c NULL. * * \return The key length in bits. * For variable-sized ciphers, this is the default length. * For DES, this includes the parity bits. * \return \c 0 if \p info is \c NULL. */ static inline size_t mbedtls_cipher_info_get_key_bitlen( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } else { return ((size_t) info->MBEDTLS_PRIVATE(key_bitlen)) << MBEDTLS_KEY_BITLEN_SHIFT; } } /** * \brief Retrieve the human-readable name for a * cipher info structure. * * \param[in] info The cipher info structure to query. * This may be \c NULL. * * \return The cipher name, which is a human readable string, * with static storage duration. * \return \c NULL if \p info is \c NULL. */ static inline const char *mbedtls_cipher_info_get_name( const mbedtls_cipher_info_t *info) { if (info == NULL) { return NULL; } else { return info->MBEDTLS_PRIVATE(name); } } /** * \brief This function returns the size of the IV or nonce * for the cipher info structure, in bytes. * * \param info The cipher info structure. This may be \c NULL. * * \return The recommended IV size. * \return \c 0 for ciphers not using an IV or a nonce. * \return \c 0 if \p info is \c NULL. */ static inline size_t mbedtls_cipher_info_get_iv_size( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } return ((size_t) info->MBEDTLS_PRIVATE(iv_size)) << MBEDTLS_IV_SIZE_SHIFT; } /** * \brief This function returns the block size of the given * cipher info structure in bytes. * * \param info The cipher info structure. This may be \c NULL. * * \return The block size of the cipher. * \return \c 1 if the cipher is a stream cipher. * \return \c 0 if \p info is \c NULL. */ static inline size_t mbedtls_cipher_info_get_block_size( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } return (size_t) (info->MBEDTLS_PRIVATE(block_size)); } /** * \brief This function returns a non-zero value if the key length for * the given cipher is variable. * * \param info The cipher info structure. This may be \c NULL. * * \return Non-zero if the key length is variable, \c 0 otherwise. * \return \c 0 if the given pointer is \c NULL. */ static inline int mbedtls_cipher_info_has_variable_key_bitlen( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_KEY_LEN; } /** * \brief This function returns a non-zero value if the IV size for * the given cipher is variable. * * \param info The cipher info structure. This may be \c NULL. * * \return Non-zero if the IV size is variable, \c 0 otherwise. * \return \c 0 if the given pointer is \c NULL. */ static inline int mbedtls_cipher_info_has_variable_iv_size( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_IV_LEN; } /** * \brief This function initializes a \p ctx as NONE. * * \param ctx The context to be initialized. This must not be \c NULL. */ void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx); /** * \brief This function frees and clears the cipher-specific * context of \p ctx. Freeing \p ctx itself remains the * responsibility of the caller. * * \param ctx The context to be freed. If this is \c NULL, the * function has no effect, otherwise this must point to an * initialized context. */ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx); /** * \brief This function prepares a cipher context for * use with the given cipher primitive. * * \note After calling this function, you should call * mbedtls_cipher_setkey() and, if the mode uses padding, * mbedtls_cipher_set_padding_mode(), then for each * message to encrypt or decrypt with this key, either: * - mbedtls_cipher_crypt() for one-shot processing with * non-AEAD modes; * - mbedtls_cipher_auth_encrypt_ext() or * mbedtls_cipher_auth_decrypt_ext() for one-shot * processing with AEAD modes or NIST_KW; * - for multi-part processing, see the documentation of * mbedtls_cipher_reset(). * * \param ctx The context to prepare. This must be initialized by * a call to mbedtls_cipher_init() first. * \param cipher_info The cipher to use. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the * cipher-specific context fails. */ int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info); #if defined(MBEDTLS_USE_PSA_CRYPTO) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief This function initializes a cipher context for * PSA-based use with the given cipher primitive. * * \deprecated This function is deprecated and will be removed in a * future version of the library. * Please use psa_aead_xxx() / psa_cipher_xxx() directly * instead. * * \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA. * * \param ctx The context to initialize. May not be \c NULL. * \param cipher_info The cipher to use. * \param taglen For AEAD ciphers, the length in bytes of the * authentication tag to use. Subsequent uses of * mbedtls_cipher_auth_encrypt_ext() or * mbedtls_cipher_auth_decrypt_ext() must provide * the same tag length. * For non-AEAD ciphers, the value must be \c 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the * cipher-specific context fails. */ int MBEDTLS_DEPRECATED mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info, size_t taglen); #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ /** * \brief This function returns the block size of the given cipher * in bytes. * * \param ctx The context of the cipher. * * \return The block size of the underlying cipher. * \return \c 1 if the cipher is a stream cipher. * \return \c 0 if \p ctx has not been initialized. */ static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return 0; } return (unsigned int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size); } /** * \brief This function returns the mode of operation for * the cipher. For example, MBEDTLS_MODE_CBC. * * \param ctx The context of the cipher. This must be initialized. * * \return The mode of operation. * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. */ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_MODE_NONE; } return (mbedtls_cipher_mode_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode); } /** * \brief This function returns the size of the IV or nonce * of the cipher, in Bytes. * * \param ctx The context of the cipher. This must be initialized. * * \return The recommended IV size if no IV has been set. * \return \c 0 for ciphers not using an IV or a nonce. * \return The actual size if an IV has been set. */ static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return 0; } if (ctx->MBEDTLS_PRIVATE(iv_size) != 0) { return (int) ctx->MBEDTLS_PRIVATE(iv_size); } return (int) (((int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size)) << MBEDTLS_IV_SIZE_SHIFT); } /** * \brief This function returns the type of the given cipher. * * \param ctx The context of the cipher. This must be initialized. * * \return The type of the cipher. * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. */ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_CIPHER_NONE; } return (mbedtls_cipher_type_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type); } /** * \brief This function returns the name of the given cipher * as a string. * * \param ctx The context of the cipher. This must be initialized. * * \return The name of the cipher. * \return NULL if \p ctx has not been not initialized. */ static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return 0; } return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(name); } /** * \brief This function returns the key length of the cipher. * * \param ctx The context of the cipher. This must be initialized. * * \return The key length of the cipher in bits. * \return #MBEDTLS_KEY_LENGTH_NONE if \p ctx has not been * initialized. */ static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_KEY_LENGTH_NONE; } return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen) << MBEDTLS_KEY_BITLEN_SHIFT; } /** * \brief This function returns the operation of the given cipher. * * \param ctx The context of the cipher. This must be initialized. * * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. */ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_OPERATION_NONE; } return ctx->MBEDTLS_PRIVATE(operation); } /** * \brief This function sets the key to use with the given context. * * \param ctx The generic cipher context. This must be initialized and * bound to a cipher information structure. * \param key The key to use. This must be a readable buffer of at * least \p key_bitlen Bits. * \param key_bitlen The key length to use, in Bits. * \param operation The operation that the key will be used for: * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *key, int key_bitlen, const mbedtls_operation_t operation); #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /** * \brief This function sets the padding mode, for cipher modes * that use padding. * * * \param ctx The generic cipher context. This must be initialized and * bound to a cipher information structure. * \param mode The padding mode. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE * if the selected padding mode is not supported. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode * does not support padding. */ int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode); #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ /** * \brief This function sets the initialization vector (IV) * or nonce. * * \note Some ciphers do not use IVs nor nonce. For these * ciphers, this function has no effect. * * \note For #MBEDTLS_CIPHER_CHACHA20, the nonce length must * be 12, and the initial counter value is 0. * * \note For #MBEDTLS_CIPHER_CHACHA20_POLY1305, the nonce length * must be 12. * * \param ctx The generic cipher context. This must be initialized and * bound to a cipher information structure. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This * must be a readable buffer of at least \p iv_len Bytes. * \param iv_len The IV length for ciphers with variable-size IV. * This parameter is discarded by ciphers with fixed-size IV. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. */ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len); /** * \brief This function resets the cipher state. * * \note With non-AEAD ciphers, the order of calls for each message * is as follows: * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. * 2. mbedtls_cipher_reset() * 3. mbedtls_cipher_update() one or more times * 4. mbedtls_cipher_finish() * . * This sequence can be repeated to encrypt or decrypt multiple * messages with the same key. * * \note With AEAD ciphers, the order of calls for each message * is as follows: * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. * 2. mbedtls_cipher_reset() * 3. mbedtls_cipher_update_ad() * 4. mbedtls_cipher_update() one or more times * 5. mbedtls_cipher_finish() * 6. mbedtls_cipher_check_tag() (for decryption) or * mbedtls_cipher_write_tag() (for encryption). * . * This sequence can be repeated to encrypt or decrypt multiple * messages with the same key. * * \param ctx The generic cipher context. This must be bound to a key. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. */ int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx); #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function adds additional data for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. * * \param ctx The generic cipher context. This must be initialized. * \param ad The additional data to use. This must be a readable * buffer of at least \p ad_len Bytes. * \param ad_len The length of \p ad in Bytes. * * \return \c 0 on success. * \return A specific error code on failure. */ int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len); #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** * \brief The generic cipher update function. It encrypts or * decrypts using the given cipher context. Writes as * many block-sized blocks of data as possible to output. * Any data that cannot be written immediately is either * added to the next block, or flushed when * mbedtls_cipher_finish() is called. * Exception: For MBEDTLS_MODE_ECB, expects a single block * in size. For example, 16 Bytes for AES. * * \param ctx The generic cipher context. This must be initialized and * bound to a key. * \param input The buffer holding the input data. This must be a * readable buffer of at least \p ilen Bytes. * \param ilen The length of the input data. * \param output The buffer for the output data. This must be able to * hold at least `ilen + block_size`. This must not be the * same buffer as \p input. * \param olen The length of the output data, to be updated with the * actual number of Bytes written. This must not be * \c NULL. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an * unsupported mode for a cipher. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen); /** * \brief The generic cipher finalization function. If data still * needs to be flushed from an incomplete block, the data * contained in it is padded to the size of * the last block, and written to the \p output buffer. * * \param ctx The generic cipher context. This must be initialized and * bound to a key. * \param output The buffer to write data to. This needs to be a writable * buffer of at least block_size Bytes. * \param olen The length of the data written to the \p output buffer. * This may not be \c NULL. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption * expecting a full block but not receiving one. * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding * while decrypting. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen); #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function writes a tag for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. * This must be called after mbedtls_cipher_finish(). * * \param ctx The generic cipher context. This must be initialized, * bound to a key, and have just completed a cipher * operation through mbedtls_cipher_finish() the tag for * which should be written. * \param tag The buffer to write the tag to. This must be a writable * buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to write. * * \return \c 0 on success. * \return A specific error code on failure. */ int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len); /** * \brief This function checks the tag for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. * This must be called after mbedtls_cipher_finish(). * * \param ctx The generic cipher context. This must be initialized. * \param tag The buffer holding the tag. This must be a readable * buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to check. * * \return \c 0 on success. * \return A specific error code on failure. */ int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len); #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** * \brief The generic all-in-one encryption/decryption function, * for all ciphers except AEAD constructs. * * \param ctx The generic cipher context. This must be initialized. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. * This must be a readable buffer of at least \p iv_len * Bytes. * \param iv_len The IV length for ciphers with variable-size IV. * This parameter is discarded by ciphers with fixed-size * IV. * \param input The buffer holding the input data. This must be a * readable buffer of at least \p ilen Bytes. * \param ilen The length of the input data in Bytes. * \param output The buffer for the output data. This must be able to * hold at least `ilen + block_size`. This must not be the * same buffer as \p input. * \param olen The length of the output data, to be updated with the * actual number of Bytes written. This must not be * \c NULL. * * \note Some ciphers do not use IVs nor nonce. For these * ciphers, use \p iv = NULL and \p iv_len = 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption * expecting a full block but not receiving one. * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding * while decrypting. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen); #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) /** * \brief The authenticated encryption (AEAD/NIST_KW) function. * * \note For AEAD modes, the tag will be appended to the * ciphertext, as recommended by RFC 5116. * (NIST_KW doesn't have a separate tag.) * * \param ctx The generic cipher context. This must be initialized and * bound to a key, with an AEAD algorithm or NIST_KW. * \param iv The nonce to use. This must be a readable buffer of * at least \p iv_len Bytes and may be \c NULL if \p * iv_len is \c 0. * \param iv_len The length of the nonce. For AEAD ciphers, this must * satisfy the constraints imposed by the cipher used. * For NIST_KW, this must be \c 0. * \param ad The additional data to authenticate. This must be a * readable buffer of at least \p ad_len Bytes, and may * be \c NULL is \p ad_len is \c 0. * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. * \param input The buffer holding the input data. This must be a * readable buffer of at least \p ilen Bytes, and may be * \c NULL if \p ilen is \c 0. * \param ilen The length of the input data. * \param output The buffer for the output data. This must be a * writable buffer of at least \p output_len Bytes, and * must not be \c NULL. * \param output_len The length of the \p output buffer in Bytes. For AEAD * ciphers, this must be at least \p ilen + \p tag_len. * For NIST_KW, this must be at least \p ilen + 8 * (rounded up to a multiple of 8 if KWP is used); * \p ilen + 15 is always a safe value. * \param olen This will be filled with the actual number of Bytes * written to the \p output buffer. This must point to a * writable object of type \c size_t. * \param tag_len The desired length of the authentication tag. For AEAD * ciphers, this must match the constraints imposed by * the cipher used, and in particular must not be \c 0. * For NIST_KW, this must be \c 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len); /** * \brief The authenticated encryption (AEAD/NIST_KW) function. * * \note If the data is not authentic, then the output buffer * is zeroed out to prevent the unauthentic plaintext being * used, making this interface safer. * * \note For AEAD modes, the tag must be appended to the * ciphertext, as recommended by RFC 5116. * (NIST_KW doesn't have a separate tag.) * * \param ctx The generic cipher context. This must be initialized and * bound to a key, with an AEAD algorithm or NIST_KW. * \param iv The nonce to use. This must be a readable buffer of * at least \p iv_len Bytes and may be \c NULL if \p * iv_len is \c 0. * \param iv_len The length of the nonce. For AEAD ciphers, this must * satisfy the constraints imposed by the cipher used. * For NIST_KW, this must be \c 0. * \param ad The additional data to authenticate. This must be a * readable buffer of at least \p ad_len Bytes, and may * be \c NULL is \p ad_len is \c 0. * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. * \param input The buffer holding the input data. This must be a * readable buffer of at least \p ilen Bytes, and may be * \c NULL if \p ilen is \c 0. * \param ilen The length of the input data. For AEAD ciphers this * must be at least \p tag_len. For NIST_KW this must be * at least \c 8. * \param output The buffer for the output data. This must be a * writable buffer of at least \p output_len Bytes, and * may be \c NULL if \p output_len is \c 0. * \param output_len The length of the \p output buffer in Bytes. For AEAD * ciphers, this must be at least \p ilen - \p tag_len. * For NIST_KW, this must be at least \p ilen - 8. * \param olen This will be filled with the actual number of Bytes * written to the \p output buffer. This must point to a * writable object of type \c size_t. * \param tag_len The actual length of the authentication tag. For AEAD * ciphers, this must match the constraints imposed by * the cipher used, and in particular must not be \c 0. * For NIST_KW, this must be \c 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len); #endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CIPHER_H */ webfakes/src/mbedtls/include/mbedtls/nist_kw.h0000644000176200001440000001550114740737024021200 0ustar liggesusers/** * \file nist_kw.h * * \brief This file provides an API for key wrapping (KW) and key wrapping with * padding (KWP) as defined in NIST SP 800-38F. * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf * * Key wrapping specifies a deterministic authenticated-encryption mode * of operation, according to NIST SP 800-38F: Recommendation for * Block Cipher Modes of Operation: Methods for Key Wrapping. Its * purpose is to protect cryptographic keys. * * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. * https://tools.ietf.org/html/rfc3394 * https://tools.ietf.org/html/rfc5649 * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_NIST_KW_H #define MBEDTLS_NIST_KW_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #ifdef __cplusplus extern "C" { #endif typedef enum { MBEDTLS_KW_MODE_KW = 0, MBEDTLS_KW_MODE_KWP = 1 } mbedtls_nist_kw_mode_t; #if !defined(MBEDTLS_NIST_KW_ALT) // Regular implementation // /** * \brief The key wrapping context-type definition. The key wrapping context is passed * to the APIs called. * * \note The definition of this type may change in future library versions. * Don't make any assumptions on this context! */ typedef struct { mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ } mbedtls_nist_kw_context; #else /* MBEDTLS_NIST_key wrapping_ALT */ #include "nist_kw_alt.h" #endif /* MBEDTLS_NIST_KW_ALT */ /** * \brief This function initializes the specified key wrapping context * to make references valid and prepare the context * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). * * \param ctx The key wrapping context to initialize. * */ void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx); /** * \brief This function initializes the key wrapping context set in the * \p ctx parameter and sets the encryption key. * * \param ctx The key wrapping context. * \param cipher The 128-bit block cipher to use. Only AES is supported. * \param key The Key Encryption Key (KEK). * \param keybits The KEK size in bits. This must be acceptable by the cipher. * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping * * \return \c 0 on success. * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers * which are not supported. * \return cipher-specific error code on failure of the underlying cipher. */ int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits, const int is_wrap); /** * \brief This function releases and clears the specified key wrapping context * and underlying cipher sub-context. * * \param ctx The key wrapping context to clear. */ void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx); /** * \brief This function encrypts a buffer using key wrapping. * * \param ctx The key wrapping context to use for encryption. * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) * \param input The buffer holding the input data. * \param in_len The length of the input data in Bytes. * The input uses units of 8 Bytes called semiblocks. *
  • For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive.
  • *
  • For KWP mode: any length between 1 and 2^32-1 inclusive.
* \param[out] output The buffer holding the output data. *
  • For KW mode: Must be at least 8 bytes larger than \p in_len.
  • *
  • For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of * 8 bytes for KWP (15 bytes at most).
* \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. * \param[in] out_size The capacity of the output buffer. * * \return \c 0 on success. * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. * \return cipher-specific error code on failure of the underlying cipher. */ int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, const unsigned char *input, size_t in_len, unsigned char *output, size_t *out_len, size_t out_size); /** * \brief This function decrypts a buffer using key wrapping. * * \param ctx The key wrapping context to use for decryption. * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) * \param input The buffer holding the input data. * \param in_len The length of the input data in Bytes. * The input uses units of 8 Bytes called semiblocks. * The input must be a multiple of semiblocks. *
  • For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive.
  • *
  • For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.
* \param[out] output The buffer holding the output data. * The output buffer's minimal length is 8 bytes shorter than \p in_len. * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, * depending on how much padding was added to the data. * \param[in] out_size The capacity of the output buffer. * * \return \c 0 on success. * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. * \return cipher-specific error code on failure of the underlying cipher. */ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, const unsigned char *input, size_t in_len, unsigned char *output, size_t *out_len, size_t out_size); #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /** * \brief The key wrapping checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_nist_kw_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_NIST_KW_H */ webfakes/src/mbedtls/include/mbedtls/md.h0000644000176200001440000004741514740737024020133 0ustar liggesusers/** * \file md.h * * \brief This file contains the generic functions for message-digest * (hashing) and HMAC. * * \author Adriaan de Jong */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD_H #define MBEDTLS_MD_H #include "mbedtls/private_access.h" #include #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" /** The selected feature is not available. */ #define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /** Bad input parameters to function. */ #define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /** Failed to allocate memory. */ #define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /** Opening or reading of file failed. */ #define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 #ifdef __cplusplus extern "C" { #endif /** * \brief Supported message digests. * * \warning MD5 and SHA-1 are considered weak message digests and * their use constitutes a security risk. We recommend considering * stronger message digests instead. * */ /* Note: these are aligned with the definitions of PSA_ALG_ macros for hashes, * in order to enable an efficient implementation of conversion functions. * This is tested by md_to_from_psa() in test_suite_md. */ typedef enum { MBEDTLS_MD_NONE=0, /**< None. */ MBEDTLS_MD_MD5=0x03, /**< The MD5 message digest. */ MBEDTLS_MD_RIPEMD160=0x04, /**< The RIPEMD-160 message digest. */ MBEDTLS_MD_SHA1=0x05, /**< The SHA-1 message digest. */ MBEDTLS_MD_SHA224=0x08, /**< The SHA-224 message digest. */ MBEDTLS_MD_SHA256=0x09, /**< The SHA-256 message digest. */ MBEDTLS_MD_SHA384=0x0a, /**< The SHA-384 message digest. */ MBEDTLS_MD_SHA512=0x0b, /**< The SHA-512 message digest. */ MBEDTLS_MD_SHA3_224=0x10, /**< The SHA3-224 message digest. */ MBEDTLS_MD_SHA3_256=0x11, /**< The SHA3-256 message digest. */ MBEDTLS_MD_SHA3_384=0x12, /**< The SHA3-384 message digest. */ MBEDTLS_MD_SHA3_512=0x13, /**< The SHA3-512 message digest. */ } mbedtls_md_type_t; /* Note: this should always be >= PSA_HASH_MAX_SIZE * in all builds with both CRYPTO_C and MD_LIGHT. * * This is to make things easier for modules such as TLS that may define a * buffer size using MD_MAX_SIZE in a part of the code that's common to PSA * and legacy, then assume the buffer's size is PSA_HASH_MAX_SIZE in another * part of the code based on PSA. */ #if defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA3_512) #define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ #elif defined(MBEDTLS_MD_CAN_SHA384) || defined(MBEDTLS_MD_CAN_SHA3_384) #define MBEDTLS_MD_MAX_SIZE 48 /* longest known is SHA384 */ #elif defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA3_256) #define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 */ #elif defined(MBEDTLS_MD_CAN_SHA224) || defined(MBEDTLS_MD_CAN_SHA3_224) #define MBEDTLS_MD_MAX_SIZE 28 /* longest known is SHA224 */ #else #define MBEDTLS_MD_MAX_SIZE 20 /* longest known is SHA1 or RIPE MD-160 or smaller (MD5 and earlier) */ #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) #define MBEDTLS_MD_MAX_BLOCK_SIZE 144 /* the longest known is SHA3-224 */ #elif defined(MBEDTLS_MD_CAN_SHA3_256) #define MBEDTLS_MD_MAX_BLOCK_SIZE 136 #elif defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_MD_MAX_BLOCK_SIZE 128 #elif defined(MBEDTLS_MD_CAN_SHA3_384) #define MBEDTLS_MD_MAX_BLOCK_SIZE 104 #elif defined(MBEDTLS_MD_CAN_SHA3_512) #define MBEDTLS_MD_MAX_BLOCK_SIZE 72 #else #define MBEDTLS_MD_MAX_BLOCK_SIZE 64 #endif /** * Opaque struct. * * Constructed using either #mbedtls_md_info_from_string or * #mbedtls_md_info_from_type. * * Fields can be accessed with #mbedtls_md_get_size, * #mbedtls_md_get_type and #mbedtls_md_get_name. */ /* Defined internally in library/md_wrap.h. */ typedef struct mbedtls_md_info_t mbedtls_md_info_t; /** * Used internally to indicate whether a context uses legacy or PSA. * * Internal use only. */ typedef enum { MBEDTLS_MD_ENGINE_LEGACY = 0, MBEDTLS_MD_ENGINE_PSA, } mbedtls_md_engine_t; /** * The generic message-digest context. */ typedef struct mbedtls_md_context_t { /** Information about the associated message digest. */ const mbedtls_md_info_t *MBEDTLS_PRIVATE(md_info); #if defined(MBEDTLS_MD_SOME_PSA) /** Are hash operations dispatched to PSA or legacy? */ mbedtls_md_engine_t MBEDTLS_PRIVATE(engine); #endif /** The digest-specific context (legacy) or the PSA operation. */ void *MBEDTLS_PRIVATE(md_ctx); #if defined(MBEDTLS_MD_C) /** The HMAC part of the context. */ void *MBEDTLS_PRIVATE(hmac_ctx); #endif } mbedtls_md_context_t; /** * \brief This function returns the message-digest information * associated with the given digest type. * * \param md_type The type of digest to search for. * * \return The message-digest information associated with \p md_type. * \return NULL if the associated message-digest information is not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type); /** * \brief This function initializes a message-digest context without * binding it to a particular message-digest algorithm. * * This function should always be called first. It prepares the * context for mbedtls_md_setup() for binding it to a * message-digest algorithm. */ void mbedtls_md_init(mbedtls_md_context_t *ctx); /** * \brief This function clears the internal structure of \p ctx and * frees any embedded internal structure, but does not free * \p ctx itself. * * If you have called mbedtls_md_setup() on \p ctx, you must * call mbedtls_md_free() when you are no longer using the * context. * Calling this function if you have previously * called mbedtls_md_init() and nothing else is optional. * You must not call this function if you have not called * mbedtls_md_init(). */ void mbedtls_md_free(mbedtls_md_context_t *ctx); /** * \brief This function selects the message digest algorithm to use, * and allocates internal structures. * * It should be called after mbedtls_md_init() or * mbedtls_md_free(). Makes it necessary to call * mbedtls_md_free() later. * * \param ctx The context to set up. * \param md_info The information structure of the message-digest algorithm * to use. * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), * or non-zero: HMAC is used with this context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac); /** * \brief This function clones the state of a message-digest * context. * * \note You must call mbedtls_md_setup() on \c dst before calling * this function. * * \note The two contexts must have the same type, * for example, both are SHA-256. * * \warning This function clones the message-digest state, not the * HMAC state. * * \param dst The destination context. * \param src The context to be cloned. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. * \return #MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE if both contexts are * not using the same engine. This can be avoided by moving * the call to psa_crypto_init() before the first call to * mbedtls_md_setup(). */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_clone(mbedtls_md_context_t *dst, const mbedtls_md_context_t *src); /** * \brief This function extracts the message-digest size from the * message-digest information structure. * * \param md_info The information structure of the message-digest algorithm * to use. * * \return The size of the message-digest output in Bytes. */ unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info); /** * \brief This function gives the message-digest size associated to * message-digest type. * * \param md_type The message-digest type. * * \return The size of the message-digest output in Bytes, * or 0 if the message-digest type is not known. */ static inline unsigned char mbedtls_md_get_size_from_type(mbedtls_md_type_t md_type) { return mbedtls_md_get_size(mbedtls_md_info_from_type(md_type)); } /** * \brief This function extracts the message-digest type from the * message-digest information structure. * * \param md_info The information structure of the message-digest algorithm * to use. * * \return The type of the message digest. */ mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info); /** * \brief This function starts a message-digest computation. * * You must call this function after setting up the context * with mbedtls_md_setup(), and before passing data with * mbedtls_md_update(). * * \param ctx The generic message-digest context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_starts(mbedtls_md_context_t *ctx); /** * \brief This function feeds an input buffer into an ongoing * message-digest computation. * * You must call mbedtls_md_starts() before calling this * function. You may call this function multiple times. * Afterwards, call mbedtls_md_finish(). * * \param ctx The generic message-digest context. * \param input The buffer holding the input data. * \param ilen The length of the input data. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the digest operation, * and writes the result to the output buffer. * * Call this function after a call to mbedtls_md_starts(), * followed by any number of calls to mbedtls_md_update(). * Afterwards, you may either clear the context with * mbedtls_md_free(), or call mbedtls_md_starts() to reuse * the context for another digest operation with the same * algorithm. * * \param ctx The generic message-digest context. * \param output The buffer for the generic message-digest checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output); /** * \brief This function calculates the message-digest of a buffer, * with respect to a configurable message-digest algorithm * in a single call. * * The result is calculated as * Output = message_digest(input buffer). * * \param md_info The information structure of the message-digest algorithm * to use. * \param input The buffer holding the data. * \param ilen The length of the input data. * \param output The generic message-digest checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output); /** * \brief This function returns the list of digests supported by the * generic digest module. * * \note The list starts with the strongest available hashes. * * \return A statically allocated array of digests. Each element * in the returned list is an integer belonging to the * message-digest enumeration #mbedtls_md_type_t. * The last entry is 0. */ const int *mbedtls_md_list(void); /** * \brief This function returns the message-digest information * associated with the given digest name. * * \param md_name The name of the digest to search for. * * \return The message-digest information associated with \p md_name. * \return NULL if the associated message-digest information is not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name); /** * \brief This function returns the name of the message digest for * the message-digest information structure given. * * \param md_info The information structure of the message-digest algorithm * to use. * * \return The name of the message digest. */ const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info); /** * \brief This function returns the message-digest information * from the given context. * * \param ctx The context from which to extract the information. * This must be initialized (or \c NULL). * * \return The message-digest information associated with \p ctx. * \return \c NULL if \p ctx is \c NULL. */ const mbedtls_md_info_t *mbedtls_md_info_from_ctx( const mbedtls_md_context_t *ctx); #if defined(MBEDTLS_FS_IO) /** * \brief This function calculates the message-digest checksum * result of the contents of the provided file. * * The result is calculated as * Output = message_digest(file contents). * * \param md_info The information structure of the message-digest algorithm * to use. * \param path The input file name. * \param output The generic message-digest checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing * the file pointed by \p path. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, unsigned char *output); #endif /* MBEDTLS_FS_IO */ /** * \brief This function sets the HMAC key and prepares to * authenticate a new message. * * Call this function after mbedtls_md_setup(), to use * the MD context for an HMAC calculation, then call * mbedtls_md_hmac_update() to provide the input data, and * mbedtls_md_hmac_finish() to get the HMAC value. * * \param ctx The message digest context containing an embedded HMAC * context. * \param key The HMAC secret key. * \param keylen The length of the HMAC key in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen); /** * \brief This function feeds an input buffer into an ongoing HMAC * computation. * * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() * before calling this function. * You may call this function multiple times to pass the * input piecewise. * Afterwards, call mbedtls_md_hmac_finish(). * * \param ctx The message digest context containing an embedded HMAC * context. * \param input The buffer holding the input data. * \param ilen The length of the input data. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the HMAC operation, and writes * the result to the output buffer. * * Call this function after mbedtls_md_hmac_starts() and * mbedtls_md_hmac_update() to get the HMAC value. Afterwards * you may either call mbedtls_md_free() to clear the context, * or call mbedtls_md_hmac_reset() to reuse the context with * the same HMAC key. * * \param ctx The message digest context containing an embedded HMAC * context. * \param output The generic HMAC checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output); /** * \brief This function prepares to authenticate a new message with * the same key as the previous HMAC operation. * * You may call this function after mbedtls_md_hmac_finish(). * Afterwards call mbedtls_md_hmac_update() to pass the new * input. * * \param ctx The message digest context containing an embedded HMAC * context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx); /** * \brief This function calculates the full generic HMAC * on the input buffer with the provided key. * * The function allocates the context, performs the * calculation, and frees the context. * * The HMAC result is calculated as * output = generic HMAC(hmac key, input buffer). * * \param md_info The information structure of the message-digest algorithm * to use. * \param key The HMAC secret key. * \param keylen The length of the HMAC secret key in Bytes. * \param input The buffer holding the input data. * \param ilen The length of the input data. * \param output The generic HMAC result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac(const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output); #ifdef __cplusplus } #endif #endif /* MBEDTLS_MD_H */ webfakes/src/mbedtls/include/mbedtls/poly1305.h0000644000176200001440000001360614740737024021022 0ustar liggesusers/** * \file poly1305.h * * \brief This file contains Poly1305 definitions and functions. * * Poly1305 is a one-time message authenticator that can be used to * authenticate messages. Poly1305-AES was created by Daniel * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic * Poly1305 algorithm (not tied to AES) was also standardized in RFC * 7539. * * \author Daniel King */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_POLY1305_H #define MBEDTLS_POLY1305_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** Invalid input parameter(s). */ #define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_POLY1305_ALT) typedef struct mbedtls_poly1305_context { uint32_t MBEDTLS_PRIVATE(r)[4]; /** The value for 'r' (low 128 bits of the key). */ uint32_t MBEDTLS_PRIVATE(s)[4]; /** The value for 's' (high 128 bits of the key). */ uint32_t MBEDTLS_PRIVATE(acc)[5]; /** The accumulator number. */ uint8_t MBEDTLS_PRIVATE(queue)[16]; /** The current partial block of data. */ size_t MBEDTLS_PRIVATE(queue_len); /** The number of bytes stored in 'queue'. */ } mbedtls_poly1305_context; #else /* MBEDTLS_POLY1305_ALT */ #include "poly1305_alt.h" #endif /* MBEDTLS_POLY1305_ALT */ /** * \brief This function initializes the specified Poly1305 context. * * It must be the first API called before using * the context. * * It is usually followed by a call to * \c mbedtls_poly1305_starts(), then one or more calls to * \c mbedtls_poly1305_update(), then one call to * \c mbedtls_poly1305_finish(), then finally * \c mbedtls_poly1305_free(). * * \param ctx The Poly1305 context to initialize. This must * not be \c NULL. */ void mbedtls_poly1305_init(mbedtls_poly1305_context *ctx); /** * \brief This function releases and clears the specified * Poly1305 context. * * \param ctx The Poly1305 context to clear. This may be \c NULL, in which * case this function is a no-op. If it is not \c NULL, it must * point to an initialized Poly1305 context. */ void mbedtls_poly1305_free(mbedtls_poly1305_context *ctx); /** * \brief This function sets the one-time authentication key. * * \warning The key must be unique and unpredictable for each * invocation of Poly1305. * * \param ctx The Poly1305 context to which the key should be bound. * This must be initialized. * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx, const unsigned char key[32]); /** * \brief This functions feeds an input buffer into an ongoing * Poly1305 computation. * * It is called between \c mbedtls_cipher_poly1305_starts() and * \c mbedtls_cipher_poly1305_finish(). * It can be called repeatedly to process a stream of data. * * \param ctx The Poly1305 context to use for the Poly1305 operation. * This must be initialized and bound to a key. * \param ilen The length of the input data in Bytes. * Any value is accepted. * \param input The buffer holding the input data. * This pointer can be \c NULL if `ilen == 0`. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_poly1305_update(mbedtls_poly1305_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function generates the Poly1305 Message * Authentication Code (MAC). * * \param ctx The Poly1305 context to use for the Poly1305 operation. * This must be initialized and bound to a key. * \param mac The buffer to where the MAC is written. This must * be a writable buffer of length \c 16 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx, unsigned char mac[16]); /** * \brief This function calculates the Poly1305 MAC of the input * buffer with the provided key. * * \warning The key must be unique and unpredictable for each * invocation of Poly1305. * * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. * \param ilen The length of the input data in Bytes. * Any value is accepted. * \param input The buffer holding the input data. * This pointer can be \c NULL if `ilen == 0`. * \param mac The buffer to where the MAC is written. This must be * a writable buffer of length \c 16 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_poly1305_mac(const unsigned char key[32], const unsigned char *input, size_t ilen, unsigned char mac[16]); #if defined(MBEDTLS_SELF_TEST) /** * \brief The Poly1305 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_poly1305_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_POLY1305_H */ webfakes/src/mbedtls/include/mbedtls/pkcs12.h0000644000176200001440000002100614740737024020622 0ustar liggesusers/** * \file pkcs12.h * * \brief PKCS#12 Personal Information Exchange Syntax */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PKCS12_H #define MBEDTLS_PKCS12_H #include "mbedtls/build_info.h" #include "mbedtls/md.h" #include "mbedtls/cipher.h" #include "mbedtls/asn1.h" #include /** Bad input parameters to function. */ #define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /** Feature not available, e.g. unsupported encryption scheme. */ #define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /** PBE ASN.1 data not as expected. */ #define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /** Given private key password does not allow for correct decryption. */ #define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 #define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ #define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ #define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ #define MBEDTLS_PKCS12_PBE_DECRYPT MBEDTLS_DECRYPT #define MBEDTLS_PKCS12_PBE_ENCRYPT MBEDTLS_ENCRYPT #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief PKCS12 Password Based function (encryption / decryption) * for cipher-based and mbedtls_md-based PBE's * * \note When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must * be enabled at compile time. * * \deprecated This function is deprecated and will be removed in a * future version of the library. * Please use mbedtls_pkcs12_pbe_ext() instead. * * \warning When decrypting: * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile * time, this function validates the CBC padding and returns * #MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH if the padding is * invalid. Note that this can help active adversaries * attempting to brute-forcing the password. Note also that * there is no guarantee that an invalid password will be * detected (the chances of a valid padding with a random * password are about 1/255). * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is disabled at compile * time, this function does not validate the CBC padding. * * \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure * \param mode either #MBEDTLS_PKCS12_PBE_ENCRYPT or * #MBEDTLS_PKCS12_PBE_DECRYPT * \param cipher_type the cipher used * \param md_type the mbedtls_md used * \param pwd Latin1-encoded password used. This may only be \c NULL when * \p pwdlen is 0. No null terminator should be used. * \param pwdlen length of the password (may be 0) * \param data the input data * \param len data length * \param output Output buffer. * On success, it contains the encrypted or decrypted data, * possibly followed by the CBC padding. * On failure, the content is indeterminate. * For decryption, there must be enough room for \p len * bytes. * For encryption, there must be enough room for * \p len + 1 bytes, rounded up to the block size of * the block cipher identified by \p pbe_params. * * \return 0 if successful, or a MBEDTLS_ERR_XXX code */ int MBEDTLS_DEPRECATED mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output); #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) /** * \brief PKCS12 Password Based function (encryption / decryption) * for cipher-based and mbedtls_md-based PBE's * * * \warning When decrypting: * - This function validates the CBC padding and returns * #MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH if the padding is * invalid. Note that this can help active adversaries * attempting to brute-forcing the password. Note also that * there is no guarantee that an invalid password will be * detected (the chances of a valid padding with a random * password are about 1/255). * * \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure * \param mode either #MBEDTLS_PKCS12_PBE_ENCRYPT or * #MBEDTLS_PKCS12_PBE_DECRYPT * \param cipher_type the cipher used * \param md_type the mbedtls_md used * \param pwd Latin1-encoded password used. This may only be \c NULL when * \p pwdlen is 0. No null terminator should be used. * \param pwdlen length of the password (may be 0) * \param data the input data * \param len data length * \param output Output buffer. * On success, it contains the encrypted or decrypted data, * possibly followed by the CBC padding. * On failure, the content is indeterminate. * For decryption, there must be enough room for \p len * bytes. * For encryption, there must be enough room for * \p len + 1 bytes, rounded up to the block size of * the block cipher identified by \p pbe_params. * \param output_size size of output buffer. * This must be big enough to accommodate for output plus * padding data. * \param output_len On success, length of actual data written to the output buffer. * * \return 0 if successful, or a MBEDTLS_ERR_XXX code */ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output, size_t output_size, size_t *output_len); #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ #endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ /** * \brief The PKCS#12 derivation function uses a password and a salt * to produce pseudo-random bits for a particular "purpose". * * Depending on the given id, this function can produce an * encryption/decryption key, an initialization vector or an * integrity key. * * \param data buffer to store the derived data in * \param datalen length of buffer to fill * \param pwd The password to use. For compliance with PKCS#12 §B.1, this * should be a BMPString, i.e. a Unicode string where each * character is encoded as 2 bytes in big-endian order, with * no byte order mark and with a null terminator (i.e. the * last two bytes should be 0x00 0x00). * \param pwdlen length of the password (may be 0). * \param salt Salt buffer to use. This may only be \c NULL when * \p saltlen is 0. * \param saltlen length of the salt (may be zero) * \param mbedtls_md mbedtls_md type to use during the derivation * \param id id that describes the purpose (can be * #MBEDTLS_PKCS12_DERIVE_KEY, #MBEDTLS_PKCS12_DERIVE_IV or * #MBEDTLS_PKCS12_DERIVE_MAC_KEY) * \param iterations number of iterations * * \return 0 if successful, or a MD, BIGNUM type error. */ int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, const unsigned char *pwd, size_t pwdlen, const unsigned char *salt, size_t saltlen, mbedtls_md_type_t mbedtls_md, int id, int iterations); #ifdef __cplusplus } #endif #endif /* pkcs12.h */ webfakes/src/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h0000644000176200001440000002645414740737024025564 0ustar liggesusers/** * \file mbedtls/config_adjust_psa_from_legacy.h * \brief Adjust PSA configuration: construct PSA configuration from legacy * * This is an internal header. Do not include it directly. * * When MBEDTLS_PSA_CRYPTO_CONFIG is disabled, we automatically enable * cryptographic mechanisms through the PSA interface when the corresponding * legacy mechanism is enabled. In many cases, this just enables the PSA * wrapper code around the legacy implementation, but we also do this for * some mechanisms where PSA has its own independent implementation so * that high-level modules that can use either cryptographic API have the * same feature set in both cases. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H #define MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ /* * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG * is not defined */ #if defined(MBEDTLS_CCM_C) #define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 #define PSA_WANT_ALG_CCM 1 #if defined(MBEDTLS_CIPHER_C) #define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1 #define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 #endif /* MBEDTLS_CIPHER_C */ #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CMAC_C) #define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 #define PSA_WANT_ALG_CMAC 1 #endif /* MBEDTLS_CMAC_C */ #if defined(MBEDTLS_ECDH_C) #define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 #define PSA_WANT_ALG_ECDH 1 #endif /* MBEDTLS_ECDH_C */ #if defined(MBEDTLS_ECDSA_C) #define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 #define PSA_WANT_ALG_ECDSA 1 #define PSA_WANT_ALG_ECDSA_ANY 1 // Only add in DETERMINISTIC support if ECDSA is also enabled #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 #define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #endif /* MBEDTLS_ECDSA_C */ #if defined(MBEDTLS_ECP_C) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 /* Normally we wouldn't enable this because it's not implemented in ecp.c, * but since it used to be available any time ECP_C was enabled, let's enable * it anyway for the sake of backwards compatibility */ #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 /* See comment for PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE above. */ #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 #define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_DHM_C) #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 #define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 #define PSA_WANT_ALG_FFDH 1 #define PSA_WANT_DH_RFC7919_2048 1 #define PSA_WANT_DH_RFC7919_3072 1 #define PSA_WANT_DH_RFC7919_4096 1 #define PSA_WANT_DH_RFC7919_6144 1 #define PSA_WANT_DH_RFC7919_8192 1 #define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1 #endif /* MBEDTLS_DHM_C */ #if defined(MBEDTLS_GCM_C) #define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 #define PSA_WANT_ALG_GCM 1 #endif /* MBEDTLS_GCM_C */ /* Enable PSA HKDF algorithm if mbedtls HKDF is supported. * PSA HKDF EXTRACT and PSA HKDF EXPAND have minimal cost when * PSA HKDF is enabled, so enable both algorithms together * with PSA HKDF. */ #if defined(MBEDTLS_HKDF_C) #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #define PSA_WANT_ALG_HMAC 1 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 #define PSA_WANT_ALG_HKDF 1 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1 #define PSA_WANT_ALG_HKDF_EXTRACT 1 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1 #define PSA_WANT_ALG_HKDF_EXPAND 1 #endif /* MBEDTLS_HKDF_C */ #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #define PSA_WANT_ALG_HMAC 1 #define PSA_WANT_KEY_TYPE_HMAC 1 #if defined(MBEDTLS_MD_C) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 #define PSA_WANT_ALG_TLS12_PRF 1 #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 #define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_MD5_C) #define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 #define PSA_WANT_ALG_MD5 1 #endif #if defined(MBEDTLS_ECJPAKE_C) #define MBEDTLS_PSA_BUILTIN_PAKE 1 #define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1 #define PSA_WANT_ALG_JPAKE 1 #endif #if defined(MBEDTLS_RIPEMD160_C) #define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 #define PSA_WANT_ALG_RIPEMD160 1 #endif #if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_PKCS1_V15) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 #define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1 #endif /* MBEDTLS_PKCS1_V15 */ #if defined(MBEDTLS_PKCS1_V21) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 #define PSA_WANT_ALG_RSA_OAEP 1 #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 #define PSA_WANT_ALG_RSA_PSS 1 #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_GENPRIME) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 #endif /* MBEDTLS_GENPRIME */ #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 #define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_SHA1_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 #define PSA_WANT_ALG_SHA_1 1 #endif #if defined(MBEDTLS_SHA224_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 #define PSA_WANT_ALG_SHA_224 1 #endif #if defined(MBEDTLS_SHA256_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 #define PSA_WANT_ALG_SHA_256 1 #endif #if defined(MBEDTLS_SHA384_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 #define PSA_WANT_ALG_SHA_384 1 #endif #if defined(MBEDTLS_SHA512_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 #define PSA_WANT_ALG_SHA_512 1 #endif #if defined(MBEDTLS_SHA3_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1 #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1 #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1 #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1 #define PSA_WANT_ALG_SHA3_224 1 #define PSA_WANT_ALG_SHA3_256 1 #define PSA_WANT_ALG_SHA3_384 1 #define PSA_WANT_ALG_SHA3_512 1 #endif #if defined(MBEDTLS_AES_C) #define PSA_WANT_KEY_TYPE_AES 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 #endif #if defined(MBEDTLS_ARIA_C) #define PSA_WANT_KEY_TYPE_ARIA 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 #endif #if defined(MBEDTLS_CAMELLIA_C) #define PSA_WANT_KEY_TYPE_CAMELLIA 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 #endif #if defined(MBEDTLS_DES_C) #define PSA_WANT_KEY_TYPE_DES 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1 #define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 #endif #if defined(MBEDTLS_CHACHA20_C) #define PSA_WANT_KEY_TYPE_CHACHA20 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 /* ALG_STREAM_CIPHER requires CIPHER_C in order to be supported in PSA */ #if defined(MBEDTLS_CIPHER_C) #define PSA_WANT_ALG_STREAM_CIPHER 1 #define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 #endif #if defined(MBEDTLS_CHACHAPOLY_C) #define PSA_WANT_ALG_CHACHA20_POLY1305 1 #define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 #endif #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) #define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 #define PSA_WANT_ALG_CBC_NO_PADDING 1 #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) #define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 #define PSA_WANT_ALG_CBC_PKCS7 1 #endif #endif #if (defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \ defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) && \ defined(MBEDTLS_CIPHER_C) #define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 #define PSA_WANT_ALG_ECB_NO_PADDING 1 #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) #define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 #define PSA_WANT_ALG_CFB 1 #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) #define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 #define PSA_WANT_ALG_CTR 1 #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) #define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 #define PSA_WANT_ALG_OFB 1 #endif #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 #endif #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 #endif #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 #define PSA_WANT_ECC_MONTGOMERY_255 1 #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 #define PSA_WANT_ECC_MONTGOMERY_448 1 #endif #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 #define PSA_WANT_ECC_SECP_R1_192 1 #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 #define PSA_WANT_ECC_SECP_R1_224 1 #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 #define PSA_WANT_ECC_SECP_R1_256 1 #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 #define PSA_WANT_ECC_SECP_R1_384 1 #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 #define PSA_WANT_ECC_SECP_R1_521 1 #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 #define PSA_WANT_ECC_SECP_K1_192 1 #endif /* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */ #if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 #define PSA_WANT_ECC_SECP_K1_224 1 #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 #define PSA_WANT_ECC_SECP_K1_256 1 #endif #endif /* MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H */ webfakes/src/mbedtls/include/mbedtls/pkcs7.h0000644000176200001440000002262114740737024020552 0ustar liggesusers/** * \file pkcs7.h * * \brief PKCS #7 generic defines and structures * https://tools.ietf.org/html/rfc2315 */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** * Note: For the time being, this implementation of the PKCS #7 cryptographic * message syntax is a partial implementation of RFC 2315. * Differences include: * - The RFC specifies 6 different content types. The only type currently * supported in Mbed TLS is the signed-data content type. * - The only supported PKCS #7 Signed Data syntax version is version 1 * - The RFC specifies support for BER. This implementation is limited to * DER only. * - The RFC specifies that multiple digest algorithms can be specified * in the Signed Data type. Only one digest algorithm is supported in Mbed TLS. * - The RFC specifies the Signed Data type can contain multiple X.509 or PKCS #6 extended * certificates. In Mbed TLS, this list can only contain 0 or 1 certificates * and they must be in X.509 format. * - The RFC specifies the Signed Data type can contain * certificate-revocation lists (CRLs). This implementation has no support * for CRLs so it is assumed to be an empty list. * - The RFC allows for SignerInfo structure to optionally contain * unauthenticatedAttributes and authenticatedAttributes. In Mbed TLS it is * assumed these fields are empty. * - The RFC allows for the signed Data type to contain contentInfo. This * implementation assumes the type is DATA and the content is empty. */ #ifndef MBEDTLS_PKCS7_H #define MBEDTLS_PKCS7_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #include "mbedtls/x509_crt.h" /** * \name PKCS #7 Module Error codes * \{ */ #define MBEDTLS_ERR_PKCS7_INVALID_FORMAT -0x5300 /**< The format is invalid, e.g. different type expected. */ #define MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE -0x5380 /**< Unavailable feature, e.g. anything other than signed data. */ #define MBEDTLS_ERR_PKCS7_INVALID_VERSION -0x5400 /**< The PKCS #7 version element is invalid or cannot be parsed. */ #define MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO -0x5480 /**< The PKCS #7 content info is invalid or cannot be parsed. */ #define MBEDTLS_ERR_PKCS7_INVALID_ALG -0x5500 /**< The algorithm tag or value is invalid or cannot be parsed. */ #define MBEDTLS_ERR_PKCS7_INVALID_CERT -0x5580 /**< The certificate tag or value is invalid or cannot be parsed. */ #define MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE -0x5600 /**< Error parsing the signature */ #define MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO -0x5680 /**< Error parsing the signer's info */ #define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA -0x5700 /**< Input invalid. */ #define MBEDTLS_ERR_PKCS7_ALLOC_FAILED -0x5780 /**< Allocation of memory failed. */ #define MBEDTLS_ERR_PKCS7_VERIFY_FAIL -0x5800 /**< Verification Failed */ #define MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID -0x5880 /**< The PKCS #7 date issued/expired dates are invalid */ /* \} name */ /** * \name PKCS #7 Supported Version * \{ */ #define MBEDTLS_PKCS7_SUPPORTED_VERSION 0x01 /* \} name */ #ifdef __cplusplus extern "C" { #endif /** * Type-length-value structure that allows for ASN.1 using DER. */ typedef mbedtls_asn1_buf mbedtls_pkcs7_buf; /** * Container for ASN.1 named information objects. * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). */ typedef mbedtls_asn1_named_data mbedtls_pkcs7_name; /** * Container for a sequence of ASN.1 items */ typedef mbedtls_asn1_sequence mbedtls_pkcs7_sequence; /** * PKCS #7 types */ typedef enum { MBEDTLS_PKCS7_NONE=0, MBEDTLS_PKCS7_DATA, MBEDTLS_PKCS7_SIGNED_DATA, MBEDTLS_PKCS7_ENVELOPED_DATA, MBEDTLS_PKCS7_SIGNED_AND_ENVELOPED_DATA, MBEDTLS_PKCS7_DIGESTED_DATA, MBEDTLS_PKCS7_ENCRYPTED_DATA, } mbedtls_pkcs7_type; /** * Structure holding PKCS #7 signer info */ typedef struct mbedtls_pkcs7_signer_info { int MBEDTLS_PRIVATE(version); mbedtls_x509_buf MBEDTLS_PRIVATE(serial); mbedtls_x509_name MBEDTLS_PRIVATE(issuer); mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_raw); mbedtls_x509_buf MBEDTLS_PRIVATE(alg_identifier); mbedtls_x509_buf MBEDTLS_PRIVATE(sig_alg_identifier); mbedtls_x509_buf MBEDTLS_PRIVATE(sig); struct mbedtls_pkcs7_signer_info *MBEDTLS_PRIVATE(next); } mbedtls_pkcs7_signer_info; /** * Structure holding the signed data section */ typedef struct mbedtls_pkcs7_signed_data { int MBEDTLS_PRIVATE(version); mbedtls_pkcs7_buf MBEDTLS_PRIVATE(digest_alg_identifiers); int MBEDTLS_PRIVATE(no_of_certs); mbedtls_x509_crt MBEDTLS_PRIVATE(certs); int MBEDTLS_PRIVATE(no_of_crls); mbedtls_x509_crl MBEDTLS_PRIVATE(crl); int MBEDTLS_PRIVATE(no_of_signers); mbedtls_pkcs7_signer_info MBEDTLS_PRIVATE(signers); } mbedtls_pkcs7_signed_data; /** * Structure holding PKCS #7 structure, only signed data for now */ typedef struct mbedtls_pkcs7 { mbedtls_pkcs7_buf MBEDTLS_PRIVATE(raw); mbedtls_pkcs7_signed_data MBEDTLS_PRIVATE(signed_data); } mbedtls_pkcs7; /** * \brief Initialize mbedtls_pkcs7 structure. * * \param pkcs7 mbedtls_pkcs7 structure. */ void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7); /** * \brief Parse a single DER formatted PKCS #7 detached signature. * * \param pkcs7 The mbedtls_pkcs7 structure to be filled by the parser. * \param buf The buffer holding only the DER encoded PKCS #7 content. * \param buflen The size in bytes of \p buf. The size must be exactly the * length of the DER encoded PKCS #7 content. * * \note This function makes an internal copy of the PKCS #7 buffer * \p buf. In particular, \p buf may be destroyed or reused * after this call returns. * \note Signatures with internal data are not supported. * * \return The \c mbedtls_pkcs7_type of \p buf, if successful. * \return A negative error code on failure. */ int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, const size_t buflen); /** * \brief Verification of PKCS #7 signature against a caller-supplied * certificate. * * For each signer in the PKCS structure, this function computes * a signature over the supplied data, using the supplied * certificate and the same digest algorithm as specified by the * signer. It then compares this signature against the * signer's signature; verification succeeds if any comparison * matches. * * This function does not use the certificates held within the * PKCS #7 structure itself, and does not check that the * certificate is signed by a trusted certification authority. * * \param pkcs7 mbedtls_pkcs7 structure containing signature. * \param cert Certificate containing key to verify signature. * \param data Plain data on which signature has to be verified. * \param datalen Length of the data. * * \note This function internally calculates the hash on the supplied * plain data for signature verification. * * \return 0 if the signature verifies, or a negative error code on failure. */ int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *data, size_t datalen); /** * \brief Verification of PKCS #7 signature against a caller-supplied * certificate. * * For each signer in the PKCS structure, this function * validates a signature over the supplied hash, using the * supplied certificate and the same digest algorithm as * specified by the signer. Verification succeeds if any * signature is good. * * This function does not use the certificates held within the * PKCS #7 structure itself, and does not check that the * certificate is signed by a trusted certification authority. * * \param pkcs7 PKCS #7 structure containing signature. * \param cert Certificate containing key to verify signature. * \param hash Hash of the plain data on which signature has to be verified. * \param hashlen Length of the hash. * * \note This function is different from mbedtls_pkcs7_signed_data_verify() * in that it is directly passed the hash of the data. * * \return 0 if the signature verifies, or a negative error code on failure. */ int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *hash, size_t hashlen); /** * \brief Unallocate all PKCS #7 data and zeroize the memory. * It doesn't free \p pkcs7 itself. This should be done by the caller. * * \param pkcs7 mbedtls_pkcs7 structure to free. */ void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7); #ifdef __cplusplus } #endif #endif /* pkcs7.h */ webfakes/src/mbedtls/include/mbedtls/threading.h0000644000176200001440000001202614740737024021466 0ustar liggesusers/** * \file threading.h * * \brief Threading abstraction layer */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_THREADING_H #define MBEDTLS_THREADING_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #ifdef __cplusplus extern "C" { #endif /** Bad input parameters to function. */ #define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /** Locking / unlocking / free failed with error code. */ #define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E #if defined(MBEDTLS_THREADING_PTHREAD) #include typedef struct mbedtls_threading_mutex_t { pthread_mutex_t MBEDTLS_PRIVATE(mutex); /* WARNING - state should only be accessed when holding the mutex lock in * tests/src/threading_helpers.c, otherwise corruption can occur. * state will be 0 after a failed init or a free, and nonzero after a * successful init. This field is for testing only and thus not considered * part of the public API of Mbed TLS and may change without notice.*/ char MBEDTLS_PRIVATE(state); } mbedtls_threading_mutex_t; #endif #if defined(MBEDTLS_THREADING_ALT) /* You should define the mbedtls_threading_mutex_t type in your header */ #include "threading_alt.h" /** * \brief Set your alternate threading implementation function * pointers and initialize global mutexes. If used, this * function must be called once in the main thread before any * other Mbed TLS function is called, and * mbedtls_threading_free_alt() must be called once in the main * thread after all other Mbed TLS functions. * * \note mutex_init() and mutex_free() don't return a status code. * If mutex_init() fails, it should leave its argument (the * mutex) in a state such that mutex_lock() will fail when * called with this argument. * * \param mutex_init the init function implementation * \param mutex_free the free function implementation * \param mutex_lock the lock function implementation * \param mutex_unlock the unlock function implementation */ void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *), void (*mutex_free)(mbedtls_threading_mutex_t *), int (*mutex_lock)(mbedtls_threading_mutex_t *), int (*mutex_unlock)(mbedtls_threading_mutex_t *)); /** * \brief Free global mutexes. */ void mbedtls_threading_free_alt(void); #endif /* MBEDTLS_THREADING_ALT */ #if defined(MBEDTLS_THREADING_C) /* * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock * * All these functions are expected to work or the result will be undefined. */ extern void (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *mutex); extern void (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *mutex); extern int (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *mutex); extern int (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *mutex); /* * Global mutexes */ #if defined(MBEDTLS_FS_IO) extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; #endif #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) /* This mutex may or may not be used in the default definition of * mbedtls_platform_gmtime_r(), but in order to determine that, * we need to check POSIX features, hence modify _POSIX_C_SOURCE. * With the current approach, this declaration is orphaned, lacking * an accompanying definition, in case mbedtls_platform_gmtime_r() * doesn't need it, but that's not a problem. */ extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; #endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ #if defined(MBEDTLS_PSA_CRYPTO_C) /* * A mutex used to make the PSA subsystem thread safe. * * key_slot_mutex protects the registered_readers and * state variable for all key slots in &global_data.key_slots. * * This mutex must be held when any read from or write to a state or * registered_readers field is performed, i.e. when calling functions: * psa_key_slot_state_transition(), psa_register_read(), psa_unregister_read(), * psa_key_slot_has_readers() and psa_wipe_key_slot(). */ extern mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex; /* * A mutex used to make the non-rng PSA global_data struct members thread safe. * * This mutex must be held when reading or writing to any of the PSA global_data * structure members, other than the rng_state or rng struct. */ extern mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex; /* * A mutex used to make the PSA global_data rng data thread safe. * * This mutex must be held when reading or writing to the PSA * global_data rng_state or rng struct members. */ extern mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex; #endif #endif /* MBEDTLS_THREADING_C */ #ifdef __cplusplus } #endif #endif /* threading.h */ webfakes/src/mbedtls/include/mbedtls/rsa.h0000644000176200001440000015707514740737024020324 0ustar liggesusers/** * \file rsa.h * * \brief This file provides an API for the RSA public-key cryptosystem. * * The RSA public-key cryptosystem is defined in Public-Key * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption * and Public-Key Cryptography Standards (PKCS) #1 v2.1: * RSA Cryptography Specifications. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RSA_H #define MBEDTLS_RSA_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" #include "mbedtls/md.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /* * RSA Error codes */ /** Bad input parameters to function. */ #define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /** Input data contains invalid padding and is rejected. */ #define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /** Something failed during generation of a key. */ #define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /** Key failed to pass the validity check of the library. */ #define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /** The public key operation failed. */ #define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /** The private key operation failed. */ #define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /** The PKCS#1 verification failed. */ #define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /** The output buffer for decryption is not large enough. */ #define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /** The random generator failed to generate non-zeros. */ #define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /* * RSA constants */ #define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ #define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ #define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ #define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ #define MBEDTLS_RSA_SALT_LEN_ANY -1 /* * The above constants may be used even if the RSA module is compile out, * eg for alternative (PKCS#11) RSA implementations in the PK layers. */ #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_RSA_ALT) // Regular implementation // #if !defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS) #define MBEDTLS_RSA_GEN_KEY_MIN_BITS 1024 #elif MBEDTLS_RSA_GEN_KEY_MIN_BITS < 128 #error "MBEDTLS_RSA_GEN_KEY_MIN_BITS must be at least 128 bits" #endif /** * \brief The RSA context structure. */ typedef struct mbedtls_rsa_context { int MBEDTLS_PRIVATE(ver); /*!< Reserved for internal purposes. * Do not set this field in application * code. Its meaning might change without * notice. */ size_t MBEDTLS_PRIVATE(len); /*!< The size of \p N in Bytes. */ mbedtls_mpi MBEDTLS_PRIVATE(N); /*!< The public modulus. */ mbedtls_mpi MBEDTLS_PRIVATE(E); /*!< The public exponent. */ mbedtls_mpi MBEDTLS_PRIVATE(D); /*!< The private exponent. */ mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The first prime factor. */ mbedtls_mpi MBEDTLS_PRIVATE(Q); /*!< The second prime factor. */ mbedtls_mpi MBEDTLS_PRIVATE(DP); /*!< D % (P - 1). */ mbedtls_mpi MBEDTLS_PRIVATE(DQ); /*!< D % (Q - 1). */ mbedtls_mpi MBEDTLS_PRIVATE(QP); /*!< 1 / (Q % P). */ mbedtls_mpi MBEDTLS_PRIVATE(RN); /*!< cached R^2 mod N. */ mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< cached R^2 mod P. */ mbedtls_mpi MBEDTLS_PRIVATE(RQ); /*!< cached R^2 mod Q. */ mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The cached blinding value. */ mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The cached un-blinding value. */ int MBEDTLS_PRIVATE(padding); /*!< Selects padding mode: #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ int MBEDTLS_PRIVATE(hash_id); /*!< Hash identifier of mbedtls_md_type_t type, as specified in md.h for use in the MGF mask generating function used in the EME-OAEP and EMSA-PSS encodings. */ #if defined(MBEDTLS_THREADING_C) /* Invariant: the mutex is initialized iff ver != 0. */ mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< Thread-safety mutex. */ #endif } mbedtls_rsa_context; #else /* MBEDTLS_RSA_ALT */ #include "rsa_alt.h" #endif /* MBEDTLS_RSA_ALT */ /** * \brief This function initializes an RSA context. * * \note This function initializes the padding and the hash * identifier to respectively #MBEDTLS_RSA_PKCS_V15 and * #MBEDTLS_MD_NONE. See mbedtls_rsa_set_padding() for more * information about those parameters. * * \param ctx The RSA context to initialize. This must not be \c NULL. */ void mbedtls_rsa_init(mbedtls_rsa_context *ctx); /** * \brief This function sets padding for an already initialized RSA * context. * * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP * encryption scheme and the RSASSA-PSS signature scheme. * * \note The \p hash_id parameter is ignored when using * #MBEDTLS_RSA_PKCS_V15 padding. * * \note The choice of padding mode is strictly enforced for private * key operations, since there might be security concerns in * mixing padding modes. For public key operations it is * a default value, which can be overridden by calling specific * \c mbedtls_rsa_rsaes_xxx or \c mbedtls_rsa_rsassa_xxx * functions. * * \note The hash selected in \p hash_id is always used for OEAP * encryption. For PSS signatures, it is always used for * making signatures, but can be overridden for verifying them. * If set to #MBEDTLS_MD_NONE, it is always overridden. * * \param ctx The initialized RSA context to be configured. * \param padding The padding mode to use. This must be either * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. * \param hash_id The hash identifier for PSS or OAEP, if \p padding is * #MBEDTLS_RSA_PKCS_V21. #MBEDTLS_MD_NONE is accepted by this * function but may be not suitable for some operations. * Ignored if \p padding is #MBEDTLS_RSA_PKCS_V15. * * \return \c 0 on success. * \return #MBEDTLS_ERR_RSA_INVALID_PADDING failure: * \p padding or \p hash_id is invalid. */ int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, mbedtls_md_type_t hash_id); /** * \brief This function retrieves padding mode of initialized * RSA context. * * \param ctx The initialized RSA context. * * \return RSA padding mode. * */ int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx); /** * \brief This function retrieves hash identifier of mbedtls_md_type_t * type. * * \param ctx The initialized RSA context. * * \return Hash identifier of mbedtls_md_type_t type. * */ int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx); /** * \brief This function imports a set of core parameters into an * RSA context. * * \note This function can be called multiple times for successive * imports, if the parameters are not simultaneously present. * * Any sequence of calls to this function should be followed * by a call to mbedtls_rsa_complete(), which checks and * completes the provided information to a ready-for-use * public or private RSA key. * * \note See mbedtls_rsa_complete() for more information on which * parameters are necessary to set up a private or public * RSA key. * * \note The imported parameters are copied and need not be preserved * for the lifetime of the RSA context being set up. * * \param ctx The initialized RSA context to store the parameters in. * \param N The RSA modulus. This may be \c NULL. * \param P The first prime factor of \p N. This may be \c NULL. * \param Q The second prime factor of \p N. This may be \c NULL. * \param D The private exponent. This may be \c NULL. * \param E The public exponent. This may be \c NULL. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_rsa_import(mbedtls_rsa_context *ctx, const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E); /** * \brief This function imports core RSA parameters, in raw big-endian * binary format, into an RSA context. * * \note This function can be called multiple times for successive * imports, if the parameters are not simultaneously present. * * Any sequence of calls to this function should be followed * by a call to mbedtls_rsa_complete(), which checks and * completes the provided information to a ready-for-use * public or private RSA key. * * \note See mbedtls_rsa_complete() for more information on which * parameters are necessary to set up a private or public * RSA key. * * \note The imported parameters are copied and need not be preserved * for the lifetime of the RSA context being set up. * * \param ctx The initialized RSA context to store the parameters in. * \param N The RSA modulus. This may be \c NULL. * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. * \param P The first prime factor of \p N. This may be \c NULL. * \param P_len The Byte length of \p P; it is ignored if \p P == NULL. * \param Q The second prime factor of \p N. This may be \c NULL. * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. * \param D The private exponent. This may be \c NULL. * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. * \param E The public exponent. This may be \c NULL. * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx, unsigned char const *N, size_t N_len, unsigned char const *P, size_t P_len, unsigned char const *Q, size_t Q_len, unsigned char const *D, size_t D_len, unsigned char const *E, size_t E_len); /** * \brief This function completes an RSA context from * a set of imported core parameters. * * To setup an RSA public key, precisely \c N and \c E * must have been imported. * * To setup an RSA private key, sufficient information must * be present for the other parameters to be derivable. * * The default implementation supports the following: *
  • Derive \c P, \c Q from \c N, \c D, \c E.
  • *
  • Derive \c N, \c D from \c P, \c Q, \c E.
* Alternative implementations need not support these. * * If this function runs successfully, it guarantees that * the RSA context can be used for RSA operations without * the risk of failure or crash. * * \warning This function need not perform consistency checks * for the imported parameters. In particular, parameters that * are not needed by the implementation might be silently * discarded and left unchecked. To check the consistency * of the key material, see mbedtls_rsa_check_privkey(). * * \param ctx The initialized RSA context holding imported parameters. * * \return \c 0 on success. * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations * failed. * */ int mbedtls_rsa_complete(mbedtls_rsa_context *ctx); /** * \brief This function exports the core parameters of an RSA key. * * If this function runs successfully, the non-NULL buffers * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully * written, with additional unused space filled leading by * zero Bytes. * * Possible reasons for returning * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    *
  • An alternative RSA implementation is in use, which * stores the key externally, and either cannot or should * not export it into RAM.
  • *
  • A SW or HW implementation might not support a certain * deduction. For example, \p P, \p Q from \p N, \p D, * and \p E if the former are not part of the * implementation.
* * If the function fails due to an unsupported operation, * the RSA context stays intact and remains usable. * * \param ctx The initialized RSA context. * \param N The MPI to hold the RSA modulus. * This may be \c NULL if this field need not be exported. * \param P The MPI to hold the first prime factor of \p N. * This may be \c NULL if this field need not be exported. * \param Q The MPI to hold the second prime factor of \p N. * This may be \c NULL if this field need not be exported. * \param D The MPI to hold the private exponent. * This may be \c NULL if this field need not be exported. * \param E The MPI to hold the public exponent. * This may be \c NULL if this field need not be exported. * * \return \c 0 on success. * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the * requested parameters cannot be done due to missing * functionality or because of security policies. * \return A non-zero return code on any other failure. * */ int mbedtls_rsa_export(const mbedtls_rsa_context *ctx, mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, mbedtls_mpi *D, mbedtls_mpi *E); /** * \brief This function exports core parameters of an RSA key * in raw big-endian binary format. * * If this function runs successfully, the non-NULL buffers * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully * written, with additional unused space filled leading by * zero Bytes. * * Possible reasons for returning * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    *
  • An alternative RSA implementation is in use, which * stores the key externally, and either cannot or should * not export it into RAM.
  • *
  • A SW or HW implementation might not support a certain * deduction. For example, \p P, \p Q from \p N, \p D, * and \p E if the former are not part of the * implementation.
* If the function fails due to an unsupported operation, * the RSA context stays intact and remains usable. * * \note The length parameters are ignored if the corresponding * buffer pointers are NULL. * * \param ctx The initialized RSA context. * \param N The Byte array to store the RSA modulus, * or \c NULL if this field need not be exported. * \param N_len The size of the buffer for the modulus. * \param P The Byte array to hold the first prime factor of \p N, * or \c NULL if this field need not be exported. * \param P_len The size of the buffer for the first prime factor. * \param Q The Byte array to hold the second prime factor of \p N, * or \c NULL if this field need not be exported. * \param Q_len The size of the buffer for the second prime factor. * \param D The Byte array to hold the private exponent, * or \c NULL if this field need not be exported. * \param D_len The size of the buffer for the private exponent. * \param E The Byte array to hold the public exponent, * or \c NULL if this field need not be exported. * \param E_len The size of the buffer for the public exponent. * * \return \c 0 on success. * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the * requested parameters cannot be done due to missing * functionality or because of security policies. * \return A non-zero return code on any other failure. */ int mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx, unsigned char *N, size_t N_len, unsigned char *P, size_t P_len, unsigned char *Q, size_t Q_len, unsigned char *D, size_t D_len, unsigned char *E, size_t E_len); /** * \brief This function exports CRT parameters of a private RSA key. * * \note Alternative RSA implementations not using CRT-parameters * internally can implement this function based on * mbedtls_rsa_deduce_opt(). * * \param ctx The initialized RSA context. * \param DP The MPI to hold \c D modulo `P-1`, * or \c NULL if it need not be exported. * \param DQ The MPI to hold \c D modulo `Q-1`, * or \c NULL if it need not be exported. * \param QP The MPI to hold modular inverse of \c Q modulo \c P, * or \c NULL if it need not be exported. * * \return \c 0 on success. * \return A non-zero error code on failure. * */ int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP); /** * \brief This function retrieves the length of the RSA modulus in bits. * * \param ctx The initialized RSA context. * * \return The length of the RSA modulus in bits. * */ size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx); /** * \brief This function retrieves the length of RSA modulus in Bytes. * * \param ctx The initialized RSA context. * * \return The length of the RSA modulus in Bytes. * */ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx); /** * \brief This function generates an RSA keypair. * * \note mbedtls_rsa_init() must be called before this function, * to set up the RSA context. * * \param ctx The initialized RSA context used to hold the key. * \param f_rng The RNG function to be used for key generation. * This is mandatory and must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. * This may be \c NULL if \p f_rng doesn't need a context. * \param nbits The size of the public key in bits. * \param exponent The public exponent to use. For example, \c 65537. * This must be odd and greater than \c 1. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, unsigned int nbits, int exponent); /** * \brief This function checks if a context contains at least an RSA * public key. * * If the function runs successfully, it is guaranteed that * enough information is present to perform an RSA public key * operation using mbedtls_rsa_public(). * * \param ctx The initialized RSA context to check. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * */ int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx); /** * \brief This function checks if a context contains an RSA private key * and perform basic consistency checks. * * \note The consistency checks performed by this function not only * ensure that mbedtls_rsa_private() can be called successfully * on the given context, but that the various parameters are * mutually consistent with high probability, in the sense that * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. * * \warning This function should catch accidental misconfigurations * like swapping of parameters, but it cannot establish full * trust in neither the quality nor the consistency of the key * material that was used to setup the given RSA context: *
  • Consistency: Imported parameters that are irrelevant * for the implementation might be silently dropped. If dropped, * the current function does not have access to them, * and therefore cannot check them. See mbedtls_rsa_complete(). * If you want to check the consistency of the entire * content of a PKCS1-encoded RSA private key, for example, you * should use mbedtls_rsa_validate_params() before setting * up the RSA context. * Additionally, if the implementation performs empirical checks, * these checks substantiate but do not guarantee consistency.
  • *
  • Quality: This function is not expected to perform * extended quality assessments like checking that the prime * factors are safe. Additionally, it is the responsibility of the * user to ensure the trustworthiness of the source of his RSA * parameters, which goes beyond what is effectively checkable * by the library.
* * \param ctx The initialized RSA context to check. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx); /** * \brief This function checks a public-private RSA key pair. * * It checks each of the contexts, and makes sure they match. * * \param pub The initialized RSA context holding the public key. * \param prv The initialized RSA context holding the private key. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv); /** * \brief This function performs an RSA public key operation. * * \param ctx The initialized RSA context to use. * \param input The input buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \note This function does not handle message padding. * * \note Make sure to set \p input[0] = 0 or ensure that * input is smaller than \c N. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_public(mbedtls_rsa_context *ctx, const unsigned char *input, unsigned char *output); /** * \brief This function performs an RSA private key operation. * * \note Blinding is used if and only if a PRNG is provided. * * \note If blinding is used, both the base of exponentiation * and the exponent are blinded, providing protection * against some side-channel attacks. * * \warning It is deprecated and a security risk to not provide * a PRNG here and thereby prevent the use of blinding. * Future versions of the library may enforce the presence * of a PRNG. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function, used for blinding. It is mandatory. * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context. * \param input The input buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * */ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *input, unsigned char *output); /** * \brief This function adds the message padding, then performs an RSA * operation. * * It is the generic wrapper for performing a PKCS#1 encryption * operation. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG to use. It is used for padding generation * and it is mandatory. * \param p_rng The RNG context to be passed to \p f_rng. May be * \c NULL if \p f_rng doesn't need a context argument. * \param ilen The length of the plaintext in Bytes. * \param input The input data to encrypt. This must be a readable * buffer of size \p ilen Bytes. It may be \c NULL if * `ilen == 0`. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t ilen, const unsigned char *input, unsigned char *output); /** * \brief This function performs a PKCS#1 v1.5 encryption operation * (RSAES-PKCS1-v1_5-ENCRYPT). * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function to use. It is mandatory and used for * padding generation. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * \param ilen The length of the plaintext in Bytes. * \param input The input data to encrypt. This must be a readable * buffer of size \p ilen Bytes. It may be \c NULL if * `ilen == 0`. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t ilen, const unsigned char *input, unsigned char *output); /** * \brief This function performs a PKCS#1 v2.1 OAEP encryption * operation (RSAES-OAEP-ENCRYPT). * * \note The output buffer must be as large as the size * of ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function to use. This is needed for padding * generation and is mandatory. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * \param label The buffer holding the custom label to use. * This must be a readable buffer of length \p label_len * Bytes. It may be \c NULL if \p label_len is \c 0. * \param label_len The length of the label in Bytes. * \param ilen The length of the plaintext buffer \p input in Bytes. * \param input The input data to encrypt. This must be a readable * buffer of size \p ilen Bytes. It may be \c NULL if * `ilen == 0`. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *label, size_t label_len, size_t ilen, const unsigned char *input, unsigned char *output); /** * \brief This function performs an RSA operation, then removes the * message padding. * * It is the generic wrapper for performing a PKCS#1 decryption * operation. * * \warning When \p ctx->padding is set to #MBEDTLS_RSA_PKCS_V15, * mbedtls_rsa_rsaes_pkcs1_v15_decrypt() is called, which is an * inherently dangerous function (CWE-242). * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N (for example, * 128 Bytes if RSA-1024 is used) to be able to hold an * arbitrary decrypted message. If it is not large enough to * hold the decryption of the particular ciphertext provided, * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. This is used for blinding and is * mandatory; see mbedtls_rsa_private() for more. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context. * \param olen The address at which to store the length of * the plaintext. This must not be \c NULL. * \param input The ciphertext buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The buffer used to hold the plaintext. This must * be a writable buffer of length \p output_max_len Bytes. * \param output_max_len The length in Bytes of the output buffer \p output. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); /** * \brief This function performs a PKCS#1 v1.5 decryption * operation (RSAES-PKCS1-v1_5-DECRYPT). * * \warning This is an inherently dangerous function (CWE-242). Unless * it is used in a side channel free and safe way (eg. * implementing the TLS protocol as per 7.4.7.1 of RFC 5246), * the calling code is vulnerable. * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N, for example, * 128 Bytes if RSA-1024 is used, to be able to hold an * arbitrary decrypted message. If it is not large enough to * hold the decryption of the particular ciphertext provided, * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. This is used for blinding and is * mandatory; see mbedtls_rsa_private() for more. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context. * \param olen The address at which to store the length of * the plaintext. This must not be \c NULL. * \param input The ciphertext buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The buffer used to hold the plaintext. This must * be a writable buffer of length \p output_max_len Bytes. * \param output_max_len The length in Bytes of the output buffer \p output. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * */ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); /** * \brief This function performs a PKCS#1 v2.1 OAEP decryption * operation (RSAES-OAEP-DECRYPT). * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N, for * example, 128 Bytes if RSA-1024 is used, to be able to * hold an arbitrary decrypted message. If it is not * large enough to hold the decryption of the particular * ciphertext provided, the function returns * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. This is used for blinding and is * mandatory. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context. * \param label The buffer holding the custom label to use. * This must be a readable buffer of length \p label_len * Bytes. It may be \c NULL if \p label_len is \c 0. * \param label_len The length of the label in Bytes. * \param olen The address at which to store the length of * the plaintext. This must not be \c NULL. * \param input The ciphertext buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The buffer used to hold the plaintext. This must * be a writable buffer of length \p output_max_len Bytes. * \param output_max_len The length in Bytes of the output buffer \p output. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); /** * \brief This function performs a private RSA operation to sign * a message digest using PKCS#1. * * It is the generic wrapper for performing a PKCS#1 * signature. * * \note The \p sig buffer must be as large as the size * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \note For PKCS#1 v2.1 encoding, see comments on * mbedtls_rsa_rsassa_pss_sign() for details on * \p md_alg and \p hash_id. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function to use. This is mandatory and * must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); /** * \brief This function performs a PKCS#1 v1.5 signature * operation (RSASSA-PKCS1-v1_5-SIGN). * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. This is used for blinding and is * mandatory; see mbedtls_rsa_private() for more. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); #if defined(MBEDTLS_PKCS1_V21) /** * \brief This function performs a PKCS#1 v2.1 PSS signature * operation (RSASSA-PSS-SIGN). * * \note The \c hash_id set in \p ctx by calling * mbedtls_rsa_set_padding() selects the hash used for the * encoding operation and for the mask generation function * (MGF1). For more details on the encoding operation and the * mask generation function, consult RFC-3447: Public-Key * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography * Specifications. * * \note This function enforces that the provided salt length complies * with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 v2.2) §9.1.1 * step 3. The constraint is that the hash length plus the salt * length plus 2 bytes must be at most the key length. If this * constraint is not met, this function returns * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. It is mandatory and must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param saltlen The length of the salt that should be used. * If passed #MBEDTLS_RSA_SALT_LEN_ANY, the function will use * the largest possible salt length up to the hash length, * which is the largest permitted by some standards including * FIPS 186-4 §5.5. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, int saltlen, unsigned char *sig); /** * \brief This function performs a PKCS#1 v2.1 PSS signature * operation (RSASSA-PSS-SIGN). * * \note The \c hash_id set in \p ctx by calling * mbedtls_rsa_set_padding() selects the hash used for the * encoding operation and for the mask generation function * (MGF1). For more details on the encoding operation and the * mask generation function, consult RFC-3447: Public-Key * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography * Specifications. * * \note This function always uses the maximum possible salt size, * up to the length of the payload hash. This choice of salt * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 * v2.2) §9.1.1 step 3. Furthermore this function enforces a * minimum salt size which is the hash size minus 2 bytes. If * this minimum size is too large given the key size (the salt * size, plus the hash size, plus 2 bytes must be no more than * the key size in bytes), this function returns * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. It is mandatory and must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); #endif /* MBEDTLS_PKCS1_V21 */ /** * \brief This function performs a public RSA operation and checks * the message digest. * * This is the generic wrapper for performing a PKCS#1 * verification. * * \note For PKCS#1 v2.1 encoding, see comments on * mbedtls_rsa_rsassa_pss_verify() about \c md_alg and * \c hash_id. * * \param ctx The initialized RSA public key context to use. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig); /** * \brief This function performs a PKCS#1 v1.5 verification * operation (RSASSA-PKCS1-v1_5-VERIFY). * * \param ctx The initialized RSA public key context to use. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig); /** * \brief This function performs a PKCS#1 v2.1 PSS verification * operation (RSASSA-PSS-VERIFY). * * \note The \c hash_id set in \p ctx by calling * mbedtls_rsa_set_padding() selects the hash used for the * encoding operation and for the mask generation function * (MGF1). For more details on the encoding operation and the * mask generation function, consult RFC-3447: Public-Key * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography * Specifications. If the \c hash_id set in \p ctx by * mbedtls_rsa_set_padding() is #MBEDTLS_MD_NONE, the \p md_alg * parameter is used. * * \param ctx The initialized RSA public key context to use. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig); /** * \brief This function performs a PKCS#1 v2.1 PSS verification * operation (RSASSA-PSS-VERIFY). * * \note The \p sig buffer must be as large as the size * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \note The \c hash_id set in \p ctx by mbedtls_rsa_set_padding() is * ignored. * * \param ctx The initialized RSA public key context to use. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param mgf1_hash_id The message digest algorithm used for the * verification operation and the mask generation * function (MGF1). For more details on the encoding * operation and the mask generation function, consult * RFC-3447: Public-Key Cryptography Standards * (PKCS) #1 v2.1: RSA Cryptography * Specifications. * \param expected_salt_len The length of the salt used in padding. Use * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, mbedtls_md_type_t mgf1_hash_id, int expected_salt_len, const unsigned char *sig); /** * \brief This function copies the components of an RSA context. * * \param dst The destination context. This must be initialized. * \param src The source context. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. */ int mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src); /** * \brief This function frees the components of an RSA key. * * \param ctx The RSA context to free. May be \c NULL, in which case * this function is a no-op. If it is not \c NULL, it must * point to an initialized RSA context. */ void mbedtls_rsa_free(mbedtls_rsa_context *ctx); #if defined(MBEDTLS_SELF_TEST) /** * \brief The RSA checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_rsa_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* rsa.h */ webfakes/src/mbedtls/include/mbedtls/platform_time.h0000644000176200001440000000362214740737024022365 0ustar liggesusers/** * \file platform_time.h * * \brief Mbed TLS Platform time abstraction */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PLATFORM_TIME_H #define MBEDTLS_PLATFORM_TIME_H #include "mbedtls/build_info.h" #ifdef __cplusplus extern "C" { #endif /* * The time_t datatype */ #if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; #else /* For time_t */ #include typedef time_t mbedtls_time_t; #endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ #if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) typedef MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO mbedtls_ms_time_t; #else #include #include typedef int64_t mbedtls_ms_time_t; #endif /* MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO */ /** * \brief Get time in milliseconds. * * \return Monotonically-increasing current time in milliseconds. * * \note Define MBEDTLS_PLATFORM_MS_TIME_ALT to be able to provide an * alternative implementation * * \warning This function returns a monotonically-increasing time value from a * start time that will differ from platform to platform, and possibly * from run to run of the process. * */ mbedtls_ms_time_t mbedtls_ms_time(void); /* * The function pointers for time */ #if defined(MBEDTLS_PLATFORM_TIME_ALT) extern mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *time); /** * \brief Set your own time function pointer * * \param time_func the time function implementation * * \return 0 */ int mbedtls_platform_set_time(mbedtls_time_t (*time_func)(mbedtls_time_t *time)); #else #if defined(MBEDTLS_PLATFORM_TIME_MACRO) #define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO #else #define mbedtls_time time #endif /* MBEDTLS_PLATFORM_TIME_MACRO */ #endif /* MBEDTLS_PLATFORM_TIME_ALT */ #ifdef __cplusplus } #endif #endif /* platform_time.h */ webfakes/src/mbedtls/include/mbedtls/x509.h0000644000176200001440000005134414740737024020234 0ustar liggesusers/** * \file x509.h * * \brief X.509 generic defines and structures */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_H #define MBEDTLS_X509_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #include "mbedtls/pk.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif /** * \addtogroup x509_module * \{ */ #if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) /** * Maximum number of intermediate CAs in a verification chain. * That is, maximum length of the chain, excluding the end-entity certificate * and the trusted root certificate. * * Set this to a low value to prevent an adversary from making you waste * resources verifying an overlong certificate chain. */ #define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 #endif /** * \name X509 Error codes * \{ */ /** Unavailable feature, e.g. RSA hashing/encryption combination. */ #define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /** Requested OID is unknown. */ #define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /** The CRT/CRL/CSR format is invalid, e.g. different type expected. */ #define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /** The CRT/CRL/CSR version element is invalid. */ #define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /** The serial tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /** The algorithm tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /** The name tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /** The date tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /** The signature tag or value invalid. */ #define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /** The extension tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /** CRT/CRL/CSR has an unsupported version number. */ #define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /** Signature algorithm (oid) is unsupported. */ #define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /** Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ #define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /** Certificate verification failed, e.g. CRL, CA or signature check failed. */ #define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /** Format not recognized as DER or PEM. */ #define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /** Input invalid. */ #define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /** Allocation of memory failed. */ #define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /** Read/write of file failed. */ #define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /** Destination buffer is too small. */ #define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /** A fatal error occurred, eg the chain is too long or the vrfy callback failed. */ #define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /** \} name X509 Error codes */ /** * \name X509 Verify codes * \{ */ /* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ #define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ #define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ #define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ #define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ #define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ #define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ #define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ #define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ #define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ #define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ #define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ #define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ #define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ #define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ #define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ #define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ #define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ #define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ #define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ #define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ /** \} name X509 Verify codes */ /** \} addtogroup x509_module */ /* * X.509 v3 Subject Alternative Name types. * otherName [0] OtherName, * rfc822Name [1] IA5String, * dNSName [2] IA5String, * x400Address [3] ORAddress, * directoryName [4] Name, * ediPartyName [5] EDIPartyName, * uniformResourceIdentifier [6] IA5String, * iPAddress [7] OCTET STRING, * registeredID [8] OBJECT IDENTIFIER */ #define MBEDTLS_X509_SAN_OTHER_NAME 0 #define MBEDTLS_X509_SAN_RFC822_NAME 1 #define MBEDTLS_X509_SAN_DNS_NAME 2 #define MBEDTLS_X509_SAN_X400_ADDRESS_NAME 3 #define MBEDTLS_X509_SAN_DIRECTORY_NAME 4 #define MBEDTLS_X509_SAN_EDI_PARTY_NAME 5 #define MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER 6 #define MBEDTLS_X509_SAN_IP_ADDRESS 7 #define MBEDTLS_X509_SAN_REGISTERED_ID 8 /* * X.509 v3 Key Usage Extension flags * Reminder: update mbedtls_x509_info_key_usage() when adding new flags. */ #define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ #define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ #define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ #define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ #define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ #define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ #define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ #define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ #define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ /* * Netscape certificate types * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) */ #define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ #define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ #define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ #define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ #define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ #define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ #define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ #define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ /* * X.509 extension types * * Comments refer to the status for using certificates. Status can be * different for writing certificates or reading CRLs or CSRs. * * Those are defined in oid.h as oid.c needs them in a data structure. Since * these were previously defined here, let's have aliases for compatibility. */ #define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER #define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER #define MBEDTLS_X509_EXT_KEY_USAGE MBEDTLS_OID_X509_EXT_KEY_USAGE #define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES #define MBEDTLS_X509_EXT_POLICY_MAPPINGS MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS #define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME /* Supported (DNS) */ #define MBEDTLS_X509_EXT_ISSUER_ALT_NAME MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME #define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS #define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS /* Supported */ #define MBEDTLS_X509_EXT_NAME_CONSTRAINTS MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS #define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS #define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE #define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS #define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY #define MBEDTLS_X509_EXT_FRESHEST_CRL MBEDTLS_OID_X509_EXT_FRESHEST_CRL #define MBEDTLS_X509_EXT_NS_CERT_TYPE MBEDTLS_OID_X509_EXT_NS_CERT_TYPE /* * Storage format identifiers * Recognized formats: PEM and DER */ #define MBEDTLS_X509_FORMAT_DER 1 #define MBEDTLS_X509_FORMAT_PEM 2 #define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ #ifdef __cplusplus extern "C" { #endif /** * \addtogroup x509_module * \{ */ /** * \name Structures for parsing X.509 certificates, CRLs and CSRs * \{ */ /** * Type-length-value structure that allows for ASN1 using DER. */ typedef mbedtls_asn1_buf mbedtls_x509_buf; /** * Container for ASN1 bit strings. */ typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; /** * Container for ASN1 named information objects. * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). */ typedef mbedtls_asn1_named_data mbedtls_x509_name; /** * Container for a sequence of ASN.1 items */ typedef mbedtls_asn1_sequence mbedtls_x509_sequence; /* * Container for the fields of the Authority Key Identifier object */ typedef struct mbedtls_x509_authority { mbedtls_x509_buf keyIdentifier; mbedtls_x509_sequence authorityCertIssuer; mbedtls_x509_buf authorityCertSerialNumber; mbedtls_x509_buf raw; } mbedtls_x509_authority; /** Container for date and time (precision in seconds). */ typedef struct mbedtls_x509_time { int year, mon, day; /**< Date. */ int hour, min, sec; /**< Time. */ } mbedtls_x509_time; /** * From RFC 5280 section 4.2.1.6: * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * Future versions of the library may add new fields to this structure or * to its embedded union and structure. */ typedef struct mbedtls_x509_san_other_name { /** * The type_id is an OID as defined in RFC 5280. * To check the value of the type id, you should use * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf. */ mbedtls_x509_buf type_id; /**< The type id. */ union { /** * From RFC 4108 section 5: * HardwareModuleName ::= SEQUENCE { * hwType OBJECT IDENTIFIER, * hwSerialNum OCTET STRING } */ struct { mbedtls_x509_buf oid; /**< The object identifier. */ mbedtls_x509_buf val; /**< The named value. */ } hardware_module_name; } value; } mbedtls_x509_san_other_name; /** * A structure for holding the parsed Subject Alternative Name, * according to type. * * Future versions of the library may add new fields to this structure or * to its embedded union and structure. */ typedef struct mbedtls_x509_subject_alternative_name { int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */ union { mbedtls_x509_san_other_name other_name; mbedtls_x509_name directory_name; mbedtls_x509_buf unstructured_name; /**< The buffer for the unstructured types. rfc822Name, dnsName and uniformResourceIdentifier are currently supported. */ } san; /**< A union of the supported SAN types */ } mbedtls_x509_subject_alternative_name; typedef struct mbedtls_x509_san_list { mbedtls_x509_subject_alternative_name node; struct mbedtls_x509_san_list *next; } mbedtls_x509_san_list; /** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ /** \} addtogroup x509_module */ /** * \brief Store the certificate DN in printable form into buf; * no more than size characters will be written. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param dn The X509 name to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn); /** * \brief Convert the certificate DN string \p name into * a linked list of mbedtls_x509_name (equivalent to * mbedtls_asn1_named_data). * * \note This function allocates a linked list, and places the head * pointer in \p head. This list must later be freed by a * call to mbedtls_asn1_free_named_data_list(). * * \param[out] head Address in which to store the pointer to the head of the * allocated list of mbedtls_x509_name * \param[in] name The string representation of a DN to convert * * \return 0 on success, or a negative error code. */ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name); /** * \brief Return the next relative DN in an X509 name. * * \note Intended use is to compare function result to dn->next * in order to detect boundaries of multi-valued RDNs. * * \param dn Current node in the X509 name * * \return Pointer to the first attribute-value pair of the * next RDN in sequence, or NULL if end is reached. */ static inline mbedtls_x509_name *mbedtls_x509_dn_get_next( mbedtls_x509_name *dn) { while (dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL) { dn = dn->next; } return dn->next; } /** * \brief Store the certificate serial in printable form into buf; * no more than size characters will be written. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param serial The X509 serial to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial); /** * \brief Compare pair of mbedtls_x509_time. * * \param t1 mbedtls_x509_time to compare * \param t2 mbedtls_x509_time to compare * * \return < 0 if t1 is before t2 * 0 if t1 equals t2 * > 0 if t1 is after t2 */ int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2); #if defined(MBEDTLS_HAVE_TIME_DATE) /** * \brief Fill mbedtls_x509_time with provided mbedtls_time_t. * * \param tt mbedtls_time_t to convert * \param now mbedtls_x509_time to fill with converted mbedtls_time_t * * \return \c 0 on success * \return A non-zero return value on failure. */ int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now); #endif /* MBEDTLS_HAVE_TIME_DATE */ /** * \brief Check a given mbedtls_x509_time against the system time * and tell if it's in the past. * * \note Intended usage is "if( is_past( valid_to ) ) ERROR". * Hence the return value of 1 if on internal errors. * * \param to mbedtls_x509_time to check * * \return 1 if the given time is in the past or an error occurred, * 0 otherwise. */ int mbedtls_x509_time_is_past(const mbedtls_x509_time *to); /** * \brief Check a given mbedtls_x509_time against the system time * and tell if it's in the future. * * \note Intended usage is "if( is_future( valid_from ) ) ERROR". * Hence the return value of 1 if on internal errors. * * \param from mbedtls_x509_time to check * * \return 1 if the given time is in the future or an error occurred, * 0 otherwise. */ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from); /** * \brief This function parses an item in the SubjectAlternativeNames * extension. Please note that this function might allocate * additional memory for a subject alternative name, thus * mbedtls_x509_free_subject_alt_name has to be called * to dispose of this additional memory afterwards. * * \param san_buf The buffer holding the raw data item of the subject * alternative name. * \param san The target structure to populate with the parsed presentation * of the subject alternative name encoded in \p san_buf. * * \note Supported GeneralName types, as defined in RFC 5280: * "rfc822Name", "dnsName", "directoryName", * "uniformResourceIdentifier" and "hardware_module_name" * of type "otherName", as defined in RFC 4108. * * \note This function should be called on a single raw data of * subject alternative name. For example, after successful * certificate parsing, one must iterate on every item in the * \c crt->subject_alt_names sequence, and pass it to * this function. * * \warning The target structure contains pointers to the raw data of the * parsed certificate, and its lifetime is restricted by the * lifetime of the certificate. * * \return \c 0 on success * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported * SAN type. * \return Another negative value for any other failure. */ int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, mbedtls_x509_subject_alternative_name *san); /** * \brief Unallocate all data related to subject alternative name * * \param san SAN structure - extra memory owned by this structure will be freed */ void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san); /** * \brief This function parses a CN string as an IP address. * * \param cn The CN string to parse. CN string MUST be null-terminated. * \param dst The target buffer to populate with the binary IP address. * The buffer MUST be 16 bytes to save IPv6, and should be * 4-byte aligned if the result will be used as struct in_addr. * e.g. uint32_t dst[4] * * \note \p cn is parsed as an IPv6 address if string contains ':', * else \p cn is parsed as an IPv4 address. * * \return Length of binary IP address; num bytes written to target. * \return \c 0 on failure to parse CN string as an IP address. */ size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst); #define MBEDTLS_X509_SAFE_SNPRINTF \ do { \ if (ret < 0 || (size_t) ret >= n) \ return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; \ \ n -= (size_t) ret; \ p += (size_t) ret; \ } while (0) #ifdef __cplusplus } #endif #endif /* MBEDTLS_X509_H */ webfakes/src/mbedtls/include/mbedtls/aria.h0000644000176200001440000003522414740737024020442 0ustar liggesusers/** * \file aria.h * * \brief ARIA block cipher * * The ARIA algorithm is a symmetric block cipher that can encrypt and * decrypt information. It is defined by the Korean Agency for * Technology and Standards (KATS) in KS X 1213:2004 (in * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) * and also described by the IETF in RFC 5794. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ARIA_H #define MBEDTLS_ARIA_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #include "mbedtls/platform_util.h" #define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ #define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ #define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ #define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maximum number of rounds in ARIA. */ #define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ /** Bad input data. */ #define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /** Invalid data input length. */ #define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_ARIA_ALT) // Regular implementation // /** * \brief The ARIA context-type definition. */ typedef struct mbedtls_aria_context { unsigned char MBEDTLS_PRIVATE(nr); /*!< The number of rounds (12, 14 or 16) */ /*! The ARIA round keys. */ uint32_t MBEDTLS_PRIVATE(rk)[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; } mbedtls_aria_context; #else /* MBEDTLS_ARIA_ALT */ #include "aria_alt.h" #endif /* MBEDTLS_ARIA_ALT */ /** * \brief This function initializes the specified ARIA context. * * It must be the first API called before using * the context. * * \param ctx The ARIA context to initialize. This must not be \c NULL. */ void mbedtls_aria_init(mbedtls_aria_context *ctx); /** * \brief This function releases and clears the specified ARIA context. * * \param ctx The ARIA context to clear. This may be \c NULL, in which * case this function returns immediately. If it is not \c NULL, * it must point to an initialized ARIA context. */ void mbedtls_aria_free(mbedtls_aria_context *ctx); /** * \brief This function sets the encryption key. * * \param ctx The ARIA context to which the key should be bound. * This must be initialized. * \param key The encryption key. This must be a readable buffer * of size \p keybits Bits. * \param keybits The size of \p key in Bits. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief This function sets the decryption key. * * \param ctx The ARIA context to which the key should be bound. * This must be initialized. * \param key The decryption key. This must be a readable buffer * of size \p keybits Bits. * \param keybits The size of data passed. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief This function performs an ARIA single-block encryption or * decryption operation. * * It performs encryption or decryption (depending on whether * the key was set for encryption on decryption) on the input * data buffer defined in the \p input parameter. * * mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or * mbedtls_aria_setkey_dec() must be called before the first * call to this API with the same context. * * \param ctx The ARIA context to use for encryption or decryption. * This must be initialized and bound to a key. * \param input The 16-Byte buffer holding the input data. * \param output The 16-Byte buffer holding the output data. * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx, const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], unsigned char output[MBEDTLS_ARIA_BLOCKSIZE]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief This function performs an ARIA-CBC encryption or decryption operation * on full blocks. * * It performs the operation defined in the \p mode * parameter (encrypt/decrypt), on the input data buffer defined in * the \p input parameter. * * It can be called as many times as needed, until all the input * data is processed. mbedtls_aria_init(), and either * mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called * before the first call to this API with the same context. * * \note This function operates on aligned blocks, that is, the input size * must be a multiple of the ARIA block size of 16 Bytes. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the IV, you should * either save it manually or use the cipher module instead. * * * \param ctx The ARIA context to use for encryption or decryption. * This must be initialized and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_ARIA_ENCRYPT for encryption, or * #MBEDTLS_ARIA_DECRYPT for decryption. * \param length The length of the input data in Bytes. This must be a * multiple of the block size (16 Bytes). * \param iv Initialization vector (updated after use). * This must be a readable buffer of size 16 Bytes. * \param input The buffer holding the input data. This must * be a readable buffer of length \p length Bytes. * \param output The buffer holding the output data. This must * be a writable buffer of length \p length Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx, int mode, size_t length, unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /** * \brief This function performs an ARIA-CFB128 encryption or decryption * operation. * * It performs the operation defined in the \p mode * parameter (encrypt or decrypt), on the input data buffer * defined in the \p input parameter. * * For CFB, you must set up the context with mbedtls_aria_setkey_enc(), * regardless of whether you are performing an encryption or decryption * operation, that is, regardless of the \p mode parameter. This is * because CFB mode uses the same key schedule for encryption and * decryption. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the * IV, you must either save it manually or use the cipher * module instead. * * * \param ctx The ARIA context to use for encryption or decryption. * This must be initialized and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_ARIA_ENCRYPT for encryption, or * #MBEDTLS_ARIA_DECRYPT for decryption. * \param length The length of the input data \p input in Bytes. * \param iv_off The offset in IV (updated after use). * This must not be larger than 15. * \param iv The initialization vector (updated after use). * This must be a readable buffer of size 16 Bytes. * \param input The buffer holding the input data. This must * be a readable buffer of length \p length Bytes. * \param output The buffer holding the output data. This must * be a writable buffer of length \p length Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /** * \brief This function performs an ARIA-CTR encryption or decryption * operation. * * Due to the nature of CTR, you must use the same key schedule * for both encryption and decryption operations. Therefore, you * must use the context initialized with mbedtls_aria_setkey_enc() * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT. * * \warning You must never reuse a nonce value with the same key. Doing so * would void the encryption for the two messages encrypted with * the same nonce and key. * * There are two common strategies for managing nonces with CTR: * * 1. You can handle everything as a single message processed over * successive calls to this function. In that case, you want to * set \p nonce_counter and \p nc_off to 0 for the first call, and * then preserve the values of \p nonce_counter, \p nc_off and \p * stream_block across calls to this function as they will be * updated by this function. * * With this strategy, you must not encrypt more than 2**128 * blocks of data with the same key. * * 2. You can encrypt separate messages by dividing the \p * nonce_counter buffer in two areas: the first one used for a * per-message nonce, handled by yourself, and the second one * updated by this function internally. * * For example, you might reserve the first 12 bytes for the * per-message nonce, and the last 4 bytes for internal use. In that * case, before calling this function on a new message you need to * set the first 12 bytes of \p nonce_counter to your chosen nonce * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p * stream_block to be ignored). That way, you can encrypt at most * 2**96 messages of up to 2**32 blocks each with the same key. * * The per-message nonce (or information sufficient to reconstruct * it) needs to be communicated with the ciphertext and must be unique. * The recommended way to ensure uniqueness is to use a message * counter. An alternative is to generate random nonces, but this * limits the number of messages that can be securely encrypted: * for example, with 96-bit random nonces, you should not encrypt * more than 2**32 messages with the same key. * * Note that for both strategies, sizes are measured in blocks and * that an ARIA block is 16 bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its * content must not be written to insecure storage and should be * securely discarded as soon as it's no longer needed. * * \param ctx The ARIA context to use for encryption or decryption. * This must be initialized and bound to a key. * \param length The length of the input data \p input in Bytes. * \param nc_off The offset in Bytes in the current \p stream_block, * for resuming within the current cipher stream. The * offset pointer should be \c 0 at the start of a * stream. This must not be larger than \c 15 Bytes. * \param nonce_counter The 128-bit nonce and counter. This must point to * a read/write buffer of length \c 16 bytes. * \param stream_block The saved stream block for resuming. This must * point to a read/write buffer of length \c 16 bytes. * This is overwritten by the function. * \param input The buffer holding the input data. This must * be a readable buffer of length \p length Bytes. * \param output The buffer holding the output data. This must * be a writable buffer of length \p length Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine. * * \return \c 0 on success, or \c 1 on failure. */ int mbedtls_aria_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* aria.h */ webfakes/src/mbedtls/include/mbedtls/ssl_ciphersuites.h0000644000176200001440000005751614740737024023126 0ustar liggesusers/** * \file ssl_ciphersuites.h * * \brief SSL Ciphersuites for Mbed TLS */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CIPHERSUITES_H #define MBEDTLS_SSL_CIPHERSUITES_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/pk.h" #include "mbedtls/cipher.h" #include "mbedtls/md.h" #ifdef __cplusplus extern "C" { #endif /* * Supported ciphersuites (Official IANA names) */ #define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ #define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ #define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ #define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ #define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ #define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 #define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 #define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ #define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 #define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C #define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 #define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 #define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 #define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE #define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF #define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ #define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 #define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ #define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ #define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 #define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 #define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ #define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A #define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F #define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 #define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 #define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 #define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B #define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 #define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 #define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 #define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 #define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 #define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 #define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 #define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 #define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A #define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B #define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ /* The last two are named with PSK_DHE in the RFC, which looks like a typo */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ #define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ /* RFC 7905 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ /* RFC 8446, Appendix B.4 */ #define MBEDTLS_TLS1_3_AES_128_GCM_SHA256 0x1301 /**< TLS 1.3 */ #define MBEDTLS_TLS1_3_AES_256_GCM_SHA384 0x1302 /**< TLS 1.3 */ #define MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256 0x1303 /**< TLS 1.3 */ #define MBEDTLS_TLS1_3_AES_128_CCM_SHA256 0x1304 /**< TLS 1.3 */ #define MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256 0x1305 /**< TLS 1.3 */ /* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below */ typedef enum { MBEDTLS_KEY_EXCHANGE_NONE = 0, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_KEY_EXCHANGE_DHE_RSA, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_KEY_EXCHANGE_RSA_PSK, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, MBEDTLS_KEY_EXCHANGE_ECJPAKE, } mbedtls_key_exchange_type_t; /* Key exchanges using a certificate */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED #endif /* Key exchanges in either TLS 1.2 or 1.3 which are using an ECDSA * signature */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #define MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED #endif #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #define MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED #endif /* Key exchanges allowing client certificate requests. * * Note: that's almost the same as MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED * above, except RSA-PSK uses a server certificate but no client cert. * * Note: this difference is specific to TLS 1.2, as with TLS 1.3, things are * more symmetrical: client certs and server certs are either both allowed * (Ephemeral mode) or both disallowed (PSK and PKS-Ephemeral modes). */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED #endif /* Helper to state that certificate-based client authentication through ECDSA * is supported in TLS 1.2 */ #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) && \ defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) #define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED #endif /* ECDSA required for certificates in either TLS 1.2 or 1.3 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED #endif /* Key exchanges involving server signature in ServerKeyExchange */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED #endif /* Key exchanges using ECDH */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED #endif /* Key exchanges that don't involve ephemeral keys */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED #endif /* Key exchanges that involve ephemeral keys */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED #endif /* Key exchanges using a PSK */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED #endif /* Key exchanges using DHE */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED #endif /* Key exchanges using ECDHE */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED #endif /* TLS 1.2 key exchanges using ECDH or ECDHE*/ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED #endif /* TLS 1.3 PSK key exchanges */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED #endif /* TLS 1.2 or 1.3 key exchanges with PSK */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) #define MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED #endif /* TLS 1.3 ephemeral key exchanges */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED #endif /* TLS 1.3 key exchanges using ECDHE */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) && \ defined(PSA_WANT_ALG_ECDH) #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED #endif /* TLS 1.2 or 1.3 key exchanges using ECDH or ECDHE */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED #endif /* TLS 1.2 XXDH key exchanges: ECDH or ECDHE or FFDH */ #if (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)) #define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_1_2_ENABLED #endif /* The handshake params structure has a set of fields called xxdh_psa which are used: * - by TLS 1.2 with `USE_PSA` to do ECDH or ECDHE; * - by TLS 1.3 to do ECDHE or FFDHE. * The following macros can be used to guard their declaration and use. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) #define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED #endif typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; #define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ #define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, eg for CCM_8 */ #define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ /** * \brief This structure is used for storing ciphersuite information * * \note members are defined using integral types instead of enums * in order to pack structure and reduce memory usage by internal * \c ciphersuite_definitions[] */ struct mbedtls_ssl_ciphersuite_t { int MBEDTLS_PRIVATE(id); const char *MBEDTLS_PRIVATE(name); uint8_t MBEDTLS_PRIVATE(cipher); /* mbedtls_cipher_type_t */ uint8_t MBEDTLS_PRIVATE(mac); /* mbedtls_md_type_t */ uint8_t MBEDTLS_PRIVATE(key_exchange); /* mbedtls_key_exchange_type_t */ uint8_t MBEDTLS_PRIVATE(flags); uint16_t MBEDTLS_PRIVATE(min_tls_version); /* mbedtls_ssl_protocol_version */ uint16_t MBEDTLS_PRIVATE(max_tls_version); /* mbedtls_ssl_protocol_version */ }; const int *mbedtls_ssl_list_ciphersuites(void); const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string(const char *ciphersuite_name); const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite_id); static inline const char *mbedtls_ssl_ciphersuite_get_name(const mbedtls_ssl_ciphersuite_t *info) { return info->MBEDTLS_PRIVATE(name); } static inline int mbedtls_ssl_ciphersuite_get_id(const mbedtls_ssl_ciphersuite_t *info) { return info->MBEDTLS_PRIVATE(id); } size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info); #ifdef __cplusplus } #endif #endif /* ssl_ciphersuites.h */ webfakes/src/mbedtls/include/mbedtls/x509_csr.h0000644000176200001440000003435714740737024021110 0ustar liggesusers/** * \file x509_csr.h * * \brief X.509 certificate signing request parsing and writing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_CSR_H #define MBEDTLS_X509_CSR_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/x509.h" #ifdef __cplusplus extern "C" { #endif /** * \addtogroup x509_module * \{ */ /** * \name Structures and functions for X.509 Certificate Signing Requests (CSR) * \{ */ /** * Certificate Signing Request (CSR) structure. * * Some fields of this structure are publicly readable. Do not modify * them except via Mbed TLS library functions: the effect of modifying * those fields or the data that those fields point to is unspecified. */ typedef struct mbedtls_x509_csr { mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ int version; /**< CSR version (1=v1). */ mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ mbedtls_pk_context pk; /**< Container for the public key context. */ unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */ int MBEDTLS_PRIVATE(ext_types); /**< Bit string containing detected and parsed extensions */ mbedtls_x509_buf sig_oid; mbedtls_x509_buf MBEDTLS_PRIVATE(sig); mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ } mbedtls_x509_csr; /** * Container for writing a CSR */ typedef struct mbedtls_x509write_csr { mbedtls_pk_context *MBEDTLS_PRIVATE(key); mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); } mbedtls_x509write_csr; #if defined(MBEDTLS_X509_CSR_PARSE_C) /** * \brief Load a Certificate Signing Request (CSR) in DER format * * \note Any unsupported requested extensions are silently * ignored, unless the critical flag is set, in which case * the CSR is rejected. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param csr CSR context to fill * \param buf buffer holding the CRL data * \param buflen size of the buffer * * \return 0 if successful, or a specific X509 error code */ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen); /** * \brief The type of certificate extension callbacks. * * Callbacks of this type are passed to and used by the * mbedtls_x509_csr_parse_der_with_ext_cb() routine when * it encounters either an unsupported extension. * Future versions of the library may invoke the callback * in other cases, if and when the need arises. * * \param p_ctx An opaque context passed to the callback. * \param csr The CSR being parsed. * \param oid The OID of the extension. * \param critical Whether the extension is critical. * \param p Pointer to the start of the extension value * (the content of the OCTET STRING). * \param end End of extension value. * * \note The callback must fail and return a negative error code * if it can not parse or does not support the extension. * When the callback fails to parse a critical extension * mbedtls_x509_csr_parse_der_with_ext_cb() also fails. * When the callback fails to parse a non critical extension * mbedtls_x509_csr_parse_der_with_ext_cb() simply skips * the extension and continues parsing. * * \return \c 0 on success. * \return A negative error code on failure. */ typedef int (*mbedtls_x509_csr_ext_cb_t)(void *p_ctx, mbedtls_x509_csr const *csr, mbedtls_x509_buf const *oid, int critical, const unsigned char *p, const unsigned char *end); /** * \brief Load a Certificate Signing Request (CSR) in DER format * * \note Any unsupported requested extensions are silently * ignored, unless the critical flag is set, in which case * the result of the callback function decides whether * CSR is rejected. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param csr CSR context to fill * \param buf buffer holding the CRL data * \param buflen size of the buffer * \param cb A callback invoked for every unsupported certificate * extension. * \param p_ctx An opaque context passed to the callback. * * \return 0 if successful, or a specific X509 error code */ int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx); /** * \brief Load a Certificate Signing Request (CSR), DER or PEM format * * \note See notes for \c mbedtls_x509_csr_parse_der() * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param csr CSR context to fill * \param buf buffer holding the CRL data * \param buflen size of the buffer * (including the terminating null byte for PEM data) * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen); #if defined(MBEDTLS_FS_IO) /** * \brief Load a Certificate Signing Request (CSR) * * \note See notes for \c mbedtls_x509_csr_parse() * * \param csr CSR context to fill * \param path filename to read the CSR from * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path); #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Returns an informational string about the * CSR. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param prefix A line prefix * \param csr The X509 CSR to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_csr *csr); #endif /* !MBEDTLS_X509_REMOVE_INFO */ /** * \brief Initialize a CSR * * \param csr CSR to initialize */ void mbedtls_x509_csr_init(mbedtls_x509_csr *csr); /** * \brief Unallocate all CSR data * * \param csr CSR to free */ void mbedtls_x509_csr_free(mbedtls_x509_csr *csr); #endif /* MBEDTLS_X509_CSR_PARSE_C */ /** \} name Structures and functions for X.509 Certificate Signing Requests (CSR) */ #if defined(MBEDTLS_X509_CSR_WRITE_C) /** * \brief Initialize a CSR context * * \param ctx CSR context to initialize */ void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx); /** * \brief Set the subject name for a CSR * Subject names should contain a comma-separated list * of OID types and values: * e.g. "C=UK,O=ARM,CN=Mbed TLS Server 1" * * \param ctx CSR context to use * \param subject_name subject name to set * * \return 0 if subject name was parsed successfully, or * a specific error code */ int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, const char *subject_name); /** * \brief Set the key for a CSR (public key will be included, * private key used to sign the CSR when writing it) * * \param ctx CSR context to use * \param key Asymmetric key to include */ void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key); /** * \brief Set the MD algorithm to use for the signature * (e.g. MBEDTLS_MD_SHA1) * * \param ctx CSR context to use * \param md_alg MD algorithm to use */ void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg); /** * \brief Set the Key Usage Extension flags * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) * * \param ctx CSR context to use * \param key_usage key usage flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED * * \note The decipherOnly flag from the Key Usage * extension is represented by bit 8 (i.e. * 0x8000), which cannot typically be represented * in an unsigned char. Therefore, the flag * decipherOnly (i.e. * #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this * function. */ int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage); /** * \brief Set Subject Alternative Name * * \param ctx CSR context to use * \param san_list List of SAN values * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED * * \note Only "dnsName", "uniformResourceIdentifier" and "otherName", * as defined in RFC 5280, are supported. */ int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, const mbedtls_x509_san_list *san_list); /** * \brief Set the Netscape Cert Type flags * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) * * \param ctx CSR context to use * \param ns_cert_type Netscape Cert Type flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, unsigned char ns_cert_type); /** * \brief Generic function to add to or replace an extension in the * CSR * * \param ctx CSR context to use * \param oid OID of the extension * \param oid_len length of the OID * \param critical Set to 1 to mark the extension as critical, 0 otherwise. * \param val value of the extension OCTET STRING * \param val_len length of the value data * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len); /** * \brief Free the contents of a CSR context * * \param ctx CSR context to free */ void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx); /** * \brief Write a CSR (Certificate Signing Request) to a * DER structure * Note: data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer * * \param ctx CSR to write away * \param buf buffer to write to * \param size size of the buffer * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return length of data written if successful, or a specific * error code * * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_PEM_WRITE_C) /** * \brief Write a CSR (Certificate Signing Request) to a * PEM string * * \param ctx CSR to write away * \param buf buffer to write to * \param size size of the buffer * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return 0 if successful, or a specific error code * * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CSR_WRITE_C */ /** \} addtogroup x509_module */ #ifdef __cplusplus } #endif #endif /* mbedtls_x509_csr.h */ webfakes/src/mbedtls/include/mbedtls/cmac.h0000644000176200001440000002375714740737024020441 0ustar liggesusers/** * \file cmac.h * * \brief This file contains CMAC definitions and functions. * * The Cipher-based Message Authentication Code (CMAC) Mode for * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. * It is supported with AES and DES. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CMAC_H #define MBEDTLS_CMAC_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #ifdef __cplusplus extern "C" { #endif #define MBEDTLS_AES_BLOCK_SIZE 16 #define MBEDTLS_DES3_BLOCK_SIZE 8 /* We don't support Camellia or ARIA in this module */ #if defined(MBEDTLS_AES_C) #define MBEDTLS_CMAC_MAX_BLOCK_SIZE 16 /**< The longest block used by CMAC is that of AES. */ #else #define MBEDTLS_CMAC_MAX_BLOCK_SIZE 8 /**< The longest block used by CMAC is that of 3DES. */ #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** The longest block supported by the cipher module. * * \deprecated * For the maximum block size of a cipher supported by the CMAC module, * use #MBEDTLS_CMAC_MAX_BLOCK_SIZE. * For the maximum block size of a cipher supported by the cipher module, * use #MBEDTLS_MAX_BLOCK_LENGTH. */ /* Before Mbed TLS 3.5, this was the maximum block size supported by the CMAC * module, so it didn't take Camellia or ARIA into account. Since the name * of the macro doesn't even convey "CMAC", this was misleading. Now the size * is sufficient for any cipher, but the name is defined in cmac.h for * backward compatibility. */ #define MBEDTLS_CIPHER_BLKSIZE_MAX MBEDTLS_MAX_BLOCK_LENGTH #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if !defined(MBEDTLS_CMAC_ALT) /** * The CMAC context structure. */ struct mbedtls_cmac_context_t { /** The internal state of the CMAC algorithm. */ unsigned char MBEDTLS_PRIVATE(state)[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; /** Unprocessed data - either data that was not block aligned and is still * pending processing, or the final block. */ unsigned char MBEDTLS_PRIVATE(unprocessed_block)[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; /** The length of data pending processing. */ size_t MBEDTLS_PRIVATE(unprocessed_len); }; #else /* !MBEDTLS_CMAC_ALT */ #include "cmac_alt.h" #endif /* !MBEDTLS_CMAC_ALT */ /** * \brief This function starts a new CMAC computation * by setting the CMAC key, and preparing to authenticate * the input data. * It must be called with an initialized cipher context. * * Once this function has completed, data can be supplied * to the CMAC computation by calling * mbedtls_cipher_cmac_update(). * * To start a CMAC computation using the same key as a previous * CMAC computation, use mbedtls_cipher_cmac_finish(). * * \note When the CMAC implementation is supplied by an alternate * implementation (through #MBEDTLS_CMAC_ALT), some ciphers * may not be supported by that implementation, and thus * return an error. Alternate implementations must support * AES-128 and AES-256, and may support AES-192 and 3DES. * * \param ctx The cipher context used for the CMAC operation, initialized * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, * or MBEDTLS_CIPHER_DES_EDE3_ECB. * \param key The CMAC key. * \param keybits The length of the CMAC key in bits. * Must be supported by the cipher. * * \return \c 0 on success. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx, const unsigned char *key, size_t keybits); /** * \brief This function feeds an input buffer into an ongoing CMAC * computation. * * The CMAC computation must have previously been started * by calling mbedtls_cipher_cmac_starts() or * mbedtls_cipher_cmac_reset(). * * Call this function as many times as needed to input the * data to be authenticated. * Once all of the required data has been input, * call mbedtls_cipher_cmac_finish() to obtain the result * of the CMAC operation. * * \param ctx The cipher context used for the CMAC operation. * \param input The buffer holding the input data. * \param ilen The length of the input data. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes an ongoing CMAC operation, and * writes the result to the output buffer. * * It should be followed either by * mbedtls_cipher_cmac_reset(), which starts another CMAC * operation with the same key, or mbedtls_cipher_free(), * which clears the cipher context. * * \param ctx The cipher context used for the CMAC operation. * \param output The output buffer for the CMAC checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, unsigned char *output); /** * \brief This function starts a new CMAC operation with the same * key as the previous one. * * It should be called after finishing the previous CMAC * operation with mbedtls_cipher_cmac_finish(). * After calling this function, * call mbedtls_cipher_cmac_update() to supply the new * CMAC operation with data. * * \param ctx The cipher context used for the CMAC operation. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx); /** * \brief This function calculates the full generic CMAC * on the input buffer with the provided key. * * The function allocates the context, performs the * calculation, and frees the context. * * The CMAC result is calculated as * output = generic CMAC(cmac key, input buffer). * * \note When the CMAC implementation is supplied by an alternate * implementation (through #MBEDTLS_CMAC_ALT), some ciphers * may not be supported by that implementation, and thus * return an error. Alternate implementations must support * AES-128 and AES-256, and may support AES-192 and 3DES. * * \param cipher_info The cipher information. * \param key The CMAC key. * \param keylen The length of the CMAC key in bits. * \param input The buffer holding the input data. * \param ilen The length of the input data. * \param output The buffer for the generic CMAC result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output); #if defined(MBEDTLS_AES_C) /** * \brief This function implements the AES-CMAC-PRF-128 pseudorandom * function, as defined in * RFC-4615: The Advanced Encryption Standard-Cipher-based * Message Authentication Code-Pseudo-Random Function-128 * (AES-CMAC-PRF-128) Algorithm for the Internet Key * Exchange Protocol (IKE). * * \param key The key to use. * \param key_len The key length in Bytes. * \param input The buffer holding the input data. * \param in_len The length of the input data in Bytes. * \param output The buffer holding the generated 16 Bytes of * pseudorandom output. * * \return \c 0 on success. */ int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_len, const unsigned char *input, size_t in_len, unsigned char output[16]); #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_SELF_TEST) && (defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)) /** * \brief The CMAC checkup routine. * * \note In case the CMAC routines are provided by an alternative * implementation (i.e. #MBEDTLS_CMAC_ALT is defined), the * checkup routine will succeed even if the implementation does * not support the less widely used AES-192 or 3DES primitives. * The self-test requires at least AES-128 and AES-256 to be * supported by the underlying implementation. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_cmac_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CMAC_H */ webfakes/src/mbedtls/include/mbedtls/ssl_ticket.h0000644000176200001440000001655614740737024021701 0ustar liggesusers/** * \file ssl_ticket.h * * \brief TLS server ticket callbacks implementation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_TICKET_H #define MBEDTLS_SSL_TICKET_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" /* * This implementation of the session ticket callbacks includes key * management, rotating the keys periodically in order to preserve forward * secrecy, when MBEDTLS_HAVE_TIME is defined. */ #include "mbedtls/ssl.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #ifdef __cplusplus extern "C" { #endif #define MBEDTLS_SSL_TICKET_MAX_KEY_BYTES 32 /*!< Max supported key length in bytes */ #define MBEDTLS_SSL_TICKET_KEY_NAME_BYTES 4 /*!< key name length in bytes */ /** * \brief Information for session ticket protection */ typedef struct mbedtls_ssl_ticket_key { unsigned char MBEDTLS_PRIVATE(name)[MBEDTLS_SSL_TICKET_KEY_NAME_BYTES]; /*!< random key identifier */ #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t MBEDTLS_PRIVATE(generation_time); /*!< key generation timestamp (seconds) */ #endif /*! Lifetime of the key in seconds. This is also the lifetime of the * tickets created under that key. */ uint32_t MBEDTLS_PRIVATE(lifetime); #if !defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_cipher_context_t MBEDTLS_PRIVATE(ctx); /*!< context for auth enc/decryption */ #else mbedtls_svc_key_id_t MBEDTLS_PRIVATE(key); /*!< key used for auth enc/decryption */ psa_algorithm_t MBEDTLS_PRIVATE(alg); /*!< algorithm of auth enc/decryption */ psa_key_type_t MBEDTLS_PRIVATE(key_type); /*!< key type */ size_t MBEDTLS_PRIVATE(key_bits); /*!< key length in bits */ #endif } mbedtls_ssl_ticket_key; /** * \brief Context for session ticket handling functions */ typedef struct mbedtls_ssl_ticket_context { mbedtls_ssl_ticket_key MBEDTLS_PRIVATE(keys)[2]; /*!< ticket protection keys */ unsigned char MBEDTLS_PRIVATE(active); /*!< index of the currently active key */ uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< lifetime of tickets in seconds */ /** Callback for getting (pseudo-)random numbers */ int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif } mbedtls_ssl_ticket_context; /** * \brief Initialize a ticket context. * (Just make it ready for mbedtls_ssl_ticket_setup() * or mbedtls_ssl_ticket_free().) * * \param ctx Context to be initialized */ void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx); /** * \brief Prepare context to be actually used * * \param ctx Context to be set up * \param f_rng RNG callback function (mandatory) * \param p_rng RNG callback context * \param cipher AEAD cipher to use for ticket protection. * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. * \param lifetime Tickets lifetime in seconds * Recommended value: 86400 (one day). * * \note It is highly recommended to select a cipher that is at * least as strong as the strongest ciphersuite * supported. Usually that means a 256-bit key. * * \note It is recommended to pick a reasonable lifetime so as not * to negate the benefits of forward secrecy. * * \note The TLS 1.3 specification states that ticket lifetime must * be smaller than seven days. If ticket lifetime has been * set to a value greater than seven days in this module then * if the TLS 1.3 is configured to send tickets after the * handshake it will fail the connection when trying to send * the first ticket. * * \return 0 if successful, * or a specific MBEDTLS_ERR_XXX error code */ int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_cipher_type_t cipher, uint32_t lifetime); /** * \brief Rotate session ticket encryption key to new specified key. * Provides for external control of session ticket encryption * key rotation, e.g. for synchronization between different * machines. If this function is not used, or if not called * before ticket lifetime expires, then a new session ticket * encryption key is generated internally in order to avoid * unbounded session ticket encryption key lifetimes. * * \param ctx Context to be set up * \param name Session ticket encryption key name * \param nlength Session ticket encryption key name length in bytes * \param k Session ticket encryption key * \param klength Session ticket encryption key length in bytes * \param lifetime Tickets lifetime in seconds * Recommended value: 86400 (one day). * * \note \c name and \c k are recommended to be cryptographically * random data. * * \note \c nlength must match sizeof( ctx->name ) * * \note \c klength must be sufficient for use by cipher specified * to \c mbedtls_ssl_ticket_setup * * \note It is recommended to pick a reasonable lifetime so as not * to negate the benefits of forward secrecy. * * \note The TLS 1.3 specification states that ticket lifetime must * be smaller than seven days. If ticket lifetime has been * set to a value greater than seven days in this module then * if the TLS 1.3 is configured to send tickets after the * handshake it will fail the connection when trying to send * the first ticket. * * \return 0 if successful, * or a specific MBEDTLS_ERR_XXX error code */ int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx, const unsigned char *name, size_t nlength, const unsigned char *k, size_t klength, uint32_t lifetime); /** * \brief Implementation of the ticket write callback * * \note See \c mbedtls_ssl_ticket_write_t for description */ mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; /** * \brief Implementation of the ticket parse callback * * \note See \c mbedtls_ssl_ticket_parse_t for description */ mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; /** * \brief Free a context's content and zeroize it. * * \param ctx Context to be cleaned up */ void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx); #ifdef __cplusplus } #endif #endif /* ssl_ticket.h */ webfakes/src/mbedtls/include/mbedtls/gcm.h0000644000176200001440000004211714740737024020273 0ustar liggesusers/** * \file gcm.h * * \brief This file contains GCM definitions and functions. * * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation * (GCM), Natl. Inst. Stand. Technol. * * For more information on GCM, see NIST SP 800-38D: Recommendation for * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_GCM_H #define MBEDTLS_GCM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #include "mbedtls/block_cipher.h" #endif #include #define MBEDTLS_GCM_ENCRYPT 1 #define MBEDTLS_GCM_DECRYPT 0 /** Authenticated decryption failed. */ #define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /** Bad input parameters to function. */ #define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /** An output buffer is too small. */ #define MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL -0x0016 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_GCM_ALT) #if defined(MBEDTLS_GCM_LARGE_TABLE) #define MBEDTLS_GCM_HTABLE_SIZE 256 #else #define MBEDTLS_GCM_HTABLE_SIZE 16 #endif /** * \brief The GCM context structure. */ typedef struct mbedtls_gcm_context { #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx); /*!< The cipher context used. */ #else mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ #endif uint64_t MBEDTLS_PRIVATE(H)[MBEDTLS_GCM_HTABLE_SIZE][2]; /*!< Precalculated HTable. */ uint64_t MBEDTLS_PRIVATE(len); /*!< The total length of the encrypted data. */ uint64_t MBEDTLS_PRIVATE(add_len); /*!< The total length of the additional data. */ unsigned char MBEDTLS_PRIVATE(base_ectr)[16]; /*!< The first ECTR for tag. */ unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working value. */ unsigned char MBEDTLS_PRIVATE(buf)[16]; /*!< The buf working value. */ unsigned char MBEDTLS_PRIVATE(mode); /*!< The operation to perform: #MBEDTLS_GCM_ENCRYPT or #MBEDTLS_GCM_DECRYPT. */ unsigned char MBEDTLS_PRIVATE(acceleration); /*!< The acceleration to use. */ } mbedtls_gcm_context; #else /* !MBEDTLS_GCM_ALT */ #include "gcm_alt.h" #endif /* !MBEDTLS_GCM_ALT */ /** * \brief This function initializes the specified GCM context, * to make references valid, and prepares the context * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). * * The function does not bind the GCM context to a particular * cipher, nor set the key. For this purpose, use * mbedtls_gcm_setkey(). * * \param ctx The GCM context to initialize. This must not be \c NULL. */ void mbedtls_gcm_init(mbedtls_gcm_context *ctx); /** * \brief This function associates a GCM context with a * cipher algorithm and a key. * * \param ctx The GCM context. This must be initialized. * \param cipher The 128-bit block cipher to use. * \param key The encryption key. This must be a readable buffer of at * least \p keybits bits. * \param keybits The key size in bits. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return A cipher-specific error code on failure. */ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits); /** * \brief This function performs GCM encryption or decryption of a buffer. * * \note For encryption, the output buffer can be the same as the * input buffer. For decryption, the output buffer cannot be * the same as input buffer. If the buffers overlap, the output * buffer must trail at least 8 Bytes behind the input buffer. * * \warning When this function performs a decryption, it outputs the * authentication tag and does not verify that the data is * authentic. You should use this function to perform encryption * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. * * \param ctx The GCM context to use for encryption or decryption. This * must be initialized. * \param mode The operation to perform: * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. * The ciphertext is written to \p output and the * authentication tag is written to \p tag. * - #MBEDTLS_GCM_DECRYPT to perform decryption. * The plaintext is written to \p output and the * authentication tag is written to \p tag. * Note that this mode is not recommended, because it does * not verify the authenticity of the data. For this reason, * you should use mbedtls_gcm_auth_decrypt() instead of * calling this function in decryption mode. * \param length The length of the input data, which is equal to the length * of the output data. * \param iv The initialization vector. This must be a readable buffer of * at least \p iv_len Bytes. * \param iv_len The length of the IV. * \param add The buffer holding the additional data. This must be of at * least that size in Bytes. * \param add_len The length of the additional data. * \param input The buffer holding the input data. If \p length is greater * than zero, this must be a readable buffer of at least that * size in Bytes. * \param output The buffer for holding the output data. If \p length is greater * than zero, this must be a writable buffer of at least that * size in Bytes. * \param tag_len The length of the tag to generate. * \param tag The buffer for holding the tag. This must be a writable * buffer of at least \p tag_len Bytes. * * \return \c 0 if the encryption or decryption was performed * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, * this does not indicate that the data is authentic. * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are * not valid or a cipher-specific error code if the encryption * or decryption failed. */ int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx, int mode, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, size_t tag_len, unsigned char *tag); /** * \brief This function performs a GCM authenticated decryption of a * buffer. * * \note For decryption, the output buffer cannot be the same as * input buffer. If the buffers overlap, the output buffer * must trail at least 8 Bytes behind the input buffer. * * \param ctx The GCM context. This must be initialized. * \param length The length of the ciphertext to decrypt, which is also * the length of the decrypted plaintext. * \param iv The initialization vector. This must be a readable buffer * of at least \p iv_len Bytes. * \param iv_len The length of the IV. * \param add The buffer holding the additional data. This must be of at * least that size in Bytes. * \param add_len The length of the additional data. * \param tag The buffer holding the tag to verify. This must be a * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to verify. * \param input The buffer holding the ciphertext. If \p length is greater * than zero, this must be a readable buffer of at least that * size. * \param output The buffer for holding the decrypted plaintext. If \p length * is greater than zero, this must be a writable buffer of at * least that size. * * \return \c 0 if successful and authenticated. * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are * not valid or a cipher-specific error code if the decryption * failed. */ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *tag, size_t tag_len, const unsigned char *input, unsigned char *output); /** * \brief This function starts a GCM encryption or decryption * operation. * * \param ctx The GCM context. This must be initialized. * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or * #MBEDTLS_GCM_DECRYPT. * \param iv The initialization vector. This must be a readable buffer of * at least \p iv_len Bytes. * \param iv_len The length of the IV. * * \return \c 0 on success. */ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, int mode, const unsigned char *iv, size_t iv_len); /** * \brief This function feeds an input buffer as associated data * (authenticated but not encrypted data) in a GCM * encryption or decryption operation. * * Call this function after mbedtls_gcm_starts() to pass * the associated data. If the associated data is empty, * you do not need to call this function. You may not * call this function after calling mbedtls_cipher_update(). * * \param ctx The GCM context. This must have been started with * mbedtls_gcm_starts() and must not have yet received * any input with mbedtls_gcm_update(). * \param add The buffer holding the additional data, or \c NULL * if \p add_len is \c 0. * \param add_len The length of the additional data. If \c 0, * \p add may be \c NULL. * * \return \c 0 on success. */ int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx, const unsigned char *add, size_t add_len); /** * \brief This function feeds an input buffer into an ongoing GCM * encryption or decryption operation. * * You may call this function zero, one or more times * to pass successive parts of the input: the plaintext to * encrypt, or the ciphertext (not including the tag) to * decrypt. After the last part of the input, call * mbedtls_gcm_finish(). * * This function may produce output in one of the following * ways: * - Immediate output: the output length is always equal * to the input length. * - Buffered output: the output consists of a whole number * of 16-byte blocks. If the total input length so far * (not including associated data) is 16 \* *B* + *A* * with *A* < 16 then the total output length is 16 \* *B*. * * In particular: * - It is always correct to call this function with * \p output_size >= \p input_length + 15. * - If \p input_length is a multiple of 16 for all the calls * to this function during an operation, then it is * correct to use \p output_size = \p input_length. * * \note For decryption, the output buffer cannot be the same as * input buffer. If the buffers overlap, the output buffer * must trail at least 8 Bytes behind the input buffer. * * \param ctx The GCM context. This must be initialized. * \param input The buffer holding the input data. If \p input_length * is greater than zero, this must be a readable buffer * of at least \p input_length bytes. * \param input_length The length of the input data in bytes. * \param output The buffer for the output data. If \p output_size * is greater than zero, this must be a writable buffer of * of at least \p output_size bytes. * \param output_size The size of the output buffer in bytes. * See the function description regarding the output size. * \param output_length On success, \p *output_length contains the actual * length of the output written in \p output. * On failure, the content of \p *output_length is * unspecified. * * \return \c 0 on success. * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: * total input length too long, * unsupported input/output buffer overlap detected, * or \p output_size too small. */ int mbedtls_gcm_update(mbedtls_gcm_context *ctx, const unsigned char *input, size_t input_length, unsigned char *output, size_t output_size, size_t *output_length); /** * \brief This function finishes the GCM operation and generates * the authentication tag. * * It wraps up the GCM stream, and generates the * tag. The tag can have a maximum length of 16 Bytes. * * \param ctx The GCM context. This must be initialized. * \param tag The buffer for holding the tag. This must be a writable * buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to generate. This must be at least * four. * \param output The buffer for the final output. * If \p output_size is nonzero, this must be a writable * buffer of at least \p output_size bytes. * \param output_size The size of the \p output buffer in bytes. * This must be large enough for the output that * mbedtls_gcm_update() has not produced. In particular: * - If mbedtls_gcm_update() produces immediate output, * or if the total input size is a multiple of \c 16, * then mbedtls_gcm_finish() never produces any output, * so \p output_size can be \c 0. * - \p output_size never needs to be more than \c 15. * \param output_length On success, \p *output_length contains the actual * length of the output written in \p output. * On failure, the content of \p *output_length is * unspecified. * * \return \c 0 on success. * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: * invalid value of \p tag_len, * or \p output_size too small. */ int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, unsigned char *output, size_t output_size, size_t *output_length, unsigned char *tag, size_t tag_len); /** * \brief This function clears a GCM context and the underlying * cipher sub-context. * * \param ctx The GCM context to clear. If this is \c NULL, the call has * no effect. Otherwise, this must be initialized. */ void mbedtls_gcm_free(mbedtls_gcm_context *ctx); #if defined(MBEDTLS_SELF_TEST) /** * \brief The GCM checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_gcm_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* gcm.h */ webfakes/src/mbedtls/include/mbedtls/pk.h0000644000176200001440000016047714740737024020151 0ustar liggesusers/** * \file pk.h * * \brief Public Key abstraction layer */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_H #define MBEDTLS_PK_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/md.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #endif #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include "psa/crypto.h" #endif /** Memory allocation failed. */ #define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /** Type mismatch, eg attempt to encrypt with an ECDSA key */ #define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /** Bad input parameters to function. */ #define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /** Read/write of file failed. */ #define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /** Unsupported key version */ #define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /** Invalid key tag or value. */ #define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /** Key algorithm is unsupported (only RSA and EC are supported). */ #define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /** Private key password can't be empty. */ #define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /** Given private key password does not allow for correct decryption. */ #define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /** The pubkey tag or value is invalid (only RSA and EC are supported). */ #define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /** The algorithm tag or value is invalid. */ #define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /** Elliptic curve is unsupported (only NIST curves are supported). */ #define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /** Unavailable feature, e.g. RSA disabled for RSA key. */ #define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /** The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /** The output buffer is too small. */ #define MBEDTLS_ERR_PK_BUFFER_TOO_SMALL -0x3880 #ifdef __cplusplus extern "C" { #endif /** * \brief Public key types */ typedef enum { MBEDTLS_PK_NONE=0, MBEDTLS_PK_RSA, MBEDTLS_PK_ECKEY, MBEDTLS_PK_ECKEY_DH, MBEDTLS_PK_ECDSA, MBEDTLS_PK_RSA_ALT, MBEDTLS_PK_RSASSA_PSS, MBEDTLS_PK_OPAQUE, } mbedtls_pk_type_t; /** * \brief Options for RSASSA-PSS signature verification. * See \c mbedtls_rsa_rsassa_pss_verify_ext() */ typedef struct mbedtls_pk_rsassa_pss_options { /** The digest to use for MGF1 in PSS. * * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled and #MBEDTLS_RSA_C is * disabled, this must be equal to the \c md_alg argument passed * to mbedtls_pk_verify_ext(). In a future version of the library, * this constraint may apply whenever #MBEDTLS_USE_PSA_CRYPTO is * enabled regardless of the status of #MBEDTLS_RSA_C. */ mbedtls_md_type_t mgf1_hash_id; /** The expected length of the salt, in bytes. This may be * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. * * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled, only * #MBEDTLS_RSA_SALT_LEN_ANY is valid. Any other value may be * ignored (allowing any salt length). */ int expected_salt_len; } mbedtls_pk_rsassa_pss_options; /** * \brief Maximum size of a signature made by mbedtls_pk_sign(). */ /* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature * size among the supported signature types. Do it by starting at 0, * then incrementally increasing to be large enough for each supported * signature mechanism. * * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). */ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 #if (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT)) && \ MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE /* For RSA, the signature can be as large as the bignum module allows. * For RSA_ALT, the signature size is not necessarily tied to what the * bignum module can do, but in the absence of any specific setting, * we use that (rsa_alt_sign_wrap in library/pk_wrap.h will check). */ #undef MBEDTLS_PK_SIGNATURE_MAX_SIZE #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE #endif #if defined(MBEDTLS_ECDSA_C) && \ MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE /* For ECDSA, the ecdsa module exports a constant for the maximum * signature size. */ #undef MBEDTLS_PK_SIGNATURE_MAX_SIZE #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE /* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made * through the PSA API in the PSA representation. */ #undef MBEDTLS_PK_SIGNATURE_MAX_SIZE #define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE #endif #if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE /* The Mbed TLS representation is different for ECDSA signatures: * PSA uses the raw concatenation of r and s, * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the * types, lengths (represented by up to 2 bytes), and potential leading * zeros of the INTEGERs and the SEQUENCE. */ #undef MBEDTLS_PK_SIGNATURE_MAX_SIZE #define MBEDTLS_PK_SIGNATURE_MAX_SIZE (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11) #endif #endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ /* Internal helper to define which fields in the pk_context structure below * should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly) * format. It should be noted that this only affects how data is stored, not * which functions are used for various operations. The overall picture looks * like this: * - if USE_PSA is not defined and ECP_C is defined then use ecp_keypair data * structure and legacy functions * - if USE_PSA is defined and * - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly * format and use PSA functions * - if !ECP_C then use new raw data and PSA functions directly. * * The main reason for the "intermediate" (USE_PSA + ECP_C) above is that as long * as ECP_C is defined mbedtls_pk_ec() gives the user a read/write access to the * ecp_keypair structure inside the pk_context so they can modify it using * ECP functions which are not under PK module's control. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ !defined(MBEDTLS_ECP_C) #define MBEDTLS_PK_USE_PSA_EC_DATA #endif /** * \brief Types for interfacing with the debug module */ typedef enum { MBEDTLS_PK_DEBUG_NONE = 0, MBEDTLS_PK_DEBUG_MPI, MBEDTLS_PK_DEBUG_ECP, MBEDTLS_PK_DEBUG_PSA_EC, } mbedtls_pk_debug_type; /** * \brief Item to send to the debug module */ typedef struct mbedtls_pk_debug_item { mbedtls_pk_debug_type MBEDTLS_PRIVATE(type); const char *MBEDTLS_PRIVATE(name); void *MBEDTLS_PRIVATE(value); } mbedtls_pk_debug_item; /** Maximum number of item send for debugging, plus 1 */ #define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 /** * \brief Public key information and operations * * \note The library does not support custom pk info structures, * only built-in structures returned by * mbedtls_cipher_info_from_type(). */ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; #define MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN \ PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) /** * \brief Public key container */ typedef struct mbedtls_pk_context { const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ void *MBEDTLS_PRIVATE(pk_ctx); /**< Underlying public key context */ /* The following field is used to store the ID of a private key in the * following cases: * - opaque key when MBEDTLS_USE_PSA_CRYPTO is defined * - normal key when MBEDTLS_PK_USE_PSA_EC_DATA is defined. In this case: * - the pk_ctx above is not not used to store the private key anymore. * Actually that field not populated at all in this case because also * the public key will be stored in raw format as explained below * - this ID is used for all private key operations (ex: sign, check * key pair, key write, etc) using PSA functions * * Note: this private key storing solution only affects EC keys, not the * other ones. The latters still use the pk_ctx to store their own * context. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t MBEDTLS_PRIVATE(priv_id); /**< Key ID for opaque keys */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* The following fields are meant for storing the public key in raw format * which is handy for: * - easily importing it into the PSA context * - reducing the ECP module dependencies in the PK one. * * When MBEDTLS_PK_USE_PSA_EC_DATA is enabled: * - the pk_ctx above is not used anymore for storing the public key * inside the ecp_keypair structure * - the following fields are used for all public key operations: signature * verify, key pair check and key write. * - For a key pair, priv_id contains the private key. For a public key, * priv_id is null. * Of course, when MBEDTLS_PK_USE_PSA_EC_DATA is not enabled, the legacy * ecp_keypair structure is used for storing the public key and performing * all the operations. * * Note: This new public key storing solution only works for EC keys, not * other ones. The latters still use pk_ctx to store their own * context. */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) uint8_t MBEDTLS_PRIVATE(pub_raw)[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; /**< Raw public key */ size_t MBEDTLS_PRIVATE(pub_raw_len); /**< Valid bytes in "pub_raw" */ psa_ecc_family_t MBEDTLS_PRIVATE(ec_family); /**< EC family of pk */ size_t MBEDTLS_PRIVATE(ec_bits); /**< Curve's bits of pk */ #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } mbedtls_pk_context; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Context for resuming operations */ typedef struct { const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ void *MBEDTLS_PRIVATE(rs_ctx); /**< Underlying restart context */ } mbedtls_pk_restart_ctx; #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* Now we can declare functions that take a pointer to that */ typedef void mbedtls_pk_restart_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /** * \brief Types for RSA-alt abstraction */ typedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); typedef int (*mbedtls_pk_rsa_alt_sign_func)(void *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx); #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ /** * \brief Return information associated with the given PK type * * \param pk_type PK type to search for. * * \return The PK info associated with the type or NULL if not found. */ const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type); /** * \brief Initialize a #mbedtls_pk_context (as NONE). * * \param ctx The context to initialize. * This must not be \c NULL. */ void mbedtls_pk_init(mbedtls_pk_context *ctx); /** * \brief Free the components of a #mbedtls_pk_context. * * \param ctx The context to clear. It must have been initialized. * If this is \c NULL, this function does nothing. * * \note For contexts that have been set up with * mbedtls_pk_setup_opaque(), this does not free the underlying * PSA key and you still need to call psa_destroy_key() * independently if you want to destroy that key. */ void mbedtls_pk_free(mbedtls_pk_context *ctx); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context * * \param ctx The context to initialize. * This must not be \c NULL. */ void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx); /** * \brief Free the components of a restart context * * \param ctx The context to clear. It must have been initialized. * If this is \c NULL, this function does nothing. */ void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** * \brief Initialize a PK context with the information given * and allocates the type-specific PK subcontext. * * \param ctx Context to initialize. It must not have been set * up yet (type #MBEDTLS_PK_NONE). * \param info Information to use * * \return 0 on success, * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. * * \note For contexts holding an RSA-alt key, use * \c mbedtls_pk_setup_rsa_alt() instead. */ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * \brief Initialize a PK context to wrap a PSA key. * * This function creates a PK context which wraps a PSA key. The PSA wrapped * key must be an EC or RSA key pair (DH is not suported in the PK module). * * Under the hood PSA functions will be used to perform the required * operations and, based on the key type, used algorithms will be: * * EC: * * verify, verify_ext, sign, sign_ext: ECDSA. * * RSA: * * sign, decrypt: use the primary algorithm in the wrapped PSA key; * * sign_ext: RSA PSS if the pk_type is #MBEDTLS_PK_RSASSA_PSS, otherwise * it falls back to the sign() case; * * verify, verify_ext, encrypt: not supported. * * In order for the above operations to succeed, the policy of the wrapped PSA * key must allow the specified algorithm. * * Opaque PK contexts wrapping an EC keys also support \c mbedtls_pk_check_pair(), * whereas RSA ones do not. * * \warning The PSA wrapped key must remain valid as long as the wrapping PK * context is in use, that is at least between the point this function * is called and the point mbedtls_pk_free() is called on this context. * * \param ctx The context to initialize. It must be empty (type NONE). * \param key The PSA key to wrap, which must hold an ECC or RSA key pair. * * \return \c 0 on success. * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input (context already * used, invalid key identifier). * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an ECC or * RSA key pair. * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. */ int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, const mbedtls_svc_key_id_t key); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /** * \brief Initialize an RSA-alt context * * \param ctx Context to initialize. It must not have been set * up yet (type #MBEDTLS_PK_NONE). * \param key RSA key pointer * \param decrypt_func Decryption function * \param sign_func Signing function * \param key_len_func Function returning key length in bytes * * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the * context wasn't already initialized as RSA_ALT. * * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. */ int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, mbedtls_pk_rsa_alt_decrypt_func decrypt_func, mbedtls_pk_rsa_alt_sign_func sign_func, mbedtls_pk_rsa_alt_key_len_func key_len_func); #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ /** * \brief Get the size in bits of the underlying key * * \param ctx The context to query. It must have been initialized. * * \return Key size in bits, or 0 on error */ size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx); /** * \brief Get the length in bytes of the underlying key * * \param ctx The context to query. It must have been initialized. * * \return Key length in bytes, or 0 on error */ static inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx) { return (mbedtls_pk_get_bitlen(ctx) + 7) / 8; } /** * \brief Tell if a context can do the operation given by type * * \param ctx The context to query. It must have been initialized. * \param type The desired type. * * \return 1 if the context can do operations on the given type. * \return 0 if the context cannot do the operations on the given * type. This is always the case for a context that has * been initialized but not set up, or that has been * cleared with mbedtls_pk_free(). */ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type); #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * \brief Tell if context can do the operation given by PSA algorithm * * \param ctx The context to query. It must have been initialized. * \param alg PSA algorithm to check against, the following are allowed: * PSA_ALG_RSA_PKCS1V15_SIGN(hash), * PSA_ALG_RSA_PSS(hash), * PSA_ALG_RSA_PKCS1V15_CRYPT, * PSA_ALG_ECDSA(hash), * PSA_ALG_ECDH, where hash is a specific hash. * \param usage PSA usage flag to check against, must be composed of: * PSA_KEY_USAGE_SIGN_HASH * PSA_KEY_USAGE_DECRYPT * PSA_KEY_USAGE_DERIVE. * Context key must match all passed usage flags. * * \warning Since the set of allowed algorithms and usage flags may be * expanded in the future, the return value \c 0 should not * be taken in account for non-allowed algorithms and usage * flags. * * \return 1 if the context can do operations on the given type. * \return 0 if the context cannot do the operations on the given * type, for non-allowed algorithms and usage flags, or * for a context that has been initialized but not set up * or that has been cleared with mbedtls_pk_free(). */ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, psa_key_usage_t usage); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) /** * \brief Determine valid PSA attributes that can be used to * import a key into PSA. * * The attributes determined by this function are suitable * for calling mbedtls_pk_import_into_psa() to create * a PSA key with the same key material. * * The typical flow of operations involving this function is * ``` * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * int ret = mbedtls_pk_get_psa_attributes(pk, &attributes); * if (ret != 0) ...; // error handling omitted * // Tweak attributes if desired * psa_key_id_t key_id = 0; * ret = mbedtls_pk_import_into_psa(pk, &attributes, &key_id); * if (ret != 0) ...; // error handling omitted * ``` * * \note This function does not support RSA-alt contexts * (set up with mbedtls_pk_setup_rsa_alt()). * * \param[in] pk The PK context to use. It must have been set up. * It can either contain a key pair or just a public key. * \param usage A single `PSA_KEY_USAGE_xxx` flag among the following: * - #PSA_KEY_USAGE_DECRYPT: \p pk must contain a * key pair. The output \p attributes will contain a * key pair type, and the usage policy will allow * #PSA_KEY_USAGE_ENCRYPT as well as * #PSA_KEY_USAGE_DECRYPT. * - #PSA_KEY_USAGE_DERIVE: \p pk must contain a * key pair. The output \p attributes will contain a * key pair type. * - #PSA_KEY_USAGE_ENCRYPT: The output * \p attributes will contain a public key type. * - #PSA_KEY_USAGE_SIGN_HASH: \p pk must contain a * key pair. The output \p attributes will contain a * key pair type, and the usage policy will allow * #PSA_KEY_USAGE_VERIFY_HASH as well as * #PSA_KEY_USAGE_SIGN_HASH. * - #PSA_KEY_USAGE_SIGN_MESSAGE: \p pk must contain a * key pair. The output \p attributes will contain a * key pair type, and the usage policy will allow * #PSA_KEY_USAGE_VERIFY_MESSAGE as well as * #PSA_KEY_USAGE_SIGN_MESSAGE. * - #PSA_KEY_USAGE_VERIFY_HASH: The output * \p attributes will contain a public key type. * - #PSA_KEY_USAGE_VERIFY_MESSAGE: The output * \p attributes will contain a public key type. * \param[out] attributes * On success, valid attributes to import the key into PSA. * - The lifetime and key identifier are unchanged. If the * attribute structure was initialized or reset before * calling this function, this will result in a volatile * key. Call psa_set_key_identifier() before or after this * function if you wish to create a persistent key. Call * psa_set_key_lifetime() before or after this function if * you wish to import the key in a secure element. * - The key type and bit-size are determined by the contents * of the PK context. If the PK context contains a key * pair, the key type can be either a key pair type or * the corresponding public key type, depending on * \p usage. If the PK context contains a public key, * the key type is a public key type. * - The key's policy is determined by the key type and * the \p usage parameter. The usage always allows * \p usage, exporting and copying the key, and * possibly other permissions as documented for the * \p usage parameter. * The permitted algorithm policy is determined as follows * based on the #mbedtls_pk_type_t type of \p pk, * the chosen \p usage and other factors: * - #MBEDTLS_PK_RSA whose underlying * #mbedtls_rsa_context has the padding mode * #MBEDTLS_RSA_PKCS_V15: * #PSA_ALG_RSA_PKCS1V15_SIGN(#PSA_ALG_ANY_HASH) * if \p usage is SIGN/VERIFY, and * #PSA_ALG_RSA_PKCS1V15_CRYPT * if \p usage is ENCRYPT/DECRYPT. * - #MBEDTLS_PK_RSA whose underlying * #mbedtls_rsa_context has the padding mode * #MBEDTLS_RSA_PKCS_V21 and the digest type * corresponding to the PSA algorithm \c hash: * #PSA_ALG_RSA_PSS_ANY_SALT(#PSA_ALG_ANY_HASH) * if \p usage is SIGN/VERIFY, and * #PSA_ALG_RSA_OAEP(\c hash) * if \p usage is ENCRYPT/DECRYPT. * - #MBEDTLS_PK_RSA_ALT: not supported. * - #MBEDTLS_PK_ECDSA or #MBEDTLS_PK_ECKEY * if \p usage is SIGN/VERIFY: * #PSA_ALG_DETERMINISTIC_ECDSA(#PSA_ALG_ANY_HASH) * if #MBEDTLS_ECDSA_DETERMINISTIC is enabled, * otherwise #PSA_ALG_ECDSA(#PSA_ALG_ANY_HASH). * - #MBEDTLS_PK_ECKEY_DH or #MBEDTLS_PK_ECKEY * if \p usage is DERIVE: * #PSA_ALG_ECDH. * - #MBEDTLS_PK_OPAQUE: same as the primary algorithm * set for the underlying PSA key, except that * sign/decrypt flags are removed if the type is * set to a public key type. * The underlying key must allow \p usage. * Note that the enrollment algorithm set with * psa_set_key_enrollment_algorithm() is not copied. * * \return 0 on success. * #MBEDTLS_ERR_PK_TYPE_MISMATCH if \p pk does not contain * a key of the type identified in \p attributes. * Another error code on other failures. */ int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk, psa_key_usage_t usage, psa_key_attributes_t *attributes); /** * \brief Import a key into the PSA key store. * * This function is equivalent to calling psa_import_key() * with the key material from \p pk. * * The typical way to use this function is: * -# Call mbedtls_pk_get_psa_attributes() to obtain * attributes for the given key. * -# If desired, modify the attributes, for example: * - To create a persistent key, call * psa_set_key_identifier() and optionally * psa_set_key_lifetime(). * - To import only the public part of a key pair: * * psa_set_key_type(&attributes, * PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( * psa_get_key_type(&attributes))); * - Restrict the key usage if desired. * -# Call mbedtls_pk_import_into_psa(). * * \note This function does not support RSA-alt contexts * (set up with mbedtls_pk_setup_rsa_alt()). * * \param[in] pk The PK context to use. It must have been set up. * It can either contain a key pair or just a public key. * \param[in] attributes * The attributes to use for the new key. They must be * compatible with \p pk. In particular, the key type * must match the content of \p pk. * If \p pk contains a key pair, the key type in * attributes can be either the key pair type or the * corresponding public key type (to import only the * public part). * \param[out] key_id * On success, the identifier of the newly created key. * On error, this is #MBEDTLS_SVC_KEY_ID_INIT. * * \return 0 on success. * #MBEDTLS_ERR_PK_TYPE_MISMATCH if \p pk does not contain * a key of the type identified in \p attributes. * Another error code on other failures. */ int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key_id); /** * \brief Create a PK context starting from a key stored in PSA. * This key: * - must be exportable and * - must be an RSA or EC key pair or public key (FFDH is not supported in PK). * * The resulting PK object will be a transparent type: * - #MBEDTLS_PK_RSA for RSA keys or * - #MBEDTLS_PK_ECKEY for EC keys. * * Once this functions returns the PK object will be completely * independent from the original PSA key that it was generated * from. * Calling mbedtls_pk_sign(), mbedtls_pk_verify(), * mbedtls_pk_encrypt(), mbedtls_pk_decrypt() on the resulting * PK context will perform the corresponding algorithm for that * PK context type. * * For ECDSA, the choice of deterministic vs randomized will * be based on the compile-time setting #MBEDTLS_ECDSA_DETERMINISTIC. * * For an RSA key, the output PK context will allow both * encrypt/decrypt and sign/verify regardless of the original * key's policy. * The original key's policy determines the output key's padding * mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS, * otherwise PKCS1 v1.5 is set. * * \param key_id The key identifier of the key stored in PSA. * \param pk The PK context that will be filled. It must be initialized, * but not set up. * * \return 0 on success. * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input * parameters are not correct. */ int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk); /** * \brief Create a PK context for the public key of a PSA key. * * The key must be an RSA or ECC key. It can be either a * public key or a key pair, and only the public key is copied. * The resulting PK object will be a transparent type: * - #MBEDTLS_PK_RSA for RSA keys or * - #MBEDTLS_PK_ECKEY for EC keys. * * Once this functions returns the PK object will be completely * independent from the original PSA key that it was generated * from. * Calling mbedtls_pk_verify() or * mbedtls_pk_encrypt() on the resulting * PK context will perform the corresponding algorithm for that * PK context type. * * For an RSA key, the output PK context will allow both * encrypt and verify regardless of the original key's policy. * The original key's policy determines the output key's padding * mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS, * otherwise PKCS1 v1.5 is set. * * \param key_id The key identifier of the key stored in PSA. * \param pk The PK context that will be filled. It must be initialized, * but not set up. * * \return 0 on success. * \return MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input * parameters are not correct. */ int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk); #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ /** * \brief Verify signature (including padding if relevant). * * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used. * This can be #MBEDTLS_MD_NONE if the signature algorithm * does not rely on a hash algorithm (non-deterministic * ECDSA, RSA PKCS#1 v1.5). * For PKCS#1 v1.5, if \p md_alg is #MBEDTLS_MD_NONE, then * \p hash is the DigestInfo structure used by RFC 8017 * §9.2 steps 3–6. If \p md_alg is a valid hash * algorithm then \p hash is the digest itself, and this * function calculates the DigestInfo encoding internally. * \param hash Hash of the message to sign * \param hash_len Hash length * \param sig Signature to verify * \param sig_len Signature length * * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is * either PKCS#1 v1.5 or PSS (accepting any salt length), * depending on the padding mode in the underlying RSA context. * For a pk object constructed by parsing, this is PKCS#1 v1.5 * by default. Use mbedtls_pk_verify_ext() to explicitly select * a different algorithm. * * \return 0 on success (signature is valid), * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid * signature in \p sig but its length is less than \p sig_len, * or a specific error code. */ int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len); /** * \brief Restartable version of \c mbedtls_pk_verify() * * \note Performs the same job as \c mbedtls_pk_verify(), but can * return early and restart according to the limit set with * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC * operations. For RSA, same as \c mbedtls_pk_verify(). * * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) * \param sig Signature to verify * \param sig_len Signature length * \param rs_ctx Restart context (NULL to disable restart) * * \return See \c mbedtls_pk_verify(), or * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, mbedtls_pk_restart_ctx *rs_ctx); /** * \brief Verify signature, with options. * (Includes verification of the padding depending on type.) * * \param type Signature type (inc. possible padding type) to verify * \param options Pointer to type-specific options, or NULL * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) * \param sig Signature to verify * \param sig_len Signature length * * \return 0 on success (signature is valid), * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be * used for this type of signatures, * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid * signature in \p sig but its length is less than \p sig_len, * or a specific error code. * * \note If hash_len is 0, then the length associated with md_alg * is used instead, or an error returned if it is invalid. * * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 * * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point * to a mbedtls_pk_rsassa_pss_options structure, * otherwise it must be NULL. Note that if * #MBEDTLS_USE_PSA_CRYPTO is defined, the salt length is not * verified as PSA_ALG_RSA_PSS_ANY_SALT is used. */ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len); /** * \brief Make signature, including padding if relevant. * * \param ctx The PK context to use. It must have been set up * with a private key. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length * \param sig Place to write the signature. * It must have enough room for the signature. * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. * You may use a smaller buffer if it is large enough * given the key type. * \param sig_size The size of the \p sig buffer in bytes. * \param sig_len On successful return, * the number of bytes written to \p sig. * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is * either PKCS#1 v1.5 or PSS (using the largest possible salt * length up to the hash length), depending on the padding mode * in the underlying RSA context. For a pk object constructed * by parsing, this is PKCS#1 v1.5 by default. Use * mbedtls_pk_verify_ext() to explicitly select a different * algorithm. * * \return 0 on success, or a specific error code. * * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. */ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Make signature given a signature type. * * \param pk_type Signature type. * \param ctx The PK context to use. It must have been set up * with a private key. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length * \param sig Place to write the signature. * It must have enough room for the signature. * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. * You may use a smaller buffer if it is large enough * given the key type. * \param sig_size The size of the \p sig buffer in bytes. * \param sig_len On successful return, * the number of bytes written to \p sig. * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \return 0 on success, or a specific error code. * * \note When \p pk_type is #MBEDTLS_PK_RSASSA_PSS, * see #PSA_ALG_RSA_PSS for a description of PSS options used. * * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. * */ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Restartable version of \c mbedtls_pk_sign() * * \note Performs the same job as \c mbedtls_pk_sign(), but can * return early and restart according to the limit set with * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC * operations. For RSA, same as \c mbedtls_pk_sign(). * * \param ctx The PK context to use. It must have been set up * with a private key. * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) * \param hash Hash of the message to sign * \param hash_len Hash length * \param sig Place to write the signature. * It must have enough room for the signature. * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. * You may use a smaller buffer if it is large enough * given the key type. * \param sig_size The size of the \p sig buffer in bytes. * \param sig_len On successful return, * the number of bytes written to \p sig. * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * \param rs_ctx Restart context (NULL to disable restart) * * \return See \c mbedtls_pk_sign(). * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_pk_restart_ctx *rs_ctx); /** * \brief Decrypt message (including padding if relevant). * * \param ctx The PK context to use. It must have been set up * with a private key. * \param input Input to decrypt * \param ilen Input size * \param output Decrypted output * \param olen Decrypted message length * \param osize Size of the output buffer * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is * either PKCS#1 v1.5 or OAEP, depending on the padding mode in * the underlying RSA context. For a pk object constructed by * parsing, this is PKCS#1 v1.5 by default. * * \return 0 on success, or a specific error code. */ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Encrypt message (including padding if relevant). * * \param ctx The PK context to use. It must have been set up. * \param input Message to encrypt * \param ilen Message size * \param output Encrypted output * \param olen Encrypted output length * \param osize Size of the output buffer * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is * either PKCS#1 v1.5 or OAEP, depending on the padding mode in * the underlying RSA context. For a pk object constructed by * parsing, this is PKCS#1 v1.5 by default. * * \note \p f_rng is used for padding generation. * * \return 0 on success, or a specific error code. */ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Check if a public-private pair of keys matches. * * \param pub Context holding a public key. * \param prv Context holding a private (and public) key. * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \return \c 0 on success (keys were checked and match each other). * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not * be checked - in that case they may or may not match. * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. * \return Another non-zero value if the keys do not match. */ int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Export debug information * * \param ctx The PK context to use. It must have been initialized. * \param items Place to write debug items * * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA */ int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items); /** * \brief Access the type name * * \param ctx The PK context to use. It must have been initialized. * * \return Type name on success, or "invalid PK" */ const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx); /** * \brief Get the key type * * \param ctx The PK context to use. It must have been initialized. * * \return Type on success. * \return #MBEDTLS_PK_NONE for a context that has not been set up. */ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx); #if defined(MBEDTLS_RSA_C) /** * Quick access to an RSA context inside a PK context. * * \warning This function can only be used when the type of the context, as * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA. * Ensuring that is the caller's responsibility. * Alternatively, you can check whether this function returns NULL. * * \return The internal RSA context held by the PK context, or NULL. */ static inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk) { switch (mbedtls_pk_get_type(&pk)) { case MBEDTLS_PK_RSA: return (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) /** * Quick access to an EC context inside a PK context. * * \warning This function can only be used when the type of the context, as * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY, * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA. * Ensuring that is the caller's responsibility. * Alternatively, you can check whether this function returns NULL. * * \return The internal EC context held by the PK context, or NULL. */ static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) { switch (mbedtls_pk_get_type(&pk)) { case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } } #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_PK_PARSE_C) /** \ingroup pk_module */ /** * \brief Parse a private key in PEM or DER format * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param key Input buffer to parse. * The buffer must contain the input exactly, with no * extra trailing material. For PEM, the buffer must * contain a null-terminated string. * \param keylen Size of \b key in bytes. * For PEM data, this includes the terminating null byte, * so \p keylen must be equal to `strlen(key) + 1`. * \param pwd Optional password for decryption. * Pass \c NULL if expecting a non-encrypted key. * Pass a string of \p pwdlen bytes if expecting an encrypted * key; a non-encrypted key will also be accepted. * The empty password is not supported. * \param pwdlen Size of the password in bytes. * Ignored if \p pwd is \c NULL. * \param f_rng RNG function, must not be \c NULL. Used for blinding. * \param p_rng RNG parameter * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * specific key type, check the result with mbedtls_pk_can_do(). * * \note The key is also checked for correctness. * * \return 0 if successful, or a specific PK or PEM error code */ int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \ingroup pk_module */ /** * \brief Parse a public key in PEM or DER format * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param key Input buffer to parse. * The buffer must contain the input exactly, with no * extra trailing material. For PEM, the buffer must * contain a null-terminated string. * \param keylen Size of \b key in bytes. * For PEM data, this includes the terminating null byte, * so \p keylen must be equal to `strlen(key) + 1`. * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * specific key type, check the result with mbedtls_pk_can_do(). * * \note For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for * limitations. * * \note The key is also checked for correctness. * * \return 0 if successful, or a specific PK or PEM error code */ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen); #if defined(MBEDTLS_FS_IO) /** \ingroup pk_module */ /** * \brief Load and parse a private key * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param path filename to read the private key from * \param password Optional password to decrypt the file. * Pass \c NULL if expecting a non-encrypted key. * Pass a null-terminated string if expecting an encrypted * key; a non-encrypted key will also be accepted. * The empty password is not supported. * \param f_rng RNG function, must not be \c NULL. Used for blinding. * \param p_rng RNG parameter * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * specific key type, check the result with mbedtls_pk_can_do(). * * \note The key is also checked for correctness. * * \return 0 if successful, or a specific PK or PEM error code */ int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, const char *path, const char *password, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \ingroup pk_module */ /** * \brief Load and parse a public key * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param path filename to read the public key from * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If * you need a specific key type, check the result with * mbedtls_pk_can_do(). * * \note The key is also checked for correctness. * * \return 0 if successful, or a specific PK or PEM error code */ int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_PK_PARSE_C */ #if defined(MBEDTLS_PK_WRITE_C) /** * \brief Write a private key to a PKCS#1 or SEC1 DER structure * Note: data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer * * \param ctx PK context which must contain a valid private key. * \param buf buffer to write to * \param size size of the buffer * * \return length of data written if successful, or a specific * error code */ int mbedtls_pk_write_key_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); /** * \brief Write a public key to a SubjectPublicKeyInfo DER structure * Note: data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer * * \param ctx PK context which must contain a valid public or private key. * \param buf buffer to write to * \param size size of the buffer * * \return length of data written if successful, or a specific * error code */ int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); #if defined(MBEDTLS_PEM_WRITE_C) /** * \brief Write a public key to a PEM string * * \param ctx PK context which must contain a valid public or private key. * \param buf Buffer to write to. The output includes a * terminating null byte. * \param size Size of the buffer in bytes. * * \return 0 if successful, or a specific error code */ int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); /** * \brief Write a private key to a PKCS#1 or SEC1 PEM string * * \param ctx PK context which must contain a valid private key. * \param buf Buffer to write to. The output includes a * terminating null byte. * \param size Size of the buffer in bytes. * * \return 0 if successful, or a specific error code */ int mbedtls_pk_write_key_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */ /* * WARNING: Low-level functions. You probably do not want to use these unless * you are certain you do ;) */ #if defined(MBEDTLS_PK_PARSE_C) /** * \brief Parse a SubjectPublicKeyInfo DER structure * * \param p the position in the ASN.1 data * \param end end of the buffer * \param pk The PK context to fill. It must have been initialized * but not set up. * * \return 0 if successful, or a specific PK error code */ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, mbedtls_pk_context *pk); #endif /* MBEDTLS_PK_PARSE_C */ #if defined(MBEDTLS_PK_WRITE_C) /** * \brief Write a subjectPublicKey to ASN.1 data * Note: function works backwards in data buffer * * \param p reference to current position pointer * \param start start of the buffer (for bounds-checking) * \param key PK context which must contain a valid public or private key. * * \return the length written or a negative error code */ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *key); #endif /* MBEDTLS_PK_WRITE_C */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_PK_H */ webfakes/src/mbedtls/include/mbedtls/compat-2.x.h0000644000176200001440000000330714740737024021413 0ustar liggesusers/** * \file compat-2.x.h * * \brief Compatibility definitions * * \deprecated Use the new names directly instead */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #if defined(MBEDTLS_DEPRECATED_WARNING) #warning "Including compat-2.x.h is deprecated" #endif #ifndef MBEDTLS_COMPAT2X_H #define MBEDTLS_COMPAT2X_H /* * Macros for renamed functions */ #define mbedtls_ctr_drbg_update_ret mbedtls_ctr_drbg_update #define mbedtls_hmac_drbg_update_ret mbedtls_hmac_drbg_update #define mbedtls_md5_starts_ret mbedtls_md5_starts #define mbedtls_md5_update_ret mbedtls_md5_update #define mbedtls_md5_finish_ret mbedtls_md5_finish #define mbedtls_md5_ret mbedtls_md5 #define mbedtls_ripemd160_starts_ret mbedtls_ripemd160_starts #define mbedtls_ripemd160_update_ret mbedtls_ripemd160_update #define mbedtls_ripemd160_finish_ret mbedtls_ripemd160_finish #define mbedtls_ripemd160_ret mbedtls_ripemd160 #define mbedtls_sha1_starts_ret mbedtls_sha1_starts #define mbedtls_sha1_update_ret mbedtls_sha1_update #define mbedtls_sha1_finish_ret mbedtls_sha1_finish #define mbedtls_sha1_ret mbedtls_sha1 #define mbedtls_sha256_starts_ret mbedtls_sha256_starts #define mbedtls_sha256_update_ret mbedtls_sha256_update #define mbedtls_sha256_finish_ret mbedtls_sha256_finish #define mbedtls_sha256_ret mbedtls_sha256 #define mbedtls_sha512_starts_ret mbedtls_sha512_starts #define mbedtls_sha512_update_ret mbedtls_sha512_update #define mbedtls_sha512_finish_ret mbedtls_sha512_finish #define mbedtls_sha512_ret mbedtls_sha512 #endif /* MBEDTLS_COMPAT2X_H */ webfakes/src/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h0000644000176200001440000001210514740737024026457 0ustar liggesusers/** * \file mbedtls/config_adjust_psa_superset_legacy.h * \brief Adjust PSA configuration: automatic enablement from legacy * * This is an internal header. Do not include it directly. * * To simplify some edge cases, we automatically enable certain cryptographic * mechanisms in the PSA API if they are enabled in the legacy API. The general * idea is that if legacy module M uses mechanism A internally, and A has * both a legacy and a PSA implementation, we enable A through PSA whenever * it's enabled through legacy. This facilitates the transition to PSA * implementations of A for users of M. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H #define MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ /****************************************************************/ /* Hashes that are built in are also enabled in PSA. * This simplifies dependency declarations especially * for modules that obey MBEDTLS_USE_PSA_CRYPTO. */ /****************************************************************/ #if defined(MBEDTLS_MD5_C) #define PSA_WANT_ALG_MD5 1 #endif #if defined(MBEDTLS_RIPEMD160_C) #define PSA_WANT_ALG_RIPEMD160 1 #endif #if defined(MBEDTLS_SHA1_C) #define PSA_WANT_ALG_SHA_1 1 #endif #if defined(MBEDTLS_SHA224_C) #define PSA_WANT_ALG_SHA_224 1 #endif #if defined(MBEDTLS_SHA256_C) #define PSA_WANT_ALG_SHA_256 1 #endif #if defined(MBEDTLS_SHA384_C) #define PSA_WANT_ALG_SHA_384 1 #endif #if defined(MBEDTLS_SHA512_C) #define PSA_WANT_ALG_SHA_512 1 #endif #if defined(MBEDTLS_SHA3_C) #define PSA_WANT_ALG_SHA3_224 1 #define PSA_WANT_ALG_SHA3_256 1 #define PSA_WANT_ALG_SHA3_384 1 #define PSA_WANT_ALG_SHA3_512 1 #endif /* Ensure that the PSA's supported curves (PSA_WANT_ECC_xxx) are always a * superset of the builtin ones (MBEDTLS_ECP_DP_xxx). */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) #if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) #define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */ #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) #if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) #define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */ #endif /*MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) #if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) #define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */ #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #if !defined(PSA_WANT_ECC_MONTGOMERY_255) #define PSA_WANT_ECC_MONTGOMERY_255 1 #endif /* PSA_WANT_ECC_MONTGOMERY_255 */ #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #if !defined(PSA_WANT_ECC_MONTGOMERY_448) #define PSA_WANT_ECC_MONTGOMERY_448 1 #endif /* PSA_WANT_ECC_MONTGOMERY_448 */ #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_192) #define PSA_WANT_ECC_SECP_R1_192 1 #endif /* PSA_WANT_ECC_SECP_R1_192 */ #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_224) #define PSA_WANT_ECC_SECP_R1_224 1 #endif /* PSA_WANT_ECC_SECP_R1_224 */ #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_256) #define PSA_WANT_ECC_SECP_R1_256 1 #endif /* PSA_WANT_ECC_SECP_R1_256 */ #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_384) #define PSA_WANT_ECC_SECP_R1_384 1 #endif /* PSA_WANT_ECC_SECP_R1_384 */ #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_521) #define PSA_WANT_ECC_SECP_R1_521 1 #endif /* PSA_WANT_ECC_SECP_R1_521 */ #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_K1_192) #define PSA_WANT_ECC_SECP_K1_192 1 #endif /* PSA_WANT_ECC_SECP_K1_192 */ #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ /* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */ #if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_K1_224) #define PSA_WANT_ECC_SECP_K1_224 1 #endif /* PSA_WANT_ECC_SECP_K1_224 */ #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_K1_256) #define PSA_WANT_ECC_SECP_K1_256 1 #endif /* PSA_WANT_ECC_SECP_K1_256 */ #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #endif /* MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H */ webfakes/src/mbedtls/include/mbedtls/pkcs5.h0000644000176200001440000002016314740737024020547 0ustar liggesusers/** * \file pkcs5.h * * \brief PKCS#5 functions * * \author Mathias Olsson */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PKCS5_H #define MBEDTLS_PKCS5_H #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include "mbedtls/asn1.h" #include "mbedtls/md.h" #include "mbedtls/cipher.h" #include #include /** Bad input parameters to function. */ #define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /** Unexpected ASN.1 data. */ #define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /** Requested encryption or digest alg not available. */ #define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /** Given private key password does not allow for correct decryption. */ #define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 #define MBEDTLS_PKCS5_DECRYPT MBEDTLS_DECRYPT #define MBEDTLS_PKCS5_ENCRYPT MBEDTLS_ENCRYPT #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief PKCS#5 PBES2 function * * \note When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must * be enabled at compile time. * * \deprecated This function is deprecated and will be removed in a * future version of the library. * Please use mbedtls_pkcs5_pbes2_ext() instead. * * \warning When decrypting: * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile * time, this function validates the CBC padding and returns * #MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH if the padding is * invalid. Note that this can help active adversaries * attempting to brute-forcing the password. Note also that * there is no guarantee that an invalid password will be * detected (the chances of a valid padding with a random * password are about 1/255). * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is disabled at compile * time, this function does not validate the CBC padding. * * \param pbe_params the ASN.1 algorithm parameters * \param mode either #MBEDTLS_PKCS5_DECRYPT or #MBEDTLS_PKCS5_ENCRYPT * \param pwd password to use when generating key * \param pwdlen length of password * \param data data to process * \param datalen length of data * \param output Output buffer. * On success, it contains the encrypted or decrypted data, * possibly followed by the CBC padding. * On failure, the content is indeterminate. * For decryption, there must be enough room for \p datalen * bytes. * For encryption, there must be enough room for * \p datalen + 1 bytes, rounded up to the block size of * the block cipher identified by \p pbe_params. * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. */ int MBEDTLS_DEPRECATED mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output); #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) /** * \brief PKCS#5 PBES2 function * * \warning When decrypting: * - This function validates the CBC padding and returns * #MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH if the padding is * invalid. Note that this can help active adversaries * attempting to brute-forcing the password. Note also that * there is no guarantee that an invalid password will be * detected (the chances of a valid padding with a random * password are about 1/255). * * \param pbe_params the ASN.1 algorithm parameters * \param mode either #MBEDTLS_PKCS5_DECRYPT or #MBEDTLS_PKCS5_ENCRYPT * \param pwd password to use when generating key * \param pwdlen length of password * \param data data to process * \param datalen length of data * \param output Output buffer. * On success, it contains the decrypted data. * On failure, the content is indetermidate. * For decryption, there must be enough room for \p datalen * bytes. * For encryption, there must be enough room for * \p datalen + 1 bytes, rounded up to the block size of * the block cipher identified by \p pbe_params. * \param output_size size of output buffer. * This must be big enough to accommodate for output plus * padding data. * \param output_len On success, length of actual data written to the output buffer. * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if parsing or decryption fails. */ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output, size_t output_size, size_t *output_len); #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ #endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C*/ /** * \brief PKCS#5 PBKDF2 using HMAC without using the HMAC context * * \param md_type Hash algorithm used * \param password Password to use when generating key * \param plen Length of password * \param salt Salt to use when generating key * \param slen Length of salt * \param iteration_count Iteration count * \param key_length Length of generated key in bytes * \param output Generated key. Must be at least as big as key_length * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. */ int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_type, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output); #if defined(MBEDTLS_MD_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief PKCS#5 PBKDF2 using HMAC * * \deprecated Superseded by mbedtls_pkcs5_pbkdf2_hmac_ext(). * * \param ctx Generic HMAC context * \param password Password to use when generating key * \param plen Length of password * \param salt Salt to use when generating key * \param slen Length of salt * \param iteration_count Iteration count * \param key_length Length of generated key in bytes * \param output Generated key. Must be at least as big as key_length * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. */ int MBEDTLS_DEPRECATED mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output); #endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_pkcs5_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* pkcs5.h */ webfakes/src/mbedtls/include/mbedtls/ccm.h0000644000176200001440000006174414740737024020276 0ustar liggesusers/** * \file ccm.h * * \brief This file provides an API for the CCM authenticated encryption * mode for block ciphers. * * CCM combines Counter mode encryption with CBC-MAC authentication * for 128-bit block ciphers. * * Input to CCM includes the following elements: *
  • Payload - data that is both authenticated and encrypted.
  • *
  • Associated data (Adata) - data that is authenticated but not * encrypted, For example, a header.
  • *
  • Nonce - A unique value that is assigned to the payload and the * associated data.
* * Definition of CCM: * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf * RFC 3610 "Counter with CBC-MAC (CCM)" * * Related: * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" * * Definition of CCM*: * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks * Integer representation is fixed most-significant-octet-first order and * the representation of octets is most-significant-bit-first order. This is * consistent with RFC 3610. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CCM_H #define MBEDTLS_CCM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #include "mbedtls/block_cipher.h" #endif #define MBEDTLS_CCM_DECRYPT 0 #define MBEDTLS_CCM_ENCRYPT 1 #define MBEDTLS_CCM_STAR_DECRYPT 2 #define MBEDTLS_CCM_STAR_ENCRYPT 3 /** Bad input parameters to the function. */ #define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /** Authenticated decryption failed. */ #define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_CCM_ALT) // Regular implementation // /** * \brief The CCM context-type definition. The CCM context is passed * to the APIs called. */ typedef struct mbedtls_ccm_context { unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working buffer */ unsigned char MBEDTLS_PRIVATE(ctr)[16]; /*!< The counter buffer */ size_t MBEDTLS_PRIVATE(plaintext_len); /*!< Total plaintext length */ size_t MBEDTLS_PRIVATE(add_len); /*!< Total authentication data length */ size_t MBEDTLS_PRIVATE(tag_len); /*!< Total tag length */ size_t MBEDTLS_PRIVATE(processed); /*!< Track how many bytes of input data were processed (chunked input). Used independently for both auth data and plaintext/ciphertext. This variable is set to zero after auth data input is finished. */ unsigned int MBEDTLS_PRIVATE(q); /*!< The Q working value */ unsigned int MBEDTLS_PRIVATE(mode); /*!< The operation to perform: #MBEDTLS_CCM_ENCRYPT or #MBEDTLS_CCM_DECRYPT or #MBEDTLS_CCM_STAR_ENCRYPT or #MBEDTLS_CCM_STAR_DECRYPT. */ #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx); /*!< The cipher context used. */ #else mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ #endif int MBEDTLS_PRIVATE(state); /*!< Working value holding context's state. Used for chunked data input */ } mbedtls_ccm_context; #else /* MBEDTLS_CCM_ALT */ #include "ccm_alt.h" #endif /* MBEDTLS_CCM_ALT */ /** * \brief This function initializes the specified CCM context, * to make references valid, and prepare the context * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). * * \param ctx The CCM context to initialize. This must not be \c NULL. */ void mbedtls_ccm_init(mbedtls_ccm_context *ctx); /** * \brief This function initializes the CCM context set in the * \p ctx parameter and sets the encryption key. * * \param ctx The CCM context to initialize. This must be an initialized * context. * \param cipher The 128-bit block cipher to use. * \param key The encryption key. This must not be \c NULL. * \param keybits The key size in bits. This must be acceptable by the cipher. * * \return \c 0 on success. * \return A CCM or cipher-specific error code on failure. */ int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits); /** * \brief This function releases and clears the specified CCM context * and underlying cipher sub-context. * * \param ctx The CCM context to clear. If this is \c NULL, the function * has no effect. Otherwise, this must be initialized. */ void mbedtls_ccm_free(mbedtls_ccm_context *ctx); /** * \brief This function encrypts a buffer using CCM. * * \note The tag is written to a separate buffer. To concatenate * the \p tag with the \p output, as done in RFC-3610: * Counter with CBC-MAC (CCM), use * \p tag = \p output + \p length, and make sure that the * output buffer is at least \p length + \p tag_len wide. * * \param ctx The CCM context to use for encryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * \param ad The additional data field. If \p ad_len is greater than * zero, \p ad must be a readable buffer of at least that * length. * \param ad_len The length of additional data in Bytes. * This must be less than `2^16 - 2^8`. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. * \param output The buffer holding the output data. If \p length is greater * than zero, \p output must be a writable buffer of at least * that length. * \param tag The buffer holding the authentication field. This must be a * writable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * * \return \c 0 on success. * \return A CCM or cipher-specific error code on failure. */ int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len); /** * \brief This function encrypts a buffer using CCM*. * * \note The tag is written to a separate buffer. To concatenate * the \p tag with the \p output, as done in RFC-3610: * Counter with CBC-MAC (CCM), use * \p tag = \p output + \p length, and make sure that the * output buffer is at least \p length + \p tag_len wide. * * \note When using this function in a variable tag length context, * the tag length has to be encoded into the \p iv passed to * this function. * * \param ctx The CCM context to use for encryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. * For tag length = 0, input length is ignored. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * \param ad The additional data field. This must be a readable buffer of * at least \p ad_len Bytes. * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. * \param output The buffer holding the output data. If \p length is greater * than zero, \p output must be a writable buffer of at least * that length. * \param tag The buffer holding the authentication field. This must be a * writable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field to generate in Bytes: * 0, 4, 6, 8, 10, 12, 14 or 16. * * \warning Passing \c 0 as \p tag_len means that the message is no * longer authenticated. * * \return \c 0 on success. * \return A CCM or cipher-specific error code on failure. */ int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len); /** * \brief This function performs a CCM authenticated decryption of a * buffer. * * \param ctx The CCM context to use for decryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * \param ad The additional data field. This must be a readable buffer * of at least that \p ad_len Bytes.. * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. * \param output The buffer holding the output data. If \p length is greater * than zero, \p output must be a writable buffer of at least * that length. * \param tag The buffer holding the authentication field. This must be a * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * * \return \c 0 on success. This indicates that the message is authentic. * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. * \return A cipher-specific error code on calculation failure. */ int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len); /** * \brief This function performs a CCM* authenticated decryption of a * buffer. * * \note When using this function in a variable tag length context, * the tag length has to be decoded from \p iv and passed to * this function as \p tag_len. (\p tag needs to be adjusted * accordingly.) * * \param ctx The CCM context to use for decryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. * For tag length = 0, input length is ignored. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * \param ad The additional data field. This must be a readable buffer of * at least that \p ad_len Bytes. * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. * \param output The buffer holding the output data. If \p length is greater * than zero, \p output must be a writable buffer of at least * that length. * \param tag The buffer holding the authentication field. This must be a * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field in Bytes. * 0, 4, 6, 8, 10, 12, 14 or 16. * * \warning Passing \c 0 as \p tag_len means that the message is nos * longer authenticated. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. * \return A cipher-specific error code on calculation failure. */ int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len); /** * \brief This function starts a CCM encryption or decryption * operation. * * This function and mbedtls_ccm_set_lengths() must be called * before calling mbedtls_ccm_update_ad() or * mbedtls_ccm_update(). This function can be called before * or after mbedtls_ccm_set_lengths(). * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must be initialized. * \param mode The operation to perform: #MBEDTLS_CCM_ENCRYPT or * #MBEDTLS_CCM_DECRYPT or #MBEDTLS_CCM_STAR_ENCRYPT or * #MBEDTLS_CCM_STAR_DECRYPT. * \param iv The initialization vector. This must be a readable buffer * of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * \p mode is invalid, * \p iv_len is invalid (lower than \c 7 or greater than * \c 13). */ int mbedtls_ccm_starts(mbedtls_ccm_context *ctx, int mode, const unsigned char *iv, size_t iv_len); /** * \brief This function declares the lengths of the message * and additional data for a CCM encryption or decryption * operation. * * This function and mbedtls_ccm_starts() must be called * before calling mbedtls_ccm_update_ad() or * mbedtls_ccm_update(). This function can be called before * or after mbedtls_ccm_starts(). * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must be initialized. * \param total_ad_len The total length of additional data in bytes. * This must be less than `2^16 - 2^8`. * \param plaintext_len The length in bytes of the plaintext to encrypt or * result of the decryption (thus not encompassing the * additional data that are not encrypted). * \param tag_len The length of the tag to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * For CCM*, zero is also valid. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * \p total_ad_len is greater than \c 0xFF00. */ int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, size_t total_ad_len, size_t plaintext_len, size_t tag_len); /** * \brief This function feeds an input buffer as associated data * (authenticated but not encrypted data) in a CCM * encryption or decryption operation. * * You may call this function zero, one or more times * to pass successive parts of the additional data. The * lengths \p ad_len of the data parts should eventually add * up exactly to the total length of additional data * \c total_ad_len passed to mbedtls_ccm_set_lengths(). You * may not call this function after calling * mbedtls_ccm_update(). * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must have been started with * mbedtls_ccm_starts(), the lengths of the message and * additional data must have been declared with * mbedtls_ccm_set_lengths() and this must not have yet * received any input with mbedtls_ccm_update(). * \param ad The buffer holding the additional data, or \c NULL * if \p ad_len is \c 0. * \param ad_len The length of the additional data. If \c 0, * \p ad may be \c NULL. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * total input length too long. */ int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, const unsigned char *ad, size_t ad_len); /** * \brief This function feeds an input buffer into an ongoing CCM * encryption or decryption operation. * * You may call this function zero, one or more times * to pass successive parts of the input: the plaintext to * encrypt, or the ciphertext (not including the tag) to * decrypt. After the last part of the input, call * mbedtls_ccm_finish(). The lengths \p input_len of the * data parts should eventually add up exactly to the * plaintext length \c plaintext_len passed to * mbedtls_ccm_set_lengths(). * * This function may produce output in one of the following * ways: * - Immediate output: the output length is always equal * to the input length. * - Buffered output: except for the last part of input data, * the output consists of a whole number of 16-byte blocks. * If the total input length so far (not including * associated data) is 16 \* *B* + *A* with *A* < 16 then * the total output length is 16 \* *B*. * For the last part of input data, the output length is * equal to the input length plus the number of bytes (*A*) * buffered in the previous call to the function (if any). * The function uses the plaintext length * \c plaintext_len passed to mbedtls_ccm_set_lengths() * to detect the last part of input data. * * In particular: * - It is always correct to call this function with * \p output_size >= \p input_len + 15. * - If \p input_len is a multiple of 16 for all the calls * to this function during an operation (not necessary for * the last one) then it is correct to use \p output_size * =\p input_len. * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must have been started with * mbedtls_ccm_starts() and the lengths of the message and * additional data must have been declared with * mbedtls_ccm_set_lengths(). * \param input The buffer holding the input data. If \p input_len * is greater than zero, this must be a readable buffer * of at least \p input_len bytes. * \param input_len The length of the input data in bytes. * \param output The buffer for the output data. If \p output_size * is greater than zero, this must be a writable buffer of * at least \p output_size bytes. * \param output_size The size of the output buffer in bytes. * See the function description regarding the output size. * \param output_len On success, \p *output_len contains the actual * length of the output written in \p output. * On failure, the content of \p *output_len is * unspecified. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * total input length too long, * or \p output_size too small. */ int mbedtls_ccm_update(mbedtls_ccm_context *ctx, const unsigned char *input, size_t input_len, unsigned char *output, size_t output_size, size_t *output_len); /** * \brief This function finishes the CCM operation and generates * the authentication tag. * * It wraps up the CCM stream, and generates the * tag. The tag can have a maximum length of 16 Bytes. * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must have been started with * mbedtls_ccm_starts() and the lengths of the message and * additional data must have been declared with * mbedtls_ccm_set_lengths(). * \param tag The buffer for holding the tag. If \p tag_len is greater * than zero, this must be a writable buffer of at least \p * tag_len Bytes. * \param tag_len The length of the tag. Must match the tag length passed to * mbedtls_ccm_set_lengths() function. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * invalid value of \p tag_len, * the total amount of additional data passed to * mbedtls_ccm_update_ad() was lower than the total length of * additional data \c total_ad_len passed to * mbedtls_ccm_set_lengths(), * the total amount of input data passed to * mbedtls_ccm_update() was lower than the plaintext length * \c plaintext_len passed to mbedtls_ccm_set_lengths(). */ int mbedtls_ccm_finish(mbedtls_ccm_context *ctx, unsigned char *tag, size_t tag_len); #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) /** * \brief The CCM checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_ccm_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CCM_H */ webfakes/src/mbedtls/include/mbedtls/x509_crt.h0000644000176200001440000015643114740737024021107 0ustar liggesusers/** * \file x509_crt.h * * \brief X.509 certificate parsing and writing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_CRT_H #define MBEDTLS_X509_CRT_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/x509.h" #include "mbedtls/x509_crl.h" #include "mbedtls/bignum.h" /** * \addtogroup x509_module * \{ */ #ifdef __cplusplus extern "C" { #endif /** * \name Structures and functions for parsing and writing X.509 certificates * \{ */ /** * Container for an X.509 certificate. The certificate may be chained. * * Some fields of this structure are publicly readable. Do not modify * them except via Mbed TLS library functions: the effect of modifying * those fields or the data that those fields points to is unspecified. */ typedef struct mbedtls_x509_crt { int MBEDTLS_PRIVATE(own_buffer); /**< Indicates if \c raw is owned * by the structure or not. */ mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ mbedtls_x509_time valid_to; /**< End time of certificate validity. */ mbedtls_x509_buf pk_raw; mbedtls_pk_context pk; /**< Container for the public key context. */ mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */ mbedtls_x509_buf subject_key_id; /**< Optional X.509 v3 extension subject key identifier. */ mbedtls_x509_authority authority_key_id; /**< Optional X.509 v3 extension authority key identifier. */ mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */ int MBEDTLS_PRIVATE(ext_types); /**< Bit string containing detected and parsed extensions */ int MBEDTLS_PRIVATE(ca_istrue); /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ int MBEDTLS_PRIVATE(max_pathlen); /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ unsigned int MBEDTLS_PRIVATE(key_usage); /**< Optional key usage extension value: See the values in x509.h */ mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ unsigned char MBEDTLS_PRIVATE(ns_cert_type); /**< Optional Netscape certificate type extension value: See the values in x509.h */ mbedtls_x509_buf MBEDTLS_PRIVATE(sig); /**< Signature: hash of the tbs part signed with the private key. */ mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ /** Next certificate in the linked list that constitutes the CA chain. * \p NULL indicates the end of the list. * Do not modify this field directly. */ struct mbedtls_x509_crt *next; } mbedtls_x509_crt; /** * Build flag from an algorithm/curve identifier (pk, md, ecp) * Since 0 is always XXX_NONE, ignore it. */ #define MBEDTLS_X509_ID_FLAG(id) (1 << ((id) - 1)) /** * Security profile for certificate verification. * * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). * * The fields of this structure are part of the public API and can be * manipulated directly by applications. Future versions of the library may * add extra fields or reorder existing fields. * * You can create custom profiles by starting from a copy of * an existing profile, such as mbedtls_x509_crt_profile_default or * mbedtls_x509_ctr_profile_none and then tune it to your needs. * * For example to allow SHA-224 in addition to the default: * * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_default; * my_profile.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ); * * Or to allow only RSA-3072+ with SHA-256: * * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_none; * my_profile.allowed_mds = MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ); * my_profile.allowed_pks = MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_RSA ); * my_profile.rsa_min_bitlen = 3072; */ typedef struct mbedtls_x509_crt_profile { uint32_t allowed_mds; /**< MDs for signatures */ uint32_t allowed_pks; /**< PK algs for public keys; * this applies to all certificates * in the provided chain. */ uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ } mbedtls_x509_crt_profile; #define MBEDTLS_X509_CRT_VERSION_1 0 #define MBEDTLS_X509_CRT_VERSION_2 1 #define MBEDTLS_X509_CRT_VERSION_3 2 #define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 20 #define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 #if !defined(MBEDTLS_X509_MAX_FILE_PATH_LEN) #define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 #endif /* This macro unfolds to the concatenation of macro invocations * X509_CRT_ERROR_INFO( error code, * error code as string, * human readable description ) * where X509_CRT_ERROR_INFO is defined by the user. * See x509_crt.c for an example of how to use this. */ #define MBEDTLS_X509_CRT_ERROR_INFO_LIST \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXPIRED, \ "MBEDTLS_X509_BADCERT_EXPIRED", \ "The certificate validity has expired") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_REVOKED, \ "MBEDTLS_X509_BADCERT_REVOKED", \ "The certificate has been revoked (is on a CRL)") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_CN_MISMATCH, \ "MBEDTLS_X509_BADCERT_CN_MISMATCH", \ "The certificate Common Name (CN) does not match with the expected CN") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NOT_TRUSTED, \ "MBEDTLS_X509_BADCERT_NOT_TRUSTED", \ "The certificate is not correctly signed by the trusted CA") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_NOT_TRUSTED, \ "MBEDTLS_X509_BADCRL_NOT_TRUSTED", \ "The CRL is not correctly signed by the trusted CA") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_EXPIRED, \ "MBEDTLS_X509_BADCRL_EXPIRED", \ "The CRL is expired") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_MISSING, \ "MBEDTLS_X509_BADCERT_MISSING", \ "Certificate was missing") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_SKIP_VERIFY, \ "MBEDTLS_X509_BADCERT_SKIP_VERIFY", \ "Certificate verification was skipped") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_OTHER, \ "MBEDTLS_X509_BADCERT_OTHER", \ "Other reason (can be used by verify callback)") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_FUTURE, \ "MBEDTLS_X509_BADCERT_FUTURE", \ "The certificate validity starts in the future") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_FUTURE, \ "MBEDTLS_X509_BADCRL_FUTURE", \ "The CRL is from the future") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_KEY_USAGE, \ "MBEDTLS_X509_BADCERT_KEY_USAGE", \ "Usage does not match the keyUsage extension") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, \ "MBEDTLS_X509_BADCERT_EXT_KEY_USAGE", \ "Usage does not match the extendedKeyUsage extension") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NS_CERT_TYPE, \ "MBEDTLS_X509_BADCERT_NS_CERT_TYPE", \ "Usage does not match the nsCertType extension") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_MD, \ "MBEDTLS_X509_BADCERT_BAD_MD", \ "The certificate is signed with an unacceptable hash.") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_PK, \ "MBEDTLS_X509_BADCERT_BAD_PK", \ "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA).") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_KEY, \ "MBEDTLS_X509_BADCERT_BAD_KEY", \ "The certificate is signed with an unacceptable key (eg bad curve, RSA too short).") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_MD, \ "MBEDTLS_X509_BADCRL_BAD_MD", \ "The CRL is signed with an unacceptable hash.") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_PK, \ "MBEDTLS_X509_BADCRL_BAD_PK", \ "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA).") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_KEY, \ "MBEDTLS_X509_BADCRL_BAD_KEY", \ "The CRL is signed with an unacceptable key (eg bad curve, RSA too short).") /** * Container for writing a certificate (CRT) */ typedef struct mbedtls_x509write_cert { int MBEDTLS_PRIVATE(version); unsigned char MBEDTLS_PRIVATE(serial)[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN]; size_t MBEDTLS_PRIVATE(serial_len); mbedtls_pk_context *MBEDTLS_PRIVATE(subject_key); mbedtls_pk_context *MBEDTLS_PRIVATE(issuer_key); mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); mbedtls_asn1_named_data *MBEDTLS_PRIVATE(issuer); mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); char MBEDTLS_PRIVATE(not_before)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; char MBEDTLS_PRIVATE(not_after)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); } mbedtls_x509write_cert; /** * \brief Set Subject Alternative Name * * \param ctx Certificate context to use * \param san_list List of SAN values * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED * * \note "dnsName", "uniformResourceIdentifier", "IP address", * "otherName", and "DirectoryName", as defined in RFC 5280, * are supported. */ int mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx, const mbedtls_x509_san_list *san_list); /** * Item in a verification chain: cert and flags for it */ typedef struct { mbedtls_x509_crt *MBEDTLS_PRIVATE(crt); uint32_t MBEDTLS_PRIVATE(flags); } mbedtls_x509_crt_verify_chain_item; /** * Max size of verification chain: end-entity + intermediates + trusted root */ #define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2) /** * Verification chain as built by \c mbedtls_crt_verify_chain() */ typedef struct { mbedtls_x509_crt_verify_chain_item MBEDTLS_PRIVATE(items)[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; unsigned MBEDTLS_PRIVATE(len); #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /* This stores the list of potential trusted signers obtained from * the CA callback used for the CRT verification, if configured. * We must track it somewhere because the callback passes its * ownership to the caller. */ mbedtls_x509_crt *MBEDTLS_PRIVATE(trust_ca_cb_result); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } mbedtls_x509_crt_verify_chain; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Context for resuming X.509 verify operations */ typedef struct { /* for check_signature() */ mbedtls_pk_restart_ctx MBEDTLS_PRIVATE(pk); /* for find_parent_in() */ mbedtls_x509_crt *MBEDTLS_PRIVATE(parent); /* non-null iff parent_in in progress */ mbedtls_x509_crt *MBEDTLS_PRIVATE(fallback_parent); int MBEDTLS_PRIVATE(fallback_signature_is_good); /* for find_parent() */ int MBEDTLS_PRIVATE(parent_is_trusted); /* -1 if find_parent is not in progress */ /* for verify_chain() */ enum { x509_crt_rs_none, x509_crt_rs_find_parent, } MBEDTLS_PRIVATE(in_progress); /* none if no operation is in progress */ int MBEDTLS_PRIVATE(self_cnt); mbedtls_x509_crt_verify_chain MBEDTLS_PRIVATE(ver_chain); } mbedtls_x509_crt_restart_ctx; #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* Now we can declare functions that take a pointer to that */ typedef void mbedtls_x509_crt_restart_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * Default security profile. Should provide a good balance between security * and compatibility with current deployments. * * This profile permits: * - SHA2 hashes with at least 256 bits: SHA-256, SHA-384, SHA-512. * - Elliptic curves with 255 bits and above except secp256k1. * - RSA with 2048 bits and above. * * New minor versions of Mbed TLS may extend this profile, for example if * new algorithms are added to the library. New minor versions of Mbed TLS will * not reduce this profile unless serious security concerns require it. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; /** * Expected next default profile. Recommended for new deployments. * Currently targets a 128-bit security level, except for allowing RSA-2048. * This profile may change at any time. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; /** * NSA Suite B profile. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; /** * Empty profile that allows nothing. Useful as a basis for constructing * custom profiles. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none; /** * \brief Parse a single DER formatted certificate and add it * to the end of the provided chained list. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain The pointer to the start of the CRT chain to attach to. * When parsing the first CRT in a chain, this should point * to an instance of ::mbedtls_x509_crt initialized through * mbedtls_x509_crt_init(). * \param buf The buffer holding the DER encoded certificate. * \param buflen The size in Bytes of \p buf. * * \note This function makes an internal copy of the CRT buffer * \p buf. In particular, \p buf may be destroyed or reused * after this call returns. To avoid duplicating the CRT * buffer (at the cost of stricter lifetime constraints), * use mbedtls_x509_crt_parse_der_nocopy() instead. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen); /** * \brief The type of certificate extension callbacks. * * Callbacks of this type are passed to and used by the * mbedtls_x509_crt_parse_der_with_ext_cb() routine when * it encounters either an unsupported extension or a * "certificate policies" extension containing any * unsupported certificate policies. * Future versions of the library may invoke the callback * in other cases, if and when the need arises. * * \param p_ctx An opaque context passed to the callback. * \param crt The certificate being parsed. * \param oid The OID of the extension. * \param critical Whether the extension is critical. * \param p Pointer to the start of the extension value * (the content of the OCTET STRING). * \param end End of extension value. * * \note The callback must fail and return a negative error code * if it can not parse or does not support the extension. * When the callback fails to parse a critical extension * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. * When the callback fails to parse a non critical extension * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips * the extension and continues parsing. * * \return \c 0 on success. * \return A negative error code on failure. */ typedef int (*mbedtls_x509_crt_ext_cb_t)(void *p_ctx, mbedtls_x509_crt const *crt, mbedtls_x509_buf const *oid, int critical, const unsigned char *p, const unsigned char *end); /** * \brief Parse a single DER formatted certificate and add it * to the end of the provided chained list. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain The pointer to the start of the CRT chain to attach to. * When parsing the first CRT in a chain, this should point * to an instance of ::mbedtls_x509_crt initialized through * mbedtls_x509_crt_init(). * \param buf The buffer holding the DER encoded certificate. * \param buflen The size in Bytes of \p buf. * \param make_copy When not zero this function makes an internal copy of the * CRT buffer \p buf. In particular, \p buf may be destroyed * or reused after this call returns. * When zero this function avoids duplicating the CRT buffer * by taking temporary ownership thereof until the CRT * is destroyed (like mbedtls_x509_crt_parse_der_nocopy()) * \param cb A callback invoked for every unsupported certificate * extension. * \param p_ctx An opaque context passed to the callback. * * \note This call is functionally equivalent to * mbedtls_x509_crt_parse_der(), and/or * mbedtls_x509_crt_parse_der_nocopy() * but it calls the callback with every unsupported * certificate extension and additionally the * "certificate policies" extension if it contains any * unsupported certificate policies. * The callback must return a negative error code if it * does not know how to handle such an extension. * When the callback fails to parse a critical extension * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. * When the callback fails to parse a non critical extension * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips * the extension and continues parsing. * Future versions of the library may invoke the callback * in other cases, if and when the need arises. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen, int make_copy, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx); /** * \brief Parse a single DER formatted certificate and add it * to the end of the provided chained list. This is a * variant of mbedtls_x509_crt_parse_der() which takes * temporary ownership of the CRT buffer until the CRT * is destroyed. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain The pointer to the start of the CRT chain to attach to. * When parsing the first CRT in a chain, this should point * to an instance of ::mbedtls_x509_crt initialized through * mbedtls_x509_crt_init(). * \param buf The address of the readable buffer holding the DER encoded * certificate to use. On success, this buffer must be * retained and not be changed for the lifetime of the * CRT chain \p chain, that is, until \p chain is destroyed * through a call to mbedtls_x509_crt_free(). * \param buflen The size in Bytes of \p buf. * * \note This call is functionally equivalent to * mbedtls_x509_crt_parse_der(), but it avoids creating a * copy of the input buffer at the cost of stronger lifetime * constraints. This is useful in constrained environments * where duplication of the CRT cannot be tolerated. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen); /** * \brief Parse one DER-encoded or one or more concatenated PEM-encoded * certificates and add them to the chained list. * * For CRTs in PEM encoding, the function parses permissively: * if at least one certificate can be parsed, the function * returns the number of certificates for which parsing failed * (hence \c 0 if all certificates were parsed successfully). * If no certificate could be parsed, the function returns * the first (negative) error encountered during parsing. * * PEM encoded certificates may be interleaved by other data * such as human readable descriptions of their content, as * long as the certificates are enclosed in the PEM specific * '-----{BEGIN/END} CERTIFICATE-----' delimiters. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain The chain to which to add the parsed certificates. * \param buf The buffer holding the certificate data in PEM or DER format. * For certificates in PEM encoding, this may be a concatenation * of multiple certificates; for DER encoding, the buffer must * comprise exactly one certificate. * \param buflen The size of \p buf, including the terminating \c NULL byte * in case of PEM encoded data. * * \return \c 0 if all certificates were parsed successfully. * \return The (positive) number of certificates that couldn't * be parsed if parsing was partly successful (see above). * \return A negative X509 or PEM error code otherwise. * */ int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen); #if defined(MBEDTLS_FS_IO) /** * \brief Load one or more certificates and add them * to the chained list. Parses permissively. If some * certificates can be parsed, the result is the number * of failed certificates it encountered. If none complete * correctly, the first error is returned. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain points to the start of the chain * \param path filename to read the certificates from * * \return 0 if all certificates parsed successfully, a positive number * if partly successful or a specific X509 or PEM error code */ int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path); /** * \brief Load one or more certificate files from a path and add them * to the chained list. Parses permissively. If some * certificates can be parsed, the result is the number * of failed certificates it encountered. If none complete * correctly, the first error is returned. * * \param chain points to the start of the chain * \param path directory / folder to read the certificate files from * * \return 0 if all certificates parsed successfully, a positive number * if partly successful or a specific X509 or PEM error code */ int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path); #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Returns an informational string about the * certificate. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param prefix A line prefix * \param crt The X509 certificate to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crt *crt); /** * \brief Returns an informational string about the * verification status of a certificate. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param prefix A line prefix * \param flags Verification flags created by mbedtls_x509_crt_verify() * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, uint32_t flags); #endif /* !MBEDTLS_X509_REMOVE_INFO */ /** * \brief Verify a chain of certificates. * * The verify callback is a user-supplied callback that * can clear / modify / add flags for a certificate. If set, * the verification callback is called for each * certificate in the chain (from the trust-ca down to the * presented crt). The parameters for the callback are: * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, * int *flags). With the flags representing current flags for * that specific certificate and the certificate depth from * the bottom (Peer cert depth = 0). * * All flags left after returning from the callback * are also returned to the application. The function should * return 0 for anything (including invalid certificates) * other than fatal error, as a non-zero return code * immediately aborts the verification process. For fatal * errors, a specific error code should be used (different * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR * can be used if no better code is available. * * \note In case verification failed, the results can be displayed * using \c mbedtls_x509_crt_verify_info() * * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the * default security profile. * * \note It is your responsibility to provide up-to-date CRLs for * all trusted CAs. If no CRL is provided for the CA that was * used to sign the certificate, CRL verification is skipped * silently, that is *without* setting any flag. * * \note The \c trust_ca list can contain two types of certificates: * (1) those of trusted root CAs, so that certificates * chaining up to those CAs will be trusted, and (2) * self-signed end-entity certificates to be trusted (for * specific peers you know) - in that case, the self-signed * certificate doesn't need to have the CA bit set. * * \param crt The certificate chain to be verified. * \param trust_ca The list of trusted CAs. * \param ca_crl The list of CRLs for trusted CAs. * \param cn The expected Common Name. This will be checked to be * present in the certificate's subjectAltNames extension or, * if this extension is absent, as a CN component in its * Subject name. DNS names and IP addresses are fully * supported, while the URI subtype is partially supported: * only exact matching, without any normalization procedures * described in 7.4 of RFC5280, will result in a positive * URI verification. * This may be \c NULL if the CN need not be verified. * \param flags The address at which to store the result of the verification. * If the verification couldn't be completed, the flag value is * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. * * \return \c 0 if the chain is valid with respect to the * passed CN, CAs, CRLs and security profile. * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the * certificate chain verification failed. In this case, * \c *flags will have one or more * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX * flags set. * \return Another negative error code in case of a fatal error * encountered during the verification process. */ int mbedtls_x509_crt_verify(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); /** * \brief Verify a chain of certificates with respect to * a configurable security profile. * * \note Same as \c mbedtls_x509_crt_verify(), but with explicit * security profile. * * \note The restrictions on keys (RSA minimum size, allowed curves * for ECDSA) apply to all certificates: trusted root, * intermediate CAs if any, and end entity certificate. * * \param crt The certificate chain to be verified. * \param trust_ca The list of trusted CAs. * \param ca_crl The list of CRLs for trusted CAs. * \param profile The security profile to use for the verification. * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. * If the verification couldn't be completed, the flag value is * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. * * \return \c 0 if the chain is valid with respect to the * passed CN, CAs, CRLs and security profile. * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the * certificate chain verification failed. In this case, * \c *flags will have one or more * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX * flags set. * \return Another negative error code in case of a fatal error * encountered during the verification process. */ int mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); /** * \brief Restartable version of \c mbedtls_crt_verify_with_profile() * * \note Performs the same job as \c mbedtls_crt_verify_with_profile() * but can return early and restart according to the limit * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \param crt The certificate chain to be verified. * \param trust_ca The list of trusted CAs. * \param ca_crl The list of CRLs for trusted CAs. * \param profile The security profile to use for the verification. * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. * If the verification couldn't be completed, the flag value is * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. * \param rs_ctx The restart context to use. This may be set to \c NULL * to disable restartable ECC. * * \return See \c mbedtls_crt_verify_with_profile(), or * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx); /** * \brief The type of trusted certificate callbacks. * * Callbacks of this type are passed to and used by the CRT * verification routine mbedtls_x509_crt_verify_with_ca_cb() * when looking for trusted signers of a given certificate. * * On success, the callback returns a list of trusted * certificates to be considered as potential signers * for the input certificate. * * \param p_ctx An opaque context passed to the callback. * \param child The certificate for which to search a potential signer. * This will point to a readable certificate. * \param candidate_cas The address at which to store the address of the first * entry in the generated linked list of candidate signers. * This will not be \c NULL. * * \note The callback must only return a non-zero value on a * fatal error. If, in contrast, the search for a potential * signer completes without a single candidate, the * callback must return \c 0 and set \c *candidate_cas * to \c NULL. * * \return \c 0 on success. In this case, \c *candidate_cas points * to a heap-allocated linked list of instances of * ::mbedtls_x509_crt, and ownership of this list is passed * to the caller. * \return A negative error code on failure. */ typedef int (*mbedtls_x509_crt_ca_cb_t)(void *p_ctx, mbedtls_x509_crt const *child, mbedtls_x509_crt **candidate_cas); #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /** * \brief Version of \c mbedtls_x509_crt_verify_with_profile() which * uses a callback to acquire the list of trusted CA * certificates. * * \param crt The certificate chain to be verified. * \param f_ca_cb The callback to be used to query for potential signers * of a given child certificate. See the documentation of * ::mbedtls_x509_crt_ca_cb_t for more information. * \param p_ca_cb The opaque context to be passed to \p f_ca_cb. * \param profile The security profile for the verification. * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. * If the verification couldn't be completed, the flag value is * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. * * \return See \c mbedtls_crt_verify_with_profile(). */ int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ /** * \brief Check usage of certificate against keyUsage extension. * * \param crt Leaf certificate used. * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT * before using the certificate to perform an RSA key * exchange). * * \note Except for decipherOnly and encipherOnly, a bit set in the * usage argument means this bit MUST be set in the * certificate. For decipherOnly and encipherOnly, it means * that bit MAY be set. * * \return 0 is these uses of the certificate are allowed, * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension * is present but does not match the usage argument. * * \note You should only call this function on leaf certificates, on * (intermediate) CAs the keyUsage extension is automatically * checked by \c mbedtls_x509_crt_verify(). */ int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, unsigned int usage); /** * \brief Check usage of certificate against extendedKeyUsage. * * \param crt Leaf certificate used. * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or * MBEDTLS_OID_CLIENT_AUTH). * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). * * \return 0 if this use of the certificate is allowed, * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. * * \note Usually only makes sense on leaf certificates. */ int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, const char *usage_oid, size_t usage_len); #if defined(MBEDTLS_X509_CRL_PARSE_C) /** * \brief Verify the certificate revocation status * * \param crt a certificate to be verified * \param crl the CRL to verify against * * \return 1 if the certificate is revoked, 0 otherwise * */ int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl); #endif /* MBEDTLS_X509_CRL_PARSE_C */ /** * \brief Initialize a certificate (chain) * * \param crt Certificate chain to initialize */ void mbedtls_x509_crt_init(mbedtls_x509_crt *crt); /** * \brief Unallocate all certificate data * * \param crt Certificate chain to free */ void mbedtls_x509_crt_free(mbedtls_x509_crt *crt); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context */ void mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx); /** * \brief Free the components of a restart context */ void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** * \brief Query certificate for given extension type * * \param[in] ctx Certificate context to be queried, must not be \c NULL * \param ext_type Extension type being queried for, must be a valid * extension type. Must be one of the MBEDTLS_X509_EXT_XXX * values * * \return 0 if the given extension type is not present, * non-zero otherwise */ static inline int mbedtls_x509_crt_has_ext_type(const mbedtls_x509_crt *ctx, int ext_type) { return ctx->MBEDTLS_PRIVATE(ext_types) & ext_type; } /** * \brief Access the ca_istrue field * * \param[in] crt Certificate to be queried, must not be \c NULL * * \return \c 1 if this a CA certificate \c 0 otherwise. * \return MBEDTLS_ERR_X509_INVALID_EXTENSIONS if the certificate does not contain * the Optional Basic Constraint extension. * */ int mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt); /** \} name Structures and functions for parsing and writing X.509 certificates */ #if defined(MBEDTLS_X509_CRT_WRITE_C) /** * \brief Initialize a CRT writing context * * \param ctx CRT context to initialize */ void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx); /** * \brief Set the version for a Certificate * Default: MBEDTLS_X509_CRT_VERSION_3 * * \param ctx CRT context to use * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or * MBEDTLS_X509_CRT_VERSION_3) */ void mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx, int version); #if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the serial number for a Certificate. * * \deprecated This function is deprecated and will be removed in a * future version of the library. Please use * mbedtls_x509write_crt_set_serial_raw() instead. * * \note Even though the MBEDTLS_BIGNUM_C guard looks redundant since * X509 depends on PK and PK depends on BIGNUM, this emphasizes * a direct dependency between X509 and BIGNUM which is going * to be deprecated in the future. * * \param ctx CRT context to use * \param serial serial number to set * * \return 0 if successful */ int MBEDTLS_DEPRECATED mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial); #endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED /** * \brief Set the serial number for a Certificate. * * \param ctx CRT context to use * \param serial A raw array of bytes containing the serial number in big * endian format * \param serial_len Length of valid bytes (expressed in bytes) in \p serial * input buffer * * \return 0 if successful, or * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the provided input buffer * is too big (longer than MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) */ int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx, unsigned char *serial, size_t serial_len); /** * \brief Set the validity period for a Certificate * Timestamps should be in string format for UTC timezone * i.e. "YYYYMMDDhhmmss" * e.g. "20131231235959" for December 31st 2013 * at 23:59:59 * * \param ctx CRT context to use * \param not_before not_before timestamp * \param not_after not_after timestamp * * \return 0 if timestamp was parsed successfully, or * a specific error code */ int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, const char *not_before, const char *not_after); /** * \brief Set the issuer name for a Certificate * Issuer names should contain a comma-separated list * of OID types and values: * e.g. "C=UK,O=ARM,CN=Mbed TLS CA" * * \param ctx CRT context to use * \param issuer_name issuer name to set * * \return 0 if issuer name was parsed successfully, or * a specific error code */ int mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx, const char *issuer_name); /** * \brief Set the subject name for a Certificate * Subject names should contain a comma-separated list * of OID types and values: * e.g. "C=UK,O=ARM,CN=Mbed TLS Server 1" * * \param ctx CRT context to use * \param subject_name subject name to set * * \return 0 if subject name was parsed successfully, or * a specific error code */ int mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx, const char *subject_name); /** * \brief Set the subject public key for the certificate * * \param ctx CRT context to use * \param key public key to include */ void mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key); /** * \brief Set the issuer key used for signing the certificate * * \param ctx CRT context to use * \param key private key to sign with */ void mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key); /** * \brief Set the MD algorithm to use for the signature * (e.g. MBEDTLS_MD_SHA1) * * \param ctx CRT context to use * \param md_alg MD algorithm to use */ void mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg); /** * \brief Generic function to add to or replace an extension in the * CRT * * \param ctx CRT context to use * \param oid OID of the extension * \param oid_len length of the OID * \param critical if the extension is critical (per the RFC's definition) * \param val value of the extension OCTET STRING * \param val_len length of the value data * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len); /** * \brief Set the basicConstraints extension for a CRT * * \param ctx CRT context to use * \param is_ca is this a CA certificate * \param max_pathlen maximum length of certificate chains below this * certificate (only for CA certificates, -1 is * unlimited) * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx, int is_ca, int max_pathlen); #if defined(MBEDTLS_MD_CAN_SHA1) /** * \brief Set the subjectKeyIdentifier extension for a CRT * Requires that mbedtls_x509write_crt_set_subject_key() has been * called before * * \param ctx CRT context to use * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx); /** * \brief Set the authorityKeyIdentifier extension for a CRT * Requires that mbedtls_x509write_crt_set_issuer_key() has been * called before * * \param ctx CRT context to use * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx); #endif /* MBEDTLS_MD_CAN_SHA1 */ /** * \brief Set the Key Usage Extension flags * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) * * \param ctx CRT context to use * \param key_usage key usage flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx, unsigned int key_usage); /** * \brief Set the Extended Key Usage Extension * (e.g. MBEDTLS_OID_SERVER_AUTH) * * \param ctx CRT context to use * \param exts extended key usage extensions to set, a sequence of * MBEDTLS_ASN1_OID objects * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, const mbedtls_asn1_sequence *exts); /** * \brief Set the Netscape Cert Type flags * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) * * \param ctx CRT context to use * \param ns_cert_type Netscape Cert Type flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx, unsigned char ns_cert_type); /** * \brief Free the contents of a CRT write context * * \param ctx CRT context to free */ void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx); /** * \brief Write a built up certificate to a X509 DER structure * Note: data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer * * \param ctx certificate to write away * \param buf buffer to write to * \param size size of the buffer * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return length of data written if successful, or a specific * error code * * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_PEM_WRITE_C) /** * \brief Write a built up certificate to a X509 PEM string * * \param ctx certificate to write away * \param buf buffer to write to * \param size size of the buffer * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return 0 if successful, or a specific error code * * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_crt_pem(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CRT_WRITE_C */ /** \} addtogroup x509_module */ #ifdef __cplusplus } #endif #endif /* mbedtls_x509_crt.h */ webfakes/src/mbedtls/include/mbedtls/pem.h0000644000176200001440000001341414740737024020304 0ustar liggesusers/** * \file pem.h * * \brief Privacy Enhanced Mail (PEM) decoding */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PEM_H #define MBEDTLS_PEM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include /** * \name PEM Error codes * These error codes are returned in case of errors reading the * PEM data. * \{ */ /** No PEM header or footer found. */ #define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /** PEM string is not as expected. */ #define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /** Failed to allocate memory. */ #define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /** RSA IV is not in hex-format. */ #define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /** Unsupported key encryption algorithm. */ #define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /** Private key password can't be empty. */ #define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /** Given private key password does not allow for correct decryption. */ #define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /** Unavailable feature, e.g. hashing/encryption combination. */ #define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /** Bad input parameters to function. */ #define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /** \} name PEM Error codes */ #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_PEM_PARSE_C) /** * \brief PEM context structure */ typedef struct mbedtls_pem_context { unsigned char *MBEDTLS_PRIVATE(buf); /*!< buffer for decoded data */ size_t MBEDTLS_PRIVATE(buflen); /*!< length of the buffer */ unsigned char *MBEDTLS_PRIVATE(info); /*!< buffer for extra header information */ } mbedtls_pem_context; /** * \brief PEM context setup * * \param ctx context to be initialized */ void mbedtls_pem_init(mbedtls_pem_context *ctx); /** * \brief Read a buffer for PEM information and store the resulting * data into the specified context buffers. * * \param ctx context to use * \param header header string to seek and expect * \param footer footer string to seek and expect * \param data source data to look in (must be nul-terminated) * \param pwd password for decryption (can be NULL) * \param pwdlen length of password * \param use_len destination for total length used from data buffer. It is * set after header is correctly read, so unless you get * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is * the length to skip. * * \note Attempts to check password correctness by verifying if * the decrypted text starts with an ASN.1 sequence of * appropriate length * * \note \c mbedtls_pem_free must be called on PEM context before * the PEM context can be reused in another call to * \c mbedtls_pem_read_buffer * * \return 0 on success, or a specific PEM error code */ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len); /** * \brief Get the pointer to the decoded binary data in a PEM context. * * \param ctx PEM context to access. * \param buflen On success, this will contain the length of the binary data. * This must be a valid (non-null) pointer. * * \return A pointer to the decoded binary data. * * \note The returned pointer remains valid only until \p ctx is modified or freed. */ static inline const unsigned char *mbedtls_pem_get_buffer(mbedtls_pem_context *ctx, size_t *buflen) { *buflen = ctx->MBEDTLS_PRIVATE(buflen); return ctx->MBEDTLS_PRIVATE(buf); } /** * \brief PEM context memory freeing * * \param ctx context to be freed */ void mbedtls_pem_free(mbedtls_pem_context *ctx); #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_WRITE_C) /** * \brief Write a buffer of PEM information from a DER encoded * buffer. * * \param header The header string to write. * \param footer The footer string to write. * \param der_data The DER data to encode. * \param der_len The length of the DER data \p der_data in Bytes. * \param buf The buffer to write to. * \param buf_len The length of the output buffer \p buf in Bytes. * \param olen The address at which to store the total length written * or required (if \p buf_len is not enough). * * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len * to request the length of the resulting PEM buffer in * `*olen`. * * \note This function may be called with overlapping \p der_data * and \p buf buffers. * * \return \c 0 on success. * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large * enough to hold the PEM buffer. In this case, `*olen` holds * the required minimum size of \p buf. * \return Another PEM or BASE64 error code on other kinds of failure. */ int mbedtls_pem_write_buffer(const char *header, const char *footer, const unsigned char *der_data, size_t der_len, unsigned char *buf, size_t buf_len, size_t *olen); #endif /* MBEDTLS_PEM_WRITE_C */ #ifdef __cplusplus } #endif #endif /* pem.h */ webfakes/src/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h0000644000176200001440000004344314740737024025273 0ustar liggesusers/** * \file mbedtls/config_adjust_legacy_crypto.h * \brief Adjust legacy configuration configuration * * This is an internal header. Do not include it directly. * * Automatically enable certain dependencies. Generally, MBEDTLS_xxx * configurations need to be explicitly enabled by the user: enabling * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a * compilation error. However, we do automatically enable certain options * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option * used to identify parts of a module that are used by other module, and we * don't want to make the symbol MBEDTLS_xxx_B part of the public API. * Another case is if A didn't depend on B in earlier versions, and we * want to use B in A but we need to preserve backward compatibility with * configurations that explicitly activate MBEDTLS_xxx_A but not * MBEDTLS_xxx_B. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H #define MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ /* Ideally, we'd set those as defaults in mbedtls_config.h, but * putting an #ifdef _WIN32 in mbedtls_config.h would confuse config.py. * * So, adjust it here. * Not related to crypto, but this is the bottom of the stack. */ #if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) #if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) #define MBEDTLS_PLATFORM_SNPRINTF_ALT #endif #if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) #define MBEDTLS_PLATFORM_VSNPRINTF_ALT #endif #endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */ /* Auto-enable CIPHER_C when any of the unauthenticated ciphers is builtin * in PSA. */ #if defined(MBEDTLS_PSA_CRYPTO_C) && \ (defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)) #define MBEDTLS_CIPHER_C #endif /* Auto-enable MBEDTLS_MD_LIGHT based on MBEDTLS_MD_C. * This allows checking for MD_LIGHT rather than MD_LIGHT || MD_C. */ #if defined(MBEDTLS_MD_C) #define MBEDTLS_MD_LIGHT #endif /* Auto-enable MBEDTLS_MD_LIGHT if needed by a module that didn't require it * in a previous release, to ensure backwards compatibility. */ #if defined(MBEDTLS_ECJPAKE_C) || \ defined(MBEDTLS_PEM_PARSE_C) || \ defined(MBEDTLS_ENTROPY_C) || \ defined(MBEDTLS_PK_C) || \ defined(MBEDTLS_PKCS12_C) || \ defined(MBEDTLS_RSA_C) || \ defined(MBEDTLS_SSL_TLS_C) || \ defined(MBEDTLS_X509_USE_C) || \ defined(MBEDTLS_X509_CREATE_C) #define MBEDTLS_MD_LIGHT #endif #if defined(MBEDTLS_MD_LIGHT) /* * - MBEDTLS_MD_CAN_xxx is defined if the md module can perform xxx. * - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module may perform xxx via PSA * (see below). * - MBEDTLS_MD_SOME_PSA is defined if at least one algorithm may be performed * via PSA (see below). * - MBEDTLS_MD_SOME_LEGACY is defined if at least one algorithm may be performed * via a direct legacy call (see below). * * The md module performs an algorithm via PSA if there is a PSA hash * accelerator and the PSA driver subsytem is initialized at the time the * operation is started, and makes a direct legacy call otherwise. */ /* PSA accelerated implementations */ #if defined(MBEDTLS_PSA_CRYPTO_C) #if defined(MBEDTLS_PSA_ACCEL_ALG_MD5) #define MBEDTLS_MD_CAN_MD5 #define MBEDTLS_MD_MD5_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) #define MBEDTLS_MD_CAN_SHA1 #define MBEDTLS_MD_SHA1_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) #define MBEDTLS_MD_CAN_SHA224 #define MBEDTLS_MD_SHA224_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) #define MBEDTLS_MD_CAN_SHA256 #define MBEDTLS_MD_SHA256_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) #define MBEDTLS_MD_CAN_SHA384 #define MBEDTLS_MD_SHA384_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) #define MBEDTLS_MD_CAN_SHA512 #define MBEDTLS_MD_SHA512_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) #define MBEDTLS_MD_CAN_RIPEMD160 #define MBEDTLS_MD_RIPEMD160_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224) #define MBEDTLS_MD_CAN_SHA3_224 #define MBEDTLS_MD_SHA3_224_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256) #define MBEDTLS_MD_CAN_SHA3_256 #define MBEDTLS_MD_SHA3_256_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384) #define MBEDTLS_MD_CAN_SHA3_384 #define MBEDTLS_MD_SHA3_384_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512) #define MBEDTLS_MD_CAN_SHA3_512 #define MBEDTLS_MD_SHA3_512_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #endif /* MBEDTLS_PSA_CRYPTO_C */ /* Built-in implementations */ #if defined(MBEDTLS_MD5_C) #define MBEDTLS_MD_CAN_MD5 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA1_C) #define MBEDTLS_MD_CAN_SHA1 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA224_C) #define MBEDTLS_MD_CAN_SHA224 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA256_C) #define MBEDTLS_MD_CAN_SHA256 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA384_C) #define MBEDTLS_MD_CAN_SHA384 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA512_C) #define MBEDTLS_MD_CAN_SHA512 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA3_C) #define MBEDTLS_MD_CAN_SHA3_224 #define MBEDTLS_MD_CAN_SHA3_256 #define MBEDTLS_MD_CAN_SHA3_384 #define MBEDTLS_MD_CAN_SHA3_512 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_RIPEMD160_C) #define MBEDTLS_MD_CAN_RIPEMD160 #define MBEDTLS_MD_SOME_LEGACY #endif #endif /* MBEDTLS_MD_LIGHT */ /* BLOCK_CIPHER module can dispatch to PSA when: * - PSA is enabled and drivers have been initialized * - desired key type is supported on the PSA side * If the above conditions are not met, but the legacy support is enabled, then * BLOCK_CIPHER will dynamically fallback to it. * * In case BLOCK_CIPHER is defined (see below) the following symbols/helpers * can be used to define its capabilities: * - MBEDTLS_BLOCK_CIPHER_SOME_PSA: there is at least 1 key type between AES, * ARIA and Camellia which is supported through a driver; * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_PSA: xxx key type is supported through a * driver; * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_LEGACY: xxx key type is supported through * a legacy module (i.e. MBEDTLS_xxx_C) */ #if defined(MBEDTLS_PSA_CRYPTO_C) #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES) #define MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA #define MBEDTLS_BLOCK_CIPHER_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA) #define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA #define MBEDTLS_BLOCK_CIPHER_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA) #define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA #define MBEDTLS_BLOCK_CIPHER_SOME_PSA #endif #endif /* MBEDTLS_PSA_CRYPTO_C */ #if defined(MBEDTLS_AES_C) #define MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY #endif #if defined(MBEDTLS_ARIA_C) #define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY #endif #if defined(MBEDTLS_CAMELLIA_C) #define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY #endif /* Helpers to state that BLOCK_CIPHER module supports AES, ARIA and/or Camellia * block ciphers via either PSA or legacy. */ #if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) || \ defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY) #define MBEDTLS_BLOCK_CIPHER_CAN_AES #endif #if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) || \ defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY) #define MBEDTLS_BLOCK_CIPHER_CAN_ARIA #endif #if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) || \ defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY) #define MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA #endif /* GCM_C and CCM_C can either depend on (in order of preference) BLOCK_CIPHER_C * or CIPHER_C. The former is auto-enabled when: * - CIPHER_C is not defined, which is also the legacy solution; * - BLOCK_CIPHER_SOME_PSA because in this case BLOCK_CIPHER can take advantage * of the driver's acceleration. */ #if (defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)) && \ (!defined(MBEDTLS_CIPHER_C) || defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)) #define MBEDTLS_BLOCK_CIPHER_C #endif /* Helpers for GCM/CCM capabilities */ #if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_AES)) #define MBEDTLS_CCM_GCM_CAN_AES #endif #if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_ARIA_C)) || \ (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_ARIA)) #define MBEDTLS_CCM_GCM_CAN_ARIA #endif #if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_CAMELLIA_C)) || \ (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA)) #define MBEDTLS_CCM_GCM_CAN_CAMELLIA #endif /* MBEDTLS_ECP_LIGHT is auto-enabled by the following symbols: * - MBEDTLS_ECP_C because now it consists of MBEDTLS_ECP_LIGHT plus functions * for curve arithmetic. As a consequence if MBEDTLS_ECP_C is required for * some reason, then MBEDTLS_ECP_LIGHT should be enabled as well. * - MBEDTLS_PK_PARSE_EC_EXTENDED and MBEDTLS_PK_PARSE_EC_COMPRESSED because * these features are not supported in PSA so the only way to have them is * to enable the built-in solution. * Both of them are temporary dependencies: * - PK_PARSE_EC_EXTENDED will be removed after #7779 and #7789 * - support for compressed points should also be added to PSA, but in this * case there is no associated issue to track it yet. * - PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE because Weierstrass key derivation * still depends on ECP_LIGHT. * - PK_C + USE_PSA + PSA_WANT_ALG_ECDSA is a temporary dependency which will * be fixed by #7453. */ #if defined(MBEDTLS_ECP_C) || \ defined(MBEDTLS_PK_PARSE_EC_EXTENDED) || \ defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define MBEDTLS_ECP_LIGHT #endif /* Backward compatibility: after #8740 the RSA module offers functions to parse * and write RSA private/public keys without relying on the PK one. Of course * this needs ASN1 support to do so, so we enable it here. */ #if defined(MBEDTLS_RSA_C) #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED is introduced in Mbed TLS version 3.5, while * in previous version compressed points were automatically supported as long * as PK_PARSE_C and ECP_C were enabled. As a consequence, for backward * compatibility, we auto-enable PK_PARSE_EC_COMPRESSED when these conditions * are met. */ #if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_ECP_C) #define MBEDTLS_PK_PARSE_EC_COMPRESSED #endif /* Helper symbol to state that there is support for ECDH, either through * library implementation (ECDH_C) or through PSA. */ #if (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_ECDH)) || \ (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C)) #define MBEDTLS_CAN_ECDH #endif /* PK module can achieve ECDSA functionalities by means of either software * implementations (ECDSA_C) or through a PSA driver. The following defines * are meant to list these capabilities in a general way which abstracts how * they are implemented under the hood. */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_ECDSA_C) #define MBEDTLS_PK_CAN_ECDSA_SIGN #define MBEDTLS_PK_CAN_ECDSA_VERIFY #endif /* MBEDTLS_ECDSA_C */ #else /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(PSA_WANT_ALG_ECDSA) #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define MBEDTLS_PK_CAN_ECDSA_SIGN #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */ #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #define MBEDTLS_PK_CAN_ECDSA_VERIFY #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ #endif /* PSA_WANT_ALG_ECDSA */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN) #define MBEDTLS_PK_CAN_ECDSA_SOME #endif /* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT * is defined as well to include all PSA code. */ #if defined(MBEDTLS_PSA_CRYPTO_C) #define MBEDTLS_PSA_CRYPTO_CLIENT #endif /* MBEDTLS_PSA_CRYPTO_C */ /* Helpers to state that each key is supported either on the builtin or PSA side. */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_521) #define MBEDTLS_ECP_HAVE_SECP521R1 #endif #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) #define MBEDTLS_ECP_HAVE_BP512R1 #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_448) #define MBEDTLS_ECP_HAVE_CURVE448 #endif #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) #define MBEDTLS_ECP_HAVE_BP384R1 #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_384) #define MBEDTLS_ECP_HAVE_SECP384R1 #endif #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) #define MBEDTLS_ECP_HAVE_BP256R1 #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_256) #define MBEDTLS_ECP_HAVE_SECP256K1 #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_256) #define MBEDTLS_ECP_HAVE_SECP256R1 #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_255) #define MBEDTLS_ECP_HAVE_CURVE25519 #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_224) #define MBEDTLS_ECP_HAVE_SECP224K1 #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_224) #define MBEDTLS_ECP_HAVE_SECP224R1 #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_192) #define MBEDTLS_ECP_HAVE_SECP192K1 #endif #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_192) #define MBEDTLS_ECP_HAVE_SECP192R1 #endif /* Helper symbol to state that the PK module has support for EC keys. This * can either be provided through the legacy ECP solution or through the * PSA friendly MBEDTLS_PK_USE_PSA_EC_DATA (see pk.h for its description). */ #if defined(MBEDTLS_ECP_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)) #define MBEDTLS_PK_HAVE_ECC_KEYS #endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */ /* Historically pkparse did not check the CBC padding when decrypting * a key. This was a bug, which is now fixed. As a consequence, pkparse * now needs PKCS7 padding support, but existing configurations might not * enable it, so we enable it here. */ #if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) #define MBEDTLS_CIPHER_PADDING_PKCS7 #endif /* Backwards compatibility for some macros which were renamed to reflect that * they are related to Armv8, not aarch64. */ #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) && \ !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) #define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT #endif #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) && !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY #endif /* psa_util file features some ECDSA conversion functions, to convert between * legacy's ASN.1 DER format and PSA's raw one. */ #if (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \ (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA))) #define MBEDTLS_PSA_UTIL_HAVE_ECDSA #endif /* Some internal helpers to determine which keys are available. */ #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_AES)) #define MBEDTLS_SSL_HAVE_AES #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ARIA_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ARIA)) #define MBEDTLS_SSL_HAVE_ARIA #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CAMELLIA_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_CAMELLIA)) #define MBEDTLS_SSL_HAVE_CAMELLIA #endif /* Some internal helpers to determine which operation modes are available. */ #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CIPHER_MODE_CBC)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CBC_NO_PADDING)) #define MBEDTLS_SSL_HAVE_CBC #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_GCM_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM)) #define MBEDTLS_SSL_HAVE_GCM #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CCM_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM)) #define MBEDTLS_SSL_HAVE_CCM #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CHACHAPOLY_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305)) #define MBEDTLS_SSL_HAVE_CHACHAPOLY #endif #if defined(MBEDTLS_SSL_HAVE_GCM) || defined(MBEDTLS_SSL_HAVE_CCM) || \ defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) #define MBEDTLS_SSL_HAVE_AEAD #endif #endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H */ webfakes/src/mbedtls/include/mbedtls/memory_buffer_alloc.h0000644000176200001440000001116214740737024023534 0ustar liggesusers/** * \file memory_buffer_alloc.h * * \brief Buffer-based memory allocator */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H #define MBEDTLS_MEMORY_BUFFER_ALLOC_H #include "mbedtls/build_info.h" #include /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) #define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ #endif /** \} name SECTION: Module settings */ #define MBEDTLS_MEMORY_VERIFY_NONE 0 #define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) #define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) #define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | \ MBEDTLS_MEMORY_VERIFY_FREE) #ifdef __cplusplus extern "C" { #endif /** * \brief Initialize use of stack-based memory allocator. * The stack-based allocator does memory management inside the * presented buffer and does not call calloc() and free(). * It sets the global mbedtls_calloc() and mbedtls_free() pointers * to its own functions. * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if * MBEDTLS_THREADING_C is defined) * * \note This code is not optimized and provides a straight-forward * implementation of a stack-based memory allocator. * * \param buf buffer to use as heap * \param len size of the buffer */ void mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len); /** * \brief Free the mutex for thread-safety and clear remaining memory */ void mbedtls_memory_buffer_alloc_free(void); /** * \brief Determine when the allocator should automatically verify the state * of the entire chain of headers / meta-data. * (Default: MBEDTLS_MEMORY_VERIFY_NONE) * * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS */ void mbedtls_memory_buffer_set_verify(int verify); #if defined(MBEDTLS_MEMORY_DEBUG) /** * \brief Print out the status of the allocated memory (primarily for use * after a program should have de-allocated all memory) * Prints out a list of 'still allocated' blocks and their stack * trace if MBEDTLS_MEMORY_BACKTRACE is defined. */ void mbedtls_memory_buffer_alloc_status(void); /** * \brief Get the number of alloc/free so far. * * \param alloc_count Number of allocations. * \param free_count Number of frees. */ void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count); /** * \brief Get the peak heap usage so far * * \param max_used Peak number of bytes in use or committed. This * includes bytes in allocated blocks too small to split * into smaller blocks but larger than the requested size. * \param max_blocks Peak number of blocks in use, including free and used */ void mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks); /** * \brief Reset peak statistics */ void mbedtls_memory_buffer_alloc_max_reset(void); /** * \brief Get the current heap usage * * \param cur_used Current number of bytes in use or committed. This * includes bytes in allocated blocks too small to split * into smaller blocks but larger than the requested size. * \param cur_blocks Current number of blocks in use, including free and used */ void mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks); #endif /* MBEDTLS_MEMORY_DEBUG */ /** * \brief Verifies that all headers in the memory buffer are correct * and contain sane values. Helps debug buffer-overflow errors. * * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. * Prints out full header information if MBEDTLS_MEMORY_DEBUG * is defined. (Includes stack trace information for each block if * MBEDTLS_MEMORY_BACKTRACE is defined as well). * * \return 0 if verified, 1 otherwise */ int mbedtls_memory_buffer_alloc_verify(void); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if a test failed */ int mbedtls_memory_buffer_alloc_self_test(int verbose); #endif #ifdef __cplusplus } #endif #endif /* memory_buffer_alloc.h */ webfakes/src/mbedtls/include/mbedtls/ecjpake.h0000644000176200001440000003103514740737024021124 0ustar liggesusers/** * \file ecjpake.h * * \brief Elliptic curve J-PAKE */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECJPAKE_H #define MBEDTLS_ECJPAKE_H #include "mbedtls/private_access.h" /* * J-PAKE is a password-authenticated key exchange that allows deriving a * strong shared secret from a (potentially low entropy) pre-shared * passphrase, with forward secrecy and mutual authentication. * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling * * This file implements the Elliptic Curve variant of J-PAKE, * as defined in Chapter 7.4 of the Thread v1.0 Specification, * available to members of the Thread Group http://threadgroup.org/ * * As the J-PAKE algorithm is inherently symmetric, so is our API. * Each party needs to send its first round message, in any order, to the * other party, then each sends its second round message, in any order. * The payloads are serialized in a way suitable for use in TLS, but could * also be use outside TLS. */ #include "mbedtls/build_info.h" #include "mbedtls/ecp.h" #include "mbedtls/md.h" #ifdef __cplusplus extern "C" { #endif /** * Roles in the EC J-PAKE exchange */ typedef enum { MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ MBEDTLS_ECJPAKE_SERVER, /**< Server */ MBEDTLS_ECJPAKE_NONE, /**< Undefined */ } mbedtls_ecjpake_role; #if !defined(MBEDTLS_ECJPAKE_ALT) /** * EC J-PAKE context structure. * * J-PAKE is a symmetric protocol, except for the identifiers used in * Zero-Knowledge Proofs, and the serialization of the second message * (KeyExchange) as defined by the Thread spec. * * In order to benefit from this symmetry, we choose a different naming * convention from the Thread v1.0 spec. Correspondence is indicated in the * description as a pair C: client name, S: server name */ typedef struct mbedtls_ecjpake_context { mbedtls_md_type_t MBEDTLS_PRIVATE(md_type); /**< Hash to use */ mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /**< Elliptic curve */ mbedtls_ecjpake_role MBEDTLS_PRIVATE(role); /**< Are we client or server? */ int MBEDTLS_PRIVATE(point_format); /**< Format for point export */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xm1); /**< My public key 1 C: X1, S: X3 */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xm2); /**< My public key 2 C: X2, S: X4 */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xp1); /**< Peer public key 1 C: X3, S: X1 */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xp2); /**< Peer public key 2 C: X4, S: X2 */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xp); /**< Peer public key C: Xs, S: Xc */ mbedtls_mpi MBEDTLS_PRIVATE(xm1); /**< My private key 1 C: x1, S: x3 */ mbedtls_mpi MBEDTLS_PRIVATE(xm2); /**< My private key 2 C: x2, S: x4 */ mbedtls_mpi MBEDTLS_PRIVATE(s); /**< Pre-shared secret (passphrase) */ } mbedtls_ecjpake_context; #else /* MBEDTLS_ECJPAKE_ALT */ #include "ecjpake_alt.h" #endif /* MBEDTLS_ECJPAKE_ALT */ /** * \brief Initialize an ECJPAKE context. * * \param ctx The ECJPAKE context to initialize. * This must not be \c NULL. */ void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx); /** * \brief Set up an ECJPAKE context for use. * * \note Currently the only values for hash/curve allowed by the * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1. * * \param ctx The ECJPAKE context to set up. This must be initialized. * \param role The role of the caller. This must be either * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER. * \param hash The identifier of the hash function to use, * for example #MBEDTLS_MD_SHA256. * \param curve The identifier of the elliptic curve to use, * for example #MBEDTLS_ECP_DP_SECP256R1. * \param secret The pre-shared secret (passphrase). This must be * a readable not empty buffer of length \p len Bytes. It need * only be valid for the duration of this call. * \param len The length of the pre-shared secret \p secret. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx, mbedtls_ecjpake_role role, mbedtls_md_type_t hash, mbedtls_ecp_group_id curve, const unsigned char *secret, size_t len); /** * \brief Set the point format for future reads and writes. * * \param ctx The ECJPAKE context to configure. * \param point_format The point format to use: * #MBEDTLS_ECP_PF_UNCOMPRESSED (default) * or #MBEDTLS_ECP_PF_COMPRESSED. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p point_format * is invalid. */ int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx, int point_format); /** * \brief Check if an ECJPAKE context is ready for use. * * \param ctx The ECJPAKE context to check. This must be * initialized. * * \return \c 0 if the context is ready for use. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise. */ int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx); /** * \brief Generate and write the first round message * (TLS: contents of the Client/ServerHello extension, * excluding extension type and length bytes). * * \param ctx The ECJPAKE context to use. This must be * initialized and set up. * \param buf The buffer to write the contents to. This must be a * writable buffer of length \p len Bytes. * \param len The length of \p buf in Bytes. * \param olen The address at which to store the total number * of Bytes written to \p buf. This must not be \c NULL. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This * may be \c NULL if \p f_rng doesn't use a context. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Read and process the first round message * (TLS: contents of the Client/ServerHello extension, * excluding extension type and length bytes). * * \param ctx The ECJPAKE context to use. This must be initialized * and set up. * \param buf The buffer holding the first round message. This must * be a readable buffer of length \p len Bytes. * \param len The length in Bytes of \p buf. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len); /** * \brief Generate and write the second round message * (TLS: contents of the Client/ServerKeyExchange). * * \param ctx The ECJPAKE context to use. This must be initialized, * set up, and already have performed round one. * \param buf The buffer to write the round two contents to. * This must be a writable buffer of length \p len Bytes. * \param len The size of \p buf in Bytes. * \param olen The address at which to store the total number of Bytes * written to \p buf. This must not be \c NULL. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This * may be \c NULL if \p f_rng doesn't use a context. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Read and process the second round message * (TLS: contents of the Client/ServerKeyExchange). * * \param ctx The ECJPAKE context to use. This must be initialized * and set up and already have performed round one. * \param buf The buffer holding the second round message. This must * be a readable buffer of length \p len Bytes. * \param len The length in Bytes of \p buf. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len); /** * \brief Derive the shared secret * (TLS: Pre-Master Secret). * * \param ctx The ECJPAKE context to use. This must be initialized, * set up and have performed both round one and two. * \param buf The buffer to write the derived secret to. This must * be a writable buffer of length \p len Bytes. * \param len The length of \p buf in Bytes. * \param olen The address at which to store the total number of Bytes * written to \p buf. This must not be \c NULL. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This * may be \c NULL if \p f_rng doesn't use a context. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Write the shared key material to be passed to a Key * Derivation Function as described in RFC8236. * * \param ctx The ECJPAKE context to use. This must be initialized, * set up and have performed both round one and two. * \param buf The buffer to write the derived secret to. This must * be a writable buffer of length \p len Bytes. * \param len The length of \p buf in Bytes. * \param olen The address at which to store the total number of bytes * written to \p buf. This must not be \c NULL. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This * may be \c NULL if \p f_rng doesn't use a context. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This clears an ECJPAKE context and frees any * embedded data structure. * * \param ctx The ECJPAKE context to free. This may be \c NULL, * in which case this function does nothing. If it is not * \c NULL, it must point to an initialized ECJPAKE context. */ void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if a test failed */ int mbedtls_ecjpake_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* ecjpake.h */ webfakes/src/mbedtls/include/mbedtls/block_cipher.h0000644000176200001440000000353114740737024022146 0ustar liggesusers/** * \file block_cipher.h * * \brief Internal abstraction layer. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BLOCK_CIPHER_H #define MBEDTLS_BLOCK_CIPHER_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #endif #if defined(MBEDTLS_ARIA_C) #include "mbedtls/aria.h" #endif #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #endif #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) #include "psa/crypto_types.h" #endif #ifdef __cplusplus extern "C" { #endif typedef enum { MBEDTLS_BLOCK_CIPHER_ID_NONE = 0, /**< Unset. */ MBEDTLS_BLOCK_CIPHER_ID_AES, /**< The AES cipher. */ MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ MBEDTLS_BLOCK_CIPHER_ID_ARIA, /**< The Aria cipher. */ } mbedtls_block_cipher_id_t; /** * Used internally to indicate whether a context uses legacy or PSA. * * Internal use only. */ typedef enum { MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY = 0, MBEDTLS_BLOCK_CIPHER_ENGINE_PSA, } mbedtls_block_cipher_engine_t; typedef struct { mbedtls_block_cipher_id_t MBEDTLS_PRIVATE(id); #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) mbedtls_block_cipher_engine_t MBEDTLS_PRIVATE(engine); mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psa_key_id); #endif union { unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ #if defined(MBEDTLS_AES_C) mbedtls_aes_context MBEDTLS_PRIVATE(aes); #endif #if defined(MBEDTLS_ARIA_C) mbedtls_aria_context MBEDTLS_PRIVATE(aria); #endif #if defined(MBEDTLS_CAMELLIA_C) mbedtls_camellia_context MBEDTLS_PRIVATE(camellia); #endif } MBEDTLS_PRIVATE(ctx); } mbedtls_block_cipher_context_t; #ifdef __cplusplus } #endif #endif /* MBEDTLS_BLOCK_CIPHER_H */ webfakes/src/mbedtls/include/mbedtls/constant_time.h0000644000176200001440000000231114740737024022364 0ustar liggesusers/** * Constant-time functions */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONSTANT_TIME_H #define MBEDTLS_CONSTANT_TIME_H #include /** Constant-time buffer comparison without branches. * * This is equivalent to the standard memcmp function, but is likely to be * compiled to code using bitwise operations rather than a branch, such that * the time taken is constant w.r.t. the data pointed to by \p a and \p b, * and w.r.t. whether \p a and \p b are equal or not. It is not constant-time * w.r.t. \p n . * * This function can be used to write constant-time code by replacing branches * with bit operations using masks. * * \param a Pointer to the first buffer, containing at least \p n bytes. May not be NULL. * \param b Pointer to the second buffer, containing at least \p n bytes. May not be NULL. * \param n The number of bytes to compare. * * \return Zero if the contents of the two buffers are the same, * otherwise non-zero. */ int mbedtls_ct_memcmp(const void *a, const void *b, size_t n); #endif /* MBEDTLS_CONSTANT_TIME_H */ webfakes/src/mbedtls/include/mbedtls/version.h0000644000176200001440000000433614740737024021213 0ustar liggesusers/** * \file version.h * * \brief Run-time version information */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * This set of run-time variables can be used to determine the version number of * the Mbed TLS library used. Compile-time version defines for the same can be * found in build_info.h */ #ifndef MBEDTLS_VERSION_H #define MBEDTLS_VERSION_H #include "mbedtls/build_info.h" #if defined(MBEDTLS_VERSION_C) #ifdef __cplusplus extern "C" { #endif /** * Get the version number. * * \return The constructed version number in the format * MMNNPP00 (Major, Minor, Patch). */ unsigned int mbedtls_version_get_number(void); /** * Get the version string ("x.y.z"). * * \param string The string that will receive the value. * (Should be at least 9 bytes in size) */ void mbedtls_version_get_string(char *string); /** * Get the full version string ("Mbed TLS x.y.z"). * * \param string The string that will receive the value. The Mbed TLS version * string will use 18 bytes AT MOST including a terminating * null byte. * (So the buffer should be at least 18 bytes to receive this * version string). */ void mbedtls_version_get_string_full(char *string); /** * \brief Check if support for a feature was compiled into this * Mbed TLS binary. This allows you to see at runtime if the * library was for instance compiled with or without * Multi-threading support. * * \note only checks against defines in the sections "System * support", "Mbed TLS modules" and "Mbed TLS feature * support" in mbedtls_config.h * * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") * * \return 0 if the feature is present, * -1 if the feature is not present and * -2 if support for feature checking as a whole was not * compiled in. */ int mbedtls_version_check_feature(const char *feature); #ifdef __cplusplus } #endif #endif /* MBEDTLS_VERSION_C */ #endif /* version.h */ webfakes/src/mbedtls/include/mbedtls/aes.h0000644000176200001440000006657114740737024020307 0ustar liggesusers/** * \file aes.h * * \brief This file contains AES definitions and functions. * * The Advanced Encryption Standard (AES) specifies a FIPS-approved * cryptographic algorithm that can be used to protect electronic * data. * * The AES algorithm is a symmetric block cipher that can * encrypt and decrypt information. For more information, see * FIPS Publication 197: Advanced Encryption Standard and * ISO/IEC 18033-2:2006: Information technology -- Security * techniques -- Encryption algorithms -- Part 2: Asymmetric * ciphers. * * The AES-XTS block mode is standardized by NIST SP 800-38E * * and described in detail by IEEE P1619 * . */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_AES_H #define MBEDTLS_AES_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include #include /* padlock.c and aesni.c rely on these values! */ #define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ #define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ /* Error codes in range 0x0020-0x0022 */ /** Invalid key length. */ #define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /** Invalid data input length. */ #define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /* Error codes in range 0x0021-0x0025 */ /** Invalid input data. */ #define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_AES_ALT) // Regular implementation // /** * \brief The AES context-type definition. */ typedef struct mbedtls_aes_context { int MBEDTLS_PRIVATE(nr); /*!< The number of rounds. */ size_t MBEDTLS_PRIVATE(rk_offset); /*!< The offset in array elements to AES round keys in the buffer. */ #if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && !defined(MBEDTLS_PADLOCK_C) uint32_t MBEDTLS_PRIVATE(buf)[44]; /*!< Aligned data buffer to hold 10 round keys for 128-bit case. */ #else uint32_t MBEDTLS_PRIVATE(buf)[68]; /*!< Unaligned data buffer. This buffer can hold 32 extra Bytes, which can be used for one of the following purposes:
  • Alignment if VIA padlock is used.
  • Simplifying key expansion in the 256-bit case by generating an extra round key.
*/ #endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH && !MBEDTLS_PADLOCK_C */ } mbedtls_aes_context; #if defined(MBEDTLS_CIPHER_MODE_XTS) /** * \brief The AES XTS context-type definition. */ typedef struct mbedtls_aes_xts_context { mbedtls_aes_context MBEDTLS_PRIVATE(crypt); /*!< The AES context to use for AES block encryption or decryption. */ mbedtls_aes_context MBEDTLS_PRIVATE(tweak); /*!< The AES context used for tweak computation. */ } mbedtls_aes_xts_context; #endif /* MBEDTLS_CIPHER_MODE_XTS */ #else /* MBEDTLS_AES_ALT */ #include "aes_alt.h" #endif /* MBEDTLS_AES_ALT */ /** * \brief This function initializes the specified AES context. * * It must be the first API called before using * the context. * * \param ctx The AES context to initialize. This must not be \c NULL. */ void mbedtls_aes_init(mbedtls_aes_context *ctx); /** * \brief This function releases and clears the specified AES context. * * \param ctx The AES context to clear. * If this is \c NULL, this function does nothing. * Otherwise, the context must have been at least initialized. */ void mbedtls_aes_free(mbedtls_aes_context *ctx); #if defined(MBEDTLS_CIPHER_MODE_XTS) /** * \brief This function initializes the specified AES XTS context. * * It must be the first API called before using * the context. * * \param ctx The AES XTS context to initialize. This must not be \c NULL. */ void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx); /** * \brief This function releases and clears the specified AES XTS context. * * \param ctx The AES XTS context to clear. * If this is \c NULL, this function does nothing. * Otherwise, the context must have been at least initialized. */ void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx); #endif /* MBEDTLS_CIPHER_MODE_XTS */ /** * \brief This function sets the encryption key. * * \param ctx The AES context to which the key should be bound. * It must be initialized. * \param key The encryption key. * This must be a readable buffer of size \p keybits bits. * \param keybits The size of data passed in bits. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief This function sets the decryption key. * * \param ctx The AES context to which the key should be bound. * It must be initialized. * \param key The decryption key. * This must be a readable buffer of size \p keybits bits. * \param keybits The size of data passed. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_CIPHER_MODE_XTS) /** * \brief This function prepares an XTS context for encryption and * sets the encryption key. * * \param ctx The AES XTS context to which the key should be bound. * It must be initialized. * \param key The encryption key. This is comprised of the XTS key1 * concatenated with the XTS key2. * This must be a readable buffer of size \p keybits bits. * \param keybits The size of \p key passed in bits. Valid options are: *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • *
  • 512 bits (each of key1 and key2 is a 256-bit key)
* * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits); /** * \brief This function prepares an XTS context for decryption and * sets the decryption key. * * \param ctx The AES XTS context to which the key should be bound. * It must be initialized. * \param key The decryption key. This is comprised of the XTS key1 * concatenated with the XTS key2. * This must be a readable buffer of size \p keybits bits. * \param keybits The size of \p key passed in bits. Valid options are: *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • *
  • 512 bits (each of key1 and key2 is a 256-bit key)
* * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits); #endif /* MBEDTLS_CIPHER_MODE_XTS */ /** * \brief This function performs an AES single-block encryption or * decryption operation. * * It performs the operation defined in the \p mode parameter * (encrypt or decrypt), on the input data buffer defined in * the \p input parameter. * * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or * mbedtls_aes_setkey_dec() must be called before the first * call to this API with the same context. * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. * \param input The buffer holding the input data. * It must be readable and at least \c 16 Bytes long. * \param output The buffer where the output data will be written. * It must be writeable and at least \c 16 Bytes long. * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief This function performs an AES-CBC encryption or decryption operation * on full blocks. * * It performs the operation defined in the \p mode * parameter (encrypt/decrypt), on the input data buffer defined in * the \p input parameter. * * It can be called as many times as needed, until all the input * data is processed. mbedtls_aes_init(), and either * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called * before the first call to this API with the same context. * * \note This function operates on full blocks, that is, the input size * must be a multiple of the AES block size of \c 16 Bytes. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the IV, you should * either save it manually or use the cipher module instead. * * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. * \param length The length of the input data in Bytes. This must be a * multiple of the block size (\c 16 Bytes). * \param iv Initialization vector (updated after use). * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH * on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_XTS) /** * \brief This function performs an AES-XTS encryption or decryption * operation for an entire XTS data unit. * * AES-XTS encrypts or decrypts blocks based on their location as * defined by a data unit number. The data unit number must be * provided by \p data_unit. * * NIST SP 800-38E limits the maximum size of a data unit to 2^20 * AES blocks. If the data unit is larger than this, this function * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. * * \param ctx The AES XTS context to use for AES XTS operations. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. * \param length The length of a data unit in Bytes. This can be any * length between 16 bytes and 2^24 bytes inclusive * (between 1 and 2^20 block cipher blocks). * \param data_unit The address of the data unit encoded as an array of 16 * bytes in little-endian format. For disk encryption, this * is typically the index of the block device sector that * contains the data. * \param input The buffer holding the input data (which is an entire * data unit). This function reads \p length Bytes from \p * input. * \param output The buffer holding the output data (which is an entire * data unit). This function writes \p length Bytes to \p * output. * * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is * smaller than an AES block in size (16 Bytes) or if \p * length is larger than 2^20 blocks (16 MiB). */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /** * \brief This function performs an AES-CFB128 encryption or decryption * operation. * * It performs the operation defined in the \p mode * parameter (encrypt or decrypt), on the input data buffer * defined in the \p input parameter. * * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), * regardless of whether you are performing an encryption or decryption * operation, that is, regardless of the \p mode parameter. This is * because CFB mode uses the same key schedule for encryption and * decryption. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the * IV, you must either save it manually or use the cipher * module instead. * * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. * \param length The length of the input data in Bytes. * \param iv_off The offset in IV (updated after use). * It must point to a valid \c size_t. * \param iv The initialization vector (updated after use). * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output); /** * \brief This function performs an AES-CFB8 encryption or decryption * operation. * * It performs the operation defined in the \p mode * parameter (encrypt/decrypt), on the input data buffer defined * in the \p input parameter. * * Due to the nature of CFB, you must use the same key schedule for * both encryption and decryption operations. Therefore, you must * use the context initialized with mbedtls_aes_setkey_enc() for * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT * \param length The length of the input data. * \param iv The initialization vector (updated after use). * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /*MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) /** * \brief This function performs an AES-OFB (Output Feedback Mode) * encryption or decryption operation. * * For OFB, you must set up the context with * mbedtls_aes_setkey_enc(), regardless of whether you are * performing an encryption or decryption operation. This is * because OFB mode uses the same key schedule for encryption and * decryption. * * The OFB operation is identical for encryption or decryption, * therefore no operation mode needs to be specified. * * \note Upon exit, the content of iv, the Initialisation Vector, is * updated so that you can call the same function again on the next * block(s) of data and get the same result as if it was encrypted * in one call. This allows a "streaming" usage, by initialising * iv_off to 0 before the first call, and preserving its value * between calls. * * For non-streaming use, the iv should be initialised on each call * to a unique value, and iv_off set to 0 on each call. * * If you need to retain the contents of the initialisation vector, * you must either save it manually or use the cipher module * instead. * * \warning For the OFB mode, the initialisation vector must be unique * every encryption operation. Reuse of an initialisation vector * will compromise security. * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param length The length of the input data. * \param iv_off The offset in IV (updated after use). * It must point to a valid \c size_t. * \param iv The initialization vector (updated after use). * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /** * \brief This function performs an AES-CTR encryption or decryption * operation. * * Due to the nature of CTR, you must use the same key schedule * for both encryption and decryption operations. Therefore, you * must use the context initialized with mbedtls_aes_setkey_enc() * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. * * \warning You must never reuse a nonce value with the same key. Doing so * would void the encryption for the two messages encrypted with * the same nonce and key. * * There are two common strategies for managing nonces with CTR: * * 1. You can handle everything as a single message processed over * successive calls to this function. In that case, you want to * set \p nonce_counter and \p nc_off to 0 for the first call, and * then preserve the values of \p nonce_counter, \p nc_off and \p * stream_block across calls to this function as they will be * updated by this function. * * With this strategy, you must not encrypt more than 2**128 * blocks of data with the same key. * * 2. You can encrypt separate messages by dividing the \p * nonce_counter buffer in two areas: the first one used for a * per-message nonce, handled by yourself, and the second one * updated by this function internally. * * For example, you might reserve the first 12 bytes for the * per-message nonce, and the last 4 bytes for internal use. In that * case, before calling this function on a new message you need to * set the first 12 bytes of \p nonce_counter to your chosen nonce * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p * stream_block to be ignored). That way, you can encrypt at most * 2**96 messages of up to 2**32 blocks each with the same key. * * The per-message nonce (or information sufficient to reconstruct * it) needs to be communicated with the ciphertext and must be unique. * The recommended way to ensure uniqueness is to use a message * counter. An alternative is to generate random nonces, but this * limits the number of messages that can be securely encrypted: * for example, with 96-bit random nonces, you should not encrypt * more than 2**32 messages with the same key. * * Note that for both strategies, sizes are measured in blocks and * that an AES block is 16 bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its * content must not be written to insecure storage and should be * securely discarded as soon as it's no longer needed. * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param length The length of the input data. * \param nc_off The offset in the current \p stream_block, for * resuming within the current cipher stream. The * offset pointer should be 0 at the start of a stream. * It must point to a valid \c size_t. * \param nonce_counter The 128-bit nonce and counter. * It must be a readable-writeable buffer of \c 16 Bytes. * \param stream_block The saved stream block for resuming. This is * overwritten by the function. * It must be a readable-writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CTR */ /** * \brief Internal AES block encryption function. This is only * exposed to allow overriding it using * \c MBEDTLS_AES_ENCRYPT_ALT. * * \param ctx The AES context to use for encryption. * \param input The plaintext block. * \param output The output (ciphertext) block. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Internal AES block decryption function. This is only * exposed to allow overriding it using see * \c MBEDTLS_AES_DECRYPT_ALT. * * \param ctx The AES context to use for decryption. * \param input The ciphertext block. * \param output The output (plaintext) block. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_aes_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* aes.h */ webfakes/src/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h0000644000176200001440000010471514740737024025561 0ustar liggesusers/** * \file mbedtls/config_adjust_legacy_from_psa.h * \brief Adjust PSA configuration: activate legacy implementations * * This is an internal header. Do not include it directly. * * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, activate legacy implementations * of cryptographic mechanisms as needed to fulfill the needs of the PSA * configuration. Generally speaking, we activate a legacy mechanism if * it's needed for a requested PSA mechanism and there is no PSA driver * for it. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H #define MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ /* Define appropriate ACCEL macros for the p256-m driver. * In the future, those should be generated from the drivers JSON description. */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) #define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256 #define MBEDTLS_PSA_ACCEL_ALG_ECDSA #define MBEDTLS_PSA_ACCEL_ALG_ECDH #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE #endif /* * ECC: support for a feature is controlled by a triplet or a pair: * (curve, key_type public/basic, alg) or (curve, key_type_). * * A triplet/pair is accelerated if all of is components are accelerated; * otherwise each component needs to be built in. * * We proceed in two passes: * 1. Check if acceleration is complete for curves, key types, algs. * 2. Then enable built-ins for each thing that's either not accelerated of * doesn't have complete acceleration of the other triplet/pair components. * * Note: this needs psa/crypto_adjust_keypair_types.h to have been included * already, so that we know the full set of key types that are requested. */ /* ECC: curves: is acceleration complete? */ #if (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) && \ !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256)) || \ (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) && \ !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384)) || \ (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) && \ !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512)) || \ (defined(PSA_WANT_ECC_SECP_R1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192)) || \ (defined(PSA_WANT_ECC_SECP_R1_224) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224)) || \ (defined(PSA_WANT_ECC_SECP_R1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256)) || \ (defined(PSA_WANT_ECC_SECP_R1_384) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384)) || \ (defined(PSA_WANT_ECC_SECP_R1_521) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521)) || \ (defined(PSA_WANT_ECC_SECP_K1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192)) || \ (defined(PSA_WANT_ECC_SECP_K1_224) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224)) || \ (defined(PSA_WANT_ECC_SECP_K1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES #endif #if (defined(PSA_WANT_ECC_MONTGOMERY_255) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255)) || \ (defined(PSA_WANT_ECC_MONTGOMERY_448) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES #endif /* ECC: algs: is acceleration complete? */ #if (defined(PSA_WANT_ALG_ECDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)) || \ (defined(PSA_WANT_ALG_ECDSA) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)) || \ (defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)) || \ (defined(PSA_WANT_ALG_JPAKE) && !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS #endif /* ECC: key types: is acceleration complete? */ #if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC #endif /* Special case: we don't support cooked key derivation in drivers yet */ #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #undef MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE #endif /* Note: the condition about key derivation is always true as DERIVE can't be * accelerated yet */ #if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES #endif /* ECC: curves: enable built-ins as needed. * * We need the curve built-in: * - if it's not accelerated, or * - if there's a key type with missing acceleration, or * - if there's a alg with missing acceleration. */ #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) #if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 #define MBEDTLS_ECP_DP_BP256R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */ #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) #if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 #define MBEDTLS_ECP_DP_BP384R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */ #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) #if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 #define MBEDTLS_ECP_DP_BP512R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */ #if defined(PSA_WANT_ECC_MONTGOMERY_255) #if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 #define MBEDTLS_ECP_DP_CURVE25519_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_MONTGOMERY_255 */ #if defined(PSA_WANT_ECC_MONTGOMERY_448) #if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 #define MBEDTLS_ECP_DP_CURVE448_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_MONTGOMERY_448 */ #if defined(PSA_WANT_ECC_SECP_R1_192) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 #define MBEDTLS_ECP_DP_SECP192R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_192 */ #if defined(PSA_WANT_ECC_SECP_R1_224) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 #define MBEDTLS_ECP_DP_SECP224R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_224 */ #if defined(PSA_WANT_ECC_SECP_R1_256) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_256 */ #if defined(PSA_WANT_ECC_SECP_R1_384) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 #define MBEDTLS_ECP_DP_SECP384R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_384 */ #if defined(PSA_WANT_ECC_SECP_R1_521) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 #define MBEDTLS_ECP_DP_SECP521R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_521 */ #if defined(PSA_WANT_ECC_SECP_K1_192) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 #define MBEDTLS_ECP_DP_SECP192K1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_K1_192 */ #if defined(PSA_WANT_ECC_SECP_K1_224) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 #define MBEDTLS_ECP_DP_SECP224K1_ENABLED /* https://github.com/Mbed-TLS/mbedtls/issues/3541 */ #error "SECP224K1 is buggy via the PSA API in Mbed TLS." #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_K1_224 */ #if defined(PSA_WANT_ECC_SECP_K1_256) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 #define MBEDTLS_ECP_DP_SECP256K1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_K1_256 */ /* ECC: algs: enable built-ins as needed. * * We need the alg built-in: * - if it's not accelerated, or * - if there's a relevant curve (see below) with missing acceleration, or * - if there's a key type among (public, basic) with missing acceleration. * * Relevant curves are: * - all curves for ECDH * - Weierstrass curves for (deterministic) ECDSA * - secp256r1 for EC J-PAKE */ #if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) #if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) #define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 #define MBEDTLS_ECDSA_DETERMINISTIC #define MBEDTLS_HMAC_DRBG_C #define MBEDTLS_MD_C #define MBEDTLS_ECDSA_C #define MBEDTLS_ECP_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #endif /* missing accel */ #endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */ #if defined(PSA_WANT_ALG_ECDH) #if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) #define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 #define MBEDTLS_ECDH_C #define MBEDTLS_ECP_C #define MBEDTLS_BIGNUM_C #endif /* missing accel */ #endif /* PSA_WANT_ALG_ECDH */ #if defined(PSA_WANT_ALG_ECDSA) #if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) #define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 #define MBEDTLS_ECDSA_C #define MBEDTLS_ECP_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #endif /* missing accel */ #endif /* PSA_WANT_ALG_ECDSA */ #if defined(PSA_WANT_ALG_JPAKE) #if !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE) || \ !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) #define MBEDTLS_PSA_BUILTIN_PAKE 1 #define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1 #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_BIGNUM_C #define MBEDTLS_ECP_C #define MBEDTLS_ECJPAKE_C #endif /* missing accel */ #endif /* PSA_WANT_ALG_JPAKE */ /* ECC: key types: enable built-ins as needed. * * We need the key type built-in: * - if it's not accelerated, or * - if there's a curve with missing acceleration, or * - only for public/basic: if there's an alg with missing acceleration. */ #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ /* Note: the condition is always true as DERIVE can't be accelerated yet */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #endif /* missing accel */ #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define MBEDTLS_ECP_LIGHT #define MBEDTLS_BIGNUM_C #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) #define MBEDTLS_ECP_C #define MBEDTLS_BIGNUM_C #endif /* End of ECC section */ /* * DH key types follow the same pattern used above for EC keys. They are defined * by a triplet (group, key_type, alg). A triplet is accelerated if all its * component are accelerated, otherwise each component needs to be builtin. */ /* DH: groups: is acceleration complete? */ #if (defined(PSA_WANT_DH_RFC7919_2048) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048)) || \ (defined(PSA_WANT_DH_RFC7919_3072) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072)) || \ (defined(PSA_WANT_DH_RFC7919_4096) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096)) || \ (defined(PSA_WANT_DH_RFC7919_6144) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144)) || \ (defined(PSA_WANT_DH_RFC7919_8192) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192)) #define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS #endif /* DH: algs: is acceleration complete? */ #if defined(PSA_WANT_ALG_FFDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH) #define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS #endif /* DH: key types: is acceleration complete? */ #if (defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY)) || \ (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC)) || \ (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT)) || \ (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT)) || \ (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE)) #define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES #endif #if defined(PSA_WANT_DH_RFC7919_2048) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ #endif /* PSA_WANT_DH_RFC7919_2048 */ #if defined(PSA_WANT_DH_RFC7919_3072) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ #endif /* PSA_WANT_DH_RFC7919_3072 */ #if defined(PSA_WANT_DH_RFC7919_4096) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ #endif /* PSA_WANT_DH_RFC7919_4096 */ #if defined(PSA_WANT_DH_RFC7919_6144) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ #endif /* PSA_WANT_DH_RFC7919_6144 */ #if defined(PSA_WANT_DH_RFC7919_8192) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ #endif /* PSA_WANT_DH_RFC7919_8192 */ #if defined(PSA_WANT_ALG_FFDH) #if !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1 #define MBEDTLS_BIGNUM_C #endif /* !MBEDTLS_PSA_ACCEL_ALG_FFDH */ #endif /* PSA_WANT_ALG_FFDH */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT */ #endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT */ #endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE */ #endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC */ #endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC */ #if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1 #define MBEDTLS_BIGNUM_C #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY */ #endif /* PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY */ /* End of DH section */ #if defined(PSA_WANT_ALG_HKDF) #if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF) /* * The PSA implementation has its own implementation of HKDF, separate from * hkdf.c. No need to enable MBEDTLS_HKDF_C here. */ #define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */ #endif /* PSA_WANT_ALG_HKDF */ #if defined(PSA_WANT_ALG_HKDF_EXTRACT) #if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT) /* * The PSA implementation has its own implementation of HKDF, separate from * hkdf.c. No need to enable MBEDTLS_HKDF_C here. */ #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT */ #endif /* PSA_WANT_ALG_HKDF_EXTRACT */ #if defined(PSA_WANT_ALG_HKDF_EXPAND) #if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND) /* * The PSA implementation has its own implementation of HKDF, separate from * hkdf.c. No need to enable MBEDTLS_HKDF_C here. */ #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND */ #endif /* PSA_WANT_ALG_HKDF_EXPAND */ #if defined(PSA_WANT_ALG_HMAC) #if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC) #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */ #endif /* PSA_WANT_ALG_HMAC */ #if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5) #define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 #define MBEDTLS_MD5_C #endif #if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) #define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 #define MBEDTLS_RIPEMD160_C #endif #if defined(PSA_WANT_ALG_RSA_OAEP) #if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS1_V21 #endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */ #endif /* PSA_WANT_ALG_RSA_OAEP */ #if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) #if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS1_V15 #endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */ #endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */ #if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) #if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS1_V15 #endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */ #endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */ #if defined(PSA_WANT_ALG_RSA_PSS) #if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS1_V21 #endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */ #endif /* PSA_WANT_ALG_RSA_PSS */ #if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 #define MBEDTLS_SHA1_C #endif #if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 #define MBEDTLS_SHA224_C #endif #if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 #define MBEDTLS_SHA256_C #endif #if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 #define MBEDTLS_SHA384_C #endif #if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 #define MBEDTLS_SHA512_C #endif #if defined(PSA_WANT_ALG_SHA3_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1 #define MBEDTLS_SHA3_C #endif #if defined(PSA_WANT_ALG_SHA3_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1 #define MBEDTLS_SHA3_C #endif #if defined(PSA_WANT_ALG_SHA3_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1 #define MBEDTLS_SHA3_C #endif #if defined(PSA_WANT_ALG_SHA3_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1 #define MBEDTLS_SHA3_C #endif #if defined(PSA_WANT_ALG_PBKDF2_HMAC) #if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC) #define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC 1 #define PSA_HAVE_SOFT_PBKDF2_HMAC 1 #endif /* !MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ #endif /* PSA_WANT_ALG_PBKDF2_HMAC */ #if defined(PSA_WANT_ALG_TLS12_PRF) #if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */ #endif /* PSA_WANT_ALG_TLS12_PRF */ #if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) #if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */ #endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */ #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) #if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS */ #endif /* PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 #define MBEDTLS_GENPRIME #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */ #endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */ /* If any of the block modes are requested that don't have an * associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking * in the block cipher key types. */ #if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \ (defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \ (defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \ (defined(PSA_WANT_ALG_ECB_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)) || \ (defined(PSA_WANT_ALG_CBC_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \ (defined(PSA_WANT_ALG_CBC_PKCS7) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)) || \ (defined(PSA_WANT_ALG_CMAC) && !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC)) #define PSA_HAVE_SOFT_BLOCK_MODE 1 #endif #if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) #if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128) #define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 1 #define PSA_HAVE_SOFT_PBKDF2_CMAC 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128 */ #endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */ #if defined(PSA_WANT_KEY_TYPE_AES) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES) #define PSA_HAVE_SOFT_KEY_TYPE_AES 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_BLOCK_MODE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 #define MBEDTLS_AES_C #endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */ #endif /* PSA_WANT_KEY_TYPE_AES */ #if defined(PSA_WANT_KEY_TYPE_ARIA) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA) #define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_BLOCK_MODE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 #define MBEDTLS_ARIA_C #endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */ #endif /* PSA_WANT_KEY_TYPE_ARIA */ #if defined(PSA_WANT_KEY_TYPE_CAMELLIA) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA) #define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \ defined(PSA_HAVE_SOFT_BLOCK_MODE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 #define MBEDTLS_CAMELLIA_C #endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */ #endif /* PSA_WANT_KEY_TYPE_CAMELLIA */ #if defined(PSA_WANT_KEY_TYPE_DES) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES) #define PSA_HAVE_SOFT_KEY_TYPE_DES 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ defined(PSA_HAVE_SOFT_BLOCK_MODE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 #define MBEDTLS_DES_C #endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */ #endif /* PSA_WANT_KEY_TYPE_DES */ #if defined(PSA_WANT_ALG_STREAM_CIPHER) #if !defined(MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 #endif /* MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER */ #endif /* PSA_WANT_ALG_STREAM_CIPHER */ #if defined(PSA_WANT_KEY_TYPE_CHACHA20) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 #define MBEDTLS_CHACHA20_C #endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */ #endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ /* If any of the software block ciphers are selected, define * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these * situations. */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) #define PSA_HAVE_SOFT_BLOCK_CIPHER 1 #endif #if defined(PSA_WANT_ALG_CBC_MAC) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_MAC) #error "CBC-MAC is not yet supported via the PSA API in Mbed TLS." #define MBEDTLS_PSA_BUILTIN_ALG_CBC_MAC 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_CBC_MAC */ #endif /* PSA_WANT_ALG_CBC_MAC */ #if defined(PSA_WANT_ALG_CMAC) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 #define MBEDTLS_CMAC_C #endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */ #endif /* PSA_WANT_ALG_CMAC */ #if defined(PSA_HAVE_SOFT_PBKDF2_HMAC) || \ defined(PSA_HAVE_SOFT_PBKDF2_CMAC) #define PSA_HAVE_SOFT_PBKDF2 1 #endif /* PSA_HAVE_SOFT_PBKDF2_HMAC || PSA_HAVE_SOFT_PBKDF2_CMAC */ #if defined(PSA_WANT_ALG_CTR) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 #define MBEDTLS_CIPHER_MODE_CTR #endif #endif /* PSA_WANT_ALG_CTR */ #if defined(PSA_WANT_ALG_CFB) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 #define MBEDTLS_CIPHER_MODE_CFB #endif #endif /* PSA_WANT_ALG_CFB */ #if defined(PSA_WANT_ALG_OFB) #if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 #define MBEDTLS_CIPHER_MODE_OFB #endif #endif /* PSA_WANT_ALG_OFB */ #if defined(PSA_WANT_ALG_ECB_NO_PADDING) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING) #define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 #endif #if defined(PSA_WANT_ALG_CBC_NO_PADDING) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 #endif #endif /* PSA_WANT_ALG_CBC_NO_PADDING */ #if defined(PSA_WANT_ALG_CBC_PKCS7) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 #define MBEDTLS_CIPHER_PADDING_PKCS7 #endif #endif /* PSA_WANT_ALG_CBC_PKCS7 */ #if defined(PSA_WANT_ALG_CCM) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) #define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 #define MBEDTLS_CCM_C #endif #endif /* PSA_WANT_ALG_CCM */ #if defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM_STAR_NO_TAG) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) #define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1 #define MBEDTLS_CCM_C #endif #endif /* PSA_WANT_ALG_CCM_STAR_NO_TAG */ #if defined(PSA_WANT_ALG_GCM) #if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) #define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 #define MBEDTLS_GCM_C #endif #endif /* PSA_WANT_ALG_GCM */ #if defined(PSA_WANT_ALG_CHACHA20_POLY1305) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305) #if defined(PSA_WANT_KEY_TYPE_CHACHA20) #define MBEDTLS_CHACHAPOLY_C #define MBEDTLS_CHACHA20_C #define MBEDTLS_POLY1305_C #define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 #endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ #endif /* !MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 */ #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ #endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H */ webfakes/src/mbedtls/include/mbedtls/platform.h0000644000176200001440000004175414740737024021357 0ustar liggesusers/** * \file platform.h * * \brief This file contains the definitions and functions of the * Mbed TLS platform abstraction layer. * * The platform abstraction layer removes the need for the library * to directly link to standard C library functions or operating * system services, making the library easier to port and embed. * Application developers and users of the library can provide their own * implementations of these functions, or implementations specific to * their platform, which can be statically linked to the library or * dynamically configured at runtime. * * When all compilation options related to platform abstraction are * disabled, this header just defines `mbedtls_xxx` function names * as aliases to the standard `xxx` function. * * Most modules in the library and example programs are expected to * include this header. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PLATFORM_H #define MBEDTLS_PLATFORM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #ifdef __cplusplus extern "C" { #endif /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ /* The older Microsoft Windows common runtime provides non-conforming * implementations of some standard library functions, including snprintf * and vsnprintf. This affects MSVC and MinGW builds. */ #if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) #define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF #define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF #endif #if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) #include #include #if defined(MBEDTLS_HAVE_TIME) #include #endif #if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) #define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ #else #define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ #endif #endif #if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) #define MBEDTLS_PLATFORM_STD_VSNPRINTF mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to use. */ #else #define MBEDTLS_PLATFORM_STD_VSNPRINTF vsnprintf /**< The default \c vsnprintf function to use. */ #endif #endif #if !defined(MBEDTLS_PLATFORM_STD_PRINTF) #define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) #define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_CALLOC) #define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_FREE) #define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_SETBUF) #define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< The default \c setbuf function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT) #define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_TIME) #define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) #define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) #define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ #endif #if defined(MBEDTLS_FS_IO) #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) #define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read #endif #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) #define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write #endif #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) #define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" #endif #endif /* MBEDTLS_FS_IO */ #else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ #if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) #include MBEDTLS_PLATFORM_STD_MEM_HDR #endif #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ /* Enable certain documented defines only when generating doxygen to avoid * an "unrecognized define" error. */ #if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_CALLOC) #define MBEDTLS_PLATFORM_STD_CALLOC #endif #if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_FREE) #define MBEDTLS_PLATFORM_STD_FREE #endif /** \} name SECTION: Module settings */ /* * The function pointers for calloc and free. * Please see MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE * in mbedtls_config.h for more information about behaviour and requirements. */ #if defined(MBEDTLS_PLATFORM_MEMORY) #if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ defined(MBEDTLS_PLATFORM_CALLOC_MACRO) #undef mbedtls_free #undef mbedtls_calloc #define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO #define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO #else /* For size_t */ #include extern void *mbedtls_calloc(size_t n, size_t size); extern void mbedtls_free(void *ptr); /** * \brief This function dynamically sets the memory-management * functions used by the library, during runtime. * * \param calloc_func The \c calloc function implementation. * \param free_func The \c free function implementation. * * \return \c 0. */ int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t), void (*free_func)(void *)); #endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ #else /* !MBEDTLS_PLATFORM_MEMORY */ #undef mbedtls_free #undef mbedtls_calloc #define mbedtls_free free #define mbedtls_calloc calloc #endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ /* * The function pointers for fprintf */ #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) /* We need FILE * */ #include extern int (*mbedtls_fprintf)(FILE *stream, const char *format, ...); /** * \brief This function dynamically configures the fprintf * function that is called when the * mbedtls_fprintf() function is invoked by the library. * * \param fprintf_func The \c fprintf function implementation. * * \return \c 0. */ int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *stream, const char *, ...)); #else #undef mbedtls_fprintf #if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) #define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO #else #define mbedtls_fprintf fprintf #endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ /* * The function pointers for printf */ #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) extern int (*mbedtls_printf)(const char *format, ...); /** * \brief This function dynamically configures the snprintf * function that is called when the mbedtls_snprintf() * function is invoked by the library. * * \param printf_func The \c printf function implementation. * * \return \c 0 on success. */ int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...)); #else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ #undef mbedtls_printf #if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) #define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO #else #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ /* * The function pointers for snprintf * * The snprintf implementation should conform to C99: * - it *must* always correctly zero-terminate the buffer * (except when n == 0, then it must leave the buffer untouched) * - however it is acceptable to return -1 instead of the required length when * the destination buffer is too short. */ #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) /* For Windows (inc. MSYS2), we provide our own fixed implementation */ int mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...); #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) extern int (*mbedtls_snprintf)(char *s, size_t n, const char *format, ...); /** * \brief This function allows configuring a custom * \c snprintf function pointer. * * \param snprintf_func The \c snprintf function implementation. * * \return \c 0 on success. */ int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n, const char *format, ...)); #else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ #undef mbedtls_snprintf #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) #define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO #else #define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF #endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ /* * The function pointers for vsnprintf * * The vsnprintf implementation should conform to C99: * - it *must* always correctly zero-terminate the buffer * (except when n == 0, then it must leave the buffer untouched) * - however it is acceptable to return -1 instead of the required length when * the destination buffer is too short. */ #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) #include /* For Older Windows (inc. MSYS2), we provide our own fixed implementation */ int mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, va_list arg); #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) #include extern int (*mbedtls_vsnprintf)(char *s, size_t n, const char *format, va_list arg); /** * \brief Set your own snprintf function pointer * * \param vsnprintf_func The \c vsnprintf function implementation * * \return \c 0 */ int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n, const char *format, va_list arg)); #else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ #undef mbedtls_vsnprintf #if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) #define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO #else #define mbedtls_vsnprintf vsnprintf #endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ /* * The function pointers for setbuf */ #if defined(MBEDTLS_PLATFORM_SETBUF_ALT) #include /** * \brief Function pointer to call for `setbuf()` functionality * (changing the internal buffering on stdio calls). * * \note The library calls this function to disable * buffering when reading or writing sensitive data, * to avoid having extra copies of sensitive data * remaining in stdio buffers after the file is * closed. If this is not a concern, for example if * your platform's stdio doesn't have any buffering, * you can set mbedtls_setbuf to a function that * does nothing. * * The library always calls this function with * `buf` equal to `NULL`. */ extern void (*mbedtls_setbuf)(FILE *stream, char *buf); /** * \brief Dynamically configure the function that is called * when the mbedtls_setbuf() function is called by the * library. * * \param setbuf_func The \c setbuf function implementation * * \return \c 0 */ int mbedtls_platform_set_setbuf(void (*setbuf_func)( FILE *stream, char *buf)); #else #undef mbedtls_setbuf #if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) /** * \brief Macro defining the function for the library to * call for `setbuf` functionality (changing the * internal buffering on stdio calls). * * \note See extra comments on the mbedtls_setbuf() function * pointer above. * * \return \c 0 on success, negative on error. */ #define mbedtls_setbuf MBEDTLS_PLATFORM_SETBUF_MACRO #else #define mbedtls_setbuf setbuf #endif /* MBEDTLS_PLATFORM_SETBUF_MACRO */ #endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ /* * The function pointers for exit */ #if defined(MBEDTLS_PLATFORM_EXIT_ALT) extern void (*mbedtls_exit)(int status); /** * \brief This function dynamically configures the exit * function that is called when the mbedtls_exit() * function is invoked by the library. * * \param exit_func The \c exit function implementation. * * \return \c 0 on success. */ int mbedtls_platform_set_exit(void (*exit_func)(int status)); #else #undef mbedtls_exit #if defined(MBEDTLS_PLATFORM_EXIT_MACRO) #define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO #else #define mbedtls_exit exit #endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ #endif /* MBEDTLS_PLATFORM_EXIT_ALT */ /* * The default exit values */ #if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) #define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS #else #define MBEDTLS_EXIT_SUCCESS 0 #endif #if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) #define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE #else #define MBEDTLS_EXIT_FAILURE 1 #endif /* * The function pointers for reading from and writing a seed file to * Non-Volatile storage (NV) in a platform-independent way * * Only enabled when the NV seed entropy source is enabled */ #if defined(MBEDTLS_ENTROPY_NV_SEED) #if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) /* Internal standard platform definitions */ int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len); int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len); #endif #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) extern int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len); extern int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len); /** * \brief This function allows configuring custom seed file writing and * reading functions. * * \param nv_seed_read_func The seed reading function implementation. * \param nv_seed_write_func The seed writing function implementation. * * \return \c 0 on success. */ int mbedtls_platform_set_nv_seed( int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len), int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len) ); #else #undef mbedtls_nv_seed_read #undef mbedtls_nv_seed_write #if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) #define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO #define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO #else #define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read #define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write #endif #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) /** * \brief The platform context structure. * * \note This structure may be used to assist platform-specific * setup or teardown operations. */ typedef struct mbedtls_platform_context { char MBEDTLS_PRIVATE(dummy); /**< A placeholder member, as empty structs are not portable. */ } mbedtls_platform_context; #else #include "platform_alt.h" #endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ /** * \brief This function performs any platform-specific initialization * operations. * * \note This function should be called before any other library functions. * * Its implementation is platform-specific, and unless * platform-specific code is provided, it does nothing. * * \note The usage and necessity of this function is dependent on the platform. * * \param ctx The platform context. * * \return \c 0 on success. */ int mbedtls_platform_setup(mbedtls_platform_context *ctx); /** * \brief This function performs any platform teardown operations. * * \note This function should be called after every other Mbed TLS module * has been correctly freed using the appropriate free function. * * Its implementation is platform-specific, and unless * platform-specific code is provided, it does nothing. * * \note The usage and necessity of this function is dependent on the platform. * * \param ctx The platform context. * */ void mbedtls_platform_teardown(mbedtls_platform_context *ctx); #ifdef __cplusplus } #endif #endif /* platform.h */ webfakes/src/mbedtls/include/mbedtls/sha3.h0000644000176200001440000001266314740737024020366 0ustar liggesusers/** * \file sha3.h * * \brief This file contains SHA-3 definitions and functions. * * The Secure Hash Algorithms cryptographic * hash functions are defined in FIPS 202: SHA-3 Standard: * Permutation-Based Hash and Extendable-Output Functions . */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA3_H #define MBEDTLS_SHA3_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #ifdef __cplusplus extern "C" { #endif /** SHA-3 input data was malformed. */ #define MBEDTLS_ERR_SHA3_BAD_INPUT_DATA -0x0076 /** * SHA-3 family id. * * It identifies the family (SHA3-256, SHA3-512, etc.) */ typedef enum { MBEDTLS_SHA3_NONE = 0, /*!< Operation not defined. */ MBEDTLS_SHA3_224, /*!< SHA3-224 */ MBEDTLS_SHA3_256, /*!< SHA3-256 */ MBEDTLS_SHA3_384, /*!< SHA3-384 */ MBEDTLS_SHA3_512, /*!< SHA3-512 */ } mbedtls_sha3_id; /** * \brief The SHA-3 context structure. * * The structure is used SHA-3 checksum calculations. */ typedef struct { uint64_t MBEDTLS_PRIVATE(state[25]); uint32_t MBEDTLS_PRIVATE(index); uint16_t MBEDTLS_PRIVATE(olen); uint16_t MBEDTLS_PRIVATE(max_block_size); } mbedtls_sha3_context; /** * \brief This function initializes a SHA-3 context. * * \param ctx The SHA-3 context to initialize. This must not be \c NULL. */ void mbedtls_sha3_init(mbedtls_sha3_context *ctx); /** * \brief This function clears a SHA-3 context. * * \param ctx The SHA-3 context to clear. This may be \c NULL, in which * case this function returns immediately. If it is not \c NULL, * it must point to an initialized SHA-3 context. */ void mbedtls_sha3_free(mbedtls_sha3_context *ctx); /** * \brief This function clones the state of a SHA-3 context. * * \param dst The destination context. This must be initialized. * \param src The context to clone. This must be initialized. */ void mbedtls_sha3_clone(mbedtls_sha3_context *dst, const mbedtls_sha3_context *src); /** * \brief This function starts a SHA-3 checksum * calculation. * * \param ctx The context to use. This must be initialized. * \param id The id of the SHA-3 family. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id); /** * \brief This function feeds an input buffer into an ongoing * SHA-3 checksum calculation. * * \param ctx The SHA-3 context. This must be initialized * and have a hash operation started. * \param input The buffer holding the data. This must be a readable * buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha3_update(mbedtls_sha3_context *ctx, const uint8_t *input, size_t ilen); /** * \brief This function finishes the SHA-3 operation, and writes * the result to the output buffer. * * \param ctx The SHA-3 context. This must be initialized * and have a hash operation started. * \param output The SHA-3 checksum result. * This must be a writable buffer of length \c olen bytes. * \param olen Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256, * SHA-3 384 and SHA-3 512 \c olen must equal to 28, 32, 48 and 64, * respectively. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha3_finish(mbedtls_sha3_context *ctx, uint8_t *output, size_t olen); /** * \brief This function calculates the SHA-3 * checksum of a buffer. * * The function allocates the context, performs the * calculation, and frees the context. * * The SHA-3 result is calculated as * output = SHA-3(id, input buffer, d). * * \param id The id of the SHA-3 family. * \param input The buffer holding the data. This must be a readable * buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * \param output The SHA-3 checksum result. * This must be a writable buffer of length \c olen bytes. * \param olen Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256, * SHA-3 384 and SHA-3 512 \c olen must equal to 28, 32, 48 and 64, * respectively. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input, size_t ilen, uint8_t *output, size_t olen); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine for the algorithms implemented * by this module: SHA3-224, SHA3-256, SHA3-384, SHA3-512. * * \return 0 if successful, or 1 if the test failed. */ int mbedtls_sha3_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_sha3.h */ webfakes/src/mbedtls/include/mbedtls/dhm.h0000644000176200001440000014044314740737024020276 0ustar liggesusers/** * \file dhm.h * * \brief This file contains Diffie-Hellman-Merkle (DHM) key exchange * definitions and functions. * * Diffie-Hellman-Merkle (DHM) key exchange is defined in * RFC-2631: Diffie-Hellman Key Agreement Method and * Public-Key Cryptography Standards (PKCS) #3: Diffie * Hellman Key Agreement Standard. * * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for * Internet Key Exchange (IKE) defines a number of standardized * Diffie-Hellman groups for IKE. * * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF * Standards defines a number of standardized Diffie-Hellman * groups that can be used. * * \warning The security of the DHM key exchange relies on the proper choice * of prime modulus - optimally, it should be a safe prime. The usage * of non-safe primes both decreases the difficulty of the underlying * discrete logarithm problem and can lead to small subgroup attacks * leaking private exponent bits when invalid public keys are used * and not detected. This is especially relevant if the same DHM * parameters are reused for multiple key exchanges as in static DHM, * while the criticality of small-subgroup attacks is lower for * ephemeral DHM. * * \warning For performance reasons, the code does neither perform primality * nor safe primality tests, nor the expensive checks for invalid * subgroups. Moreover, even if these were performed, non-standardized * primes cannot be trusted because of the possibility of backdoors * that can't be effectively checked for. * * \warning Diffie-Hellman-Merkle is therefore a security risk when not using * standardized primes generated using a trustworthy ("nothing up * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS * protocol, DH parameters need to be negotiated, so using the default * primes systematically is not always an option. If possible, use * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, * and for which the TLS protocol mandates the use of standard * parameters. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_DHM_H #define MBEDTLS_DHM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" /* * DHM Error codes */ /** Bad input parameters. */ #define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /** Reading of the DHM parameters failed. */ #define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /** Making of the DHM parameters failed. */ #define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /** Reading of the public values failed. */ #define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /** Making of the public value failed. */ #define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /** Calculation of the DHM secret failed. */ #define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /** The ASN.1 data is not formatted correctly. */ #define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /** Allocation of memory failed. */ #define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /** Read or write of file failed. */ #define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /** Setting the modulus and generator failed. */ #define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /** Which parameter to access in mbedtls_dhm_get_value(). */ typedef enum { MBEDTLS_DHM_PARAM_P, /*!< The prime modulus. */ MBEDTLS_DHM_PARAM_G, /*!< The generator. */ MBEDTLS_DHM_PARAM_X, /*!< Our secret value. */ MBEDTLS_DHM_PARAM_GX, /*!< Our public key = \c G^X mod \c P. */ MBEDTLS_DHM_PARAM_GY, /*!< The public key of the peer = \c G^Y mod \c P. */ MBEDTLS_DHM_PARAM_K, /*!< The shared secret = \c G^(XY) mod \c P. */ } mbedtls_dhm_parameter; #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_DHM_ALT) /** * \brief The DHM context structure. */ typedef struct mbedtls_dhm_context { mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The prime modulus. */ mbedtls_mpi MBEDTLS_PRIVATE(G); /*!< The generator. */ mbedtls_mpi MBEDTLS_PRIVATE(X); /*!< Our secret value. */ mbedtls_mpi MBEDTLS_PRIVATE(GX); /*!< Our public key = \c G^X mod \c P. */ mbedtls_mpi MBEDTLS_PRIVATE(GY); /*!< The public key of the peer = \c G^Y mod \c P. */ mbedtls_mpi MBEDTLS_PRIVATE(K); /*!< The shared secret = \c G^(XY) mod \c P. */ mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< The cached value = \c R^2 mod \c P. */ mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ mbedtls_mpi MBEDTLS_PRIVATE(pX); /*!< The previous \c X. */ } mbedtls_dhm_context; #else /* MBEDTLS_DHM_ALT */ #include "dhm_alt.h" #endif /* MBEDTLS_DHM_ALT */ /** * \brief This function initializes the DHM context. * * \param ctx The DHM context to initialize. */ void mbedtls_dhm_init(mbedtls_dhm_context *ctx); /** * \brief This function parses the DHM parameters in a * TLS ServerKeyExchange handshake message * (DHM modulus, generator, and public key). * * \note In a TLS handshake, this is the how the client * sets up its DHM context from the server's public * DHM key material. * * \param ctx The DHM context to use. This must be initialized. * \param p On input, *p must be the start of the input buffer. * On output, *p is updated to point to the end of the data * that has been read. On success, this is the first byte * past the end of the ServerKeyExchange parameters. * On error, this is the point at which an error has been * detected, which is usually not useful except to debug * failures. * \param end The end of the input buffer. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx, unsigned char **p, const unsigned char *end); /** * \brief This function generates a DHM key pair and exports its * public part together with the DHM parameters in the format * used in a TLS ServerKeyExchange handshake message. * * \note This function assumes that the DHM parameters \c ctx->P * and \c ctx->G have already been properly set. For that, use * mbedtls_dhm_set_group() below in conjunction with * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). * * \note In a TLS handshake, this is the how the server generates * and exports its DHM key material. * * \param ctx The DHM context to use. This must be initialized * and have the DHM parameters set. It may or may not * already have imported the peer's public key. * \param x_size The private key size in Bytes. * \param olen The address at which to store the number of Bytes * written on success. This must not be \c NULL. * \param output The destination buffer. This must be a writable buffer of * sufficient size to hold the reduced binary presentation of * the modulus, the generator and the public key, each wrapped * with a 2-byte length field. It is the responsibility of the * caller to ensure that enough space is available. Refer to * mbedtls_mpi_size() to computing the byte-size of an MPI. * \param f_rng The RNG function. Must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function sets the prime modulus and generator. * * \note This function can be used to set \c ctx->P, \c ctx->G * in preparation for mbedtls_dhm_make_params(). * * \param ctx The DHM context to configure. This must be initialized. * \param P The MPI holding the DHM prime modulus. This must be * an initialized MPI. * \param G The MPI holding the DHM generator. This must be an * initialized MPI. * * \return \c 0 if successful. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx, const mbedtls_mpi *P, const mbedtls_mpi *G); /** * \brief This function imports the raw public value of the peer. * * \note In a TLS handshake, this is the how the server imports * the Client's public DHM key. * * \param ctx The DHM context to use. This must be initialized and have * its DHM parameters set, e.g. via mbedtls_dhm_set_group(). * It may or may not already have generated its own private key. * \param input The input buffer containing the \c G^Y value of the peer. * This must be a readable buffer of size \p ilen Bytes. * \param ilen The size of the input buffer \p input in Bytes. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function creates a DHM key pair and exports * the raw public key in big-endian format. * * \note The destination buffer is always fully written * so as to contain a big-endian representation of G^X mod P. * If it is larger than \c ctx->len, it is padded accordingly * with zero-bytes at the beginning. * * \param ctx The DHM context to use. This must be initialized and * have the DHM parameters set. It may or may not already * have imported the peer's public key. * \param x_size The private key size in Bytes. * \param output The destination buffer. This must be a writable buffer of * size \p olen Bytes. * \param olen The length of the destination buffer. This must be at least * equal to `ctx->len` (the size of \c P). * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function derives and exports the shared secret * \c (G^Y)^X mod \c P. * * \note If \p f_rng is not \c NULL, it is used to blind the input as * a countermeasure against timing attacks. Blinding is used * only if our private key \c X is re-used, and not used * otherwise. We recommend always passing a non-NULL * \p f_rng argument. * * \param ctx The DHM context to use. This must be initialized * and have its own private key generated and the peer's * public key imported. * \param output The buffer to write the generated shared key to. This * must be a writable buffer of size \p output_size Bytes. * \param output_size The size of the destination buffer. This must be at * least the size of \c ctx->len (the size of \c P). * \param olen On exit, holds the actual number of Bytes written. * \param f_rng The RNG function. Must not be \c NULL. Used for * blinding. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx, unsigned char *output, size_t output_size, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function returns the size of the prime modulus in bits. * * \param ctx The DHM context to query. * * \return The size of the prime modulus in bits, * i.e. the number n such that 2^(n-1) <= P < 2^n. */ size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx); /** * \brief This function returns the size of the prime modulus in bytes. * * \param ctx The DHM context to query. * * \return The size of the prime modulus in bytes, * i.e. the number n such that 2^(8*(n-1)) <= P < 2^(8*n). */ size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx); /** * \brief This function copies a parameter of a DHM key. * * \param ctx The DHM context to query. * \param param The parameter to copy. * \param dest The MPI object to copy the value into. It must be * initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \p param is invalid. * \return An \c MBEDTLS_ERR_MPI_XXX error code if the copy fails. */ int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx, mbedtls_dhm_parameter param, mbedtls_mpi *dest); /** * \brief This function frees and clears the components * of a DHM context. * * \param ctx The DHM context to free and clear. This may be \c NULL, * in which case this function is a no-op. If it is not \c NULL, * it must point to an initialized DHM context. */ void mbedtls_dhm_free(mbedtls_dhm_context *ctx); #if defined(MBEDTLS_ASN1_PARSE_C) /** * \brief This function parses DHM parameters in PEM or DER format. * * \param dhm The DHM context to import the DHM parameters into. * This must be initialized. * \param dhmin The input buffer. This must be a readable buffer of * length \p dhminlen Bytes. * \param dhminlen The size of the input buffer \p dhmin, including the * terminating \c NULL Byte for PEM data. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error * code on failure. */ int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen); #if defined(MBEDTLS_FS_IO) /** * \brief This function loads and parses DHM parameters from a file. * * \param dhm The DHM context to load the parameters to. * This must be initialized. * \param path The filename to read the DHM parameters from. * This must not be \c NULL. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX * error code on failure. */ int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path); #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_ASN1_PARSE_C */ #if defined(MBEDTLS_SELF_TEST) /** * \brief The DMH checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_dhm_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif /** * RFC 3526, RFC 5114 and RFC 7919 standardize a number of * Diffie-Hellman groups, some of which are included here * for use within the SSL/TLS module and the user's convenience * when configuring the Diffie-Hellman parameters by hand * through \c mbedtls_ssl_conf_dh_param. * * The following lists the source of the above groups in the standards: * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup * - RFC 3526 section 3: 2048-bit MODP Group * - RFC 3526 section 4: 3072-bit MODP Group * - RFC 3526 section 5: 4096-bit MODP Group * - RFC 7919 section A.1: ffdhe2048 * - RFC 7919 section A.2: ffdhe3072 * - RFC 7919 section A.3: ffdhe4096 * - RFC 7919 section A.4: ffdhe6144 * - RFC 7919 section A.5: ffdhe8192 * * The constants with suffix "_p" denote the chosen prime moduli, while * the constants with suffix "_g" denote the chosen generator * of the associated prime field. * * The constants further suffixed with "_bin" are provided in binary format, * while all other constants represent null-terminated strings holding the * hexadecimal presentation of the respective numbers. * * The primes from RFC 3526 and RFC 7919 have been generating by the following * trust-worthy procedure: * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number * the first and last 64 bits are all 1, and the remaining N - 128 bits of * which are 0x7ff...ff. * - Add the smallest multiple of the first N - 129 bits of the binary expansion * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string * such that the resulting integer is a safe-prime. * - The result is the respective RFC 3526 / 7919 prime, and the corresponding * generator is always chosen to be 2 (which is a square for these prime, * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a * bit in the private exponent). * */ /* * Trustworthy DHM parameters in binary form */ #define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } #define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } #endif /* dhm.h */ webfakes/src/mbedtls/include/mbedtls/timing.h0000644000176200001440000000520714740737024021013 0ustar liggesusers/** * \file timing.h * * \brief Portable interface to timeouts and to the CPU cycle counter */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_TIMING_H #define MBEDTLS_TIMING_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_TIMING_ALT) // Regular implementation // /** * \brief timer structure */ struct mbedtls_timing_hr_time { uint64_t MBEDTLS_PRIVATE(opaque)[4]; }; /** * \brief Context for mbedtls_timing_set/get_delay() */ typedef struct mbedtls_timing_delay_context { struct mbedtls_timing_hr_time MBEDTLS_PRIVATE(timer); uint32_t MBEDTLS_PRIVATE(int_ms); uint32_t MBEDTLS_PRIVATE(fin_ms); } mbedtls_timing_delay_context; #else /* MBEDTLS_TIMING_ALT */ #include "timing_alt.h" #endif /* MBEDTLS_TIMING_ALT */ /* Internal use */ unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset); /** * \brief Set a pair of delays to watch * (See \c mbedtls_timing_get_delay().) * * \param data Pointer to timing data. * Must point to a valid \c mbedtls_timing_delay_context struct. * \param int_ms First (intermediate) delay in milliseconds. * The effect if int_ms > fin_ms is unspecified. * \param fin_ms Second (final) delay in milliseconds. * Pass 0 to cancel the current delay. * * \note To set a single delay, either use \c mbedtls_timing_set_timer * directly or use this function with int_ms == fin_ms. */ void mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms); /** * \brief Get the status of delays * (Memory helper: number of delays passed.) * * \param data Pointer to timing data * Must point to a valid \c mbedtls_timing_delay_context struct. * * \return -1 if cancelled (fin_ms = 0), * 0 if none of the delays are passed, * 1 if only the intermediate delay is passed, * 2 if the final delay is passed. */ int mbedtls_timing_get_delay(void *data); /** * \brief Get the final timing delay * * \param data Pointer to timing data * Must point to a valid \c mbedtls_timing_delay_context struct. * * \return Final timing delay in milliseconds. */ uint32_t mbedtls_timing_get_final_delay( const mbedtls_timing_delay_context *data); #ifdef __cplusplus } #endif #endif /* timing.h */ webfakes/src/mbedtls/include/mbedtls/ssl_cookie.h0000644000176200001440000000613314740737024021655 0ustar liggesusers/** * \file ssl_cookie.h * * \brief DTLS cookie callbacks implementation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_COOKIE_H #define MBEDTLS_SSL_COOKIE_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ssl.h" #if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #endif /* !MBEDTLS_USE_PSA_CRYPTO */ /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #ifndef MBEDTLS_SSL_COOKIE_TIMEOUT #define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ #endif /** \} name SECTION: Module settings */ #ifdef __cplusplus extern "C" { #endif /** * \brief Context for the default cookie functions. */ typedef struct mbedtls_ssl_cookie_ctx { #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psa_hmac_key); /*!< key id for the HMAC portion */ psa_algorithm_t MBEDTLS_PRIVATE(psa_hmac_alg); /*!< key algorithm for the HMAC portion */ #else mbedtls_md_context_t MBEDTLS_PRIVATE(hmac_ctx); /*!< context for the HMAC portion */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_HAVE_TIME) unsigned long MBEDTLS_PRIVATE(serial); /*!< serial number for expiration */ #endif unsigned long MBEDTLS_PRIVATE(timeout); /*!< timeout delay, in seconds if HAVE_TIME, or in number of tickets issued */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } mbedtls_ssl_cookie_ctx; /** * \brief Initialize cookie context */ void mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx); /** * \brief Setup cookie context (generate keys) */ int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Set expiration delay for cookies * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) * * \param ctx Cookie context * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies * issued in the meantime. * 0 to disable expiration (NOT recommended) */ void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay); /** * \brief Free cookie context */ void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx); /** * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t */ mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; /** * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t */ mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; #ifdef __cplusplus } #endif #endif /* ssl_cookie.h */ webfakes/src/mbedtls/include/mbedtls/platform_util.h0000644000176200001440000001750214740737024022406 0ustar liggesusers/** * \file platform_util.h * * \brief Common and shared functions used by multiple modules in the Mbed TLS * library. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PLATFORM_UTIL_H #define MBEDTLS_PLATFORM_UTIL_H #include "mbedtls/build_info.h" #include #if defined(MBEDTLS_HAVE_TIME_DATE) #include "mbedtls/platform_time.h" #include #endif /* MBEDTLS_HAVE_TIME_DATE */ #ifdef __cplusplus extern "C" { #endif /* Internal helper macros for deprecating API constants. */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) #define MBEDTLS_DEPRECATED __attribute__((deprecated)) MBEDTLS_DEPRECATED typedef char const *mbedtls_deprecated_string_constant_t; #define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL) \ ((mbedtls_deprecated_string_constant_t) (VAL)) MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; #define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL) \ ((mbedtls_deprecated_numeric_constant_t) (VAL)) #else /* MBEDTLS_DEPRECATED_WARNING */ #define MBEDTLS_DEPRECATED #define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL) VAL #define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL) VAL #endif /* MBEDTLS_DEPRECATED_WARNING */ #endif /* MBEDTLS_DEPRECATED_REMOVED */ /* Implementation of the check-return facility. * See the user documentation in mbedtls_config.h. * * Do not use this macro directly to annotate function: instead, * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL * depending on how important it is to check the return value. */ #if !defined(MBEDTLS_CHECK_RETURN) #if defined(__GNUC__) #define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__)) #elif defined(_MSC_VER) && _MSC_VER >= 1700 #include #define MBEDTLS_CHECK_RETURN _Check_return_ #else #define MBEDTLS_CHECK_RETURN #endif #endif /** Critical-failure function * * This macro appearing at the beginning of the declaration of a function * indicates that its return value should be checked in all applications. * Omitting the check is very likely to indicate a bug in the application * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN * is implemented for the compiler in use. * * \note The use of this macro is a work in progress. * This macro may be added to more functions in the future. * Such an extension is not considered an API break, provided that * there are near-unavoidable circumstances under which the function * can fail. For example, signature/MAC/AEAD verification functions, * and functions that require a random generator, are considered * return-check-critical. */ #define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN /** Ordinary-failure function * * This macro appearing at the beginning of the declaration of a function * indicates that its return value should be generally be checked in portable * applications. Omitting the check will result in a compile-time warning if * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration. * * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value * of a function that is annotated with #MBEDTLS_CHECK_RETURN. * * \note The use of this macro is a work in progress. * This macro will be added to more functions in the future. * Eventually this should appear before most functions returning * an error code (as \c int in the \c mbedtls_xxx API or * as ::psa_status_t in the \c psa_xxx API). */ #if defined(MBEDTLS_CHECK_RETURN_WARNING) #define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN #else #define MBEDTLS_CHECK_RETURN_TYPICAL #endif /** Benign-failure function * * This macro appearing at the beginning of the declaration of a function * indicates that it is rarely useful to check its return value. * * This macro has an empty expansion. It exists for documentation purposes: * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function * has been analyzed for return-check usefulness, whereas the lack of * an annotation indicates that the function has not been analyzed and its * return-check usefulness is unknown. */ #define MBEDTLS_CHECK_RETURN_OPTIONAL /** \def MBEDTLS_IGNORE_RETURN * * Call this macro with one argument, a function call, to suppress a warning * from #MBEDTLS_CHECK_RETURN due to that function call. */ #if !defined(MBEDTLS_IGNORE_RETURN) /* GCC doesn't silence the warning with just (void)(result). * (void)!(result) is known to work up at least up to GCC 10, as well * as with Clang and MSVC. * * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34 */ #define MBEDTLS_IGNORE_RETURN(result) ((void) !(result)) #endif /* If the following macro is defined, the library is being built by the test * framework, and the framework is going to provide a replacement * mbedtls_platform_zeroize() using a preprocessor macro, so the function * declaration should be omitted. */ #if !defined(MBEDTLS_TEST_DEFINES_ZEROIZE) //no-check-names /** * \brief Securely zeroize a buffer * * The function is meant to wipe the data contained in a buffer so * that it can no longer be recovered even if the program memory * is later compromised. Call this function on sensitive data * stored on the stack before returning from a function, and on * sensitive data stored on the heap before freeing the heap * object. * * It is extremely difficult to guarantee that calls to * mbedtls_platform_zeroize() are not removed by aggressive * compiler optimizations in a portable way. For this reason, Mbed * TLS provides the configuration option * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure * mbedtls_platform_zeroize() to use a suitable implementation for * their platform and needs * * \param buf Buffer to be zeroized * \param len Length of the buffer in bytes * */ void mbedtls_platform_zeroize(void *buf, size_t len); #endif #if defined(MBEDTLS_HAVE_TIME_DATE) /** * \brief Platform-specific implementation of gmtime_r() * * The function is a thread-safe abstraction that behaves * similarly to the gmtime_r() function from Unix/POSIX. * * Mbed TLS will try to identify the underlying platform and * make use of an appropriate underlying implementation (e.g. * gmtime_r() for POSIX and gmtime_s() for Windows). If this is * not possible, then gmtime() will be used. In this case, calls * from the library to gmtime() will be guarded by the mutex * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is * enabled. It is recommended that calls from outside the library * are also guarded by this mutex. * * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will * unconditionally use the alternative implementation for * mbedtls_platform_gmtime_r() supplied by the user at compile time. * * \param tt Pointer to an object containing time (in seconds) since the * epoch to be converted * \param tm_buf Pointer to an object where the results will be stored * * \return Pointer to an object of type struct tm on success, otherwise * NULL */ struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt, struct tm *tm_buf); #endif /* MBEDTLS_HAVE_TIME_DATE */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_PLATFORM_UTIL_H */ webfakes/src/mbedtls/include/mbedtls/hmac_drbg.h0000644000176200001440000004413514740737024021435 0ustar liggesusers/** * \file hmac_drbg.h * * \brief The HMAC_DRBG pseudorandom generator. * * This module implements the HMAC_DRBG pseudorandom generator described * in NIST SP 800-90A: Recommendation for Random Number Generation Using * Deterministic Random Bit Generators. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_HMAC_DRBG_H #define MBEDTLS_HMAC_DRBG_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/md.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /* * Error codes */ /** Too many random requested in single call. */ #define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /** Input too large (Entropy + additional). */ #define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /** Read/write error in file. */ #define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /** The entropy source failed. */ #define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) #define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ #endif #if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) #define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ #endif #if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) #define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ #endif #if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) #define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ #endif /** \} name SECTION: Module settings */ #define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ #define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ #ifdef __cplusplus extern "C" { #endif /** * HMAC_DRBG context. */ typedef struct mbedtls_hmac_drbg_context { /* Working state: the key K is not stored explicitly, * but is implied by the HMAC context */ mbedtls_md_context_t MBEDTLS_PRIVATE(md_ctx); /*!< HMAC context (inc. K) */ unsigned char MBEDTLS_PRIVATE(V)[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ int MBEDTLS_PRIVATE(reseed_counter); /*!< reseed counter */ /* Administrative state */ size_t MBEDTLS_PRIVATE(entropy_len); /*!< entropy bytes grabbed on each (re)seed */ int MBEDTLS_PRIVATE(prediction_resistance); /*!< enable prediction resistance (Automatic reseed before every random generation) */ int MBEDTLS_PRIVATE(reseed_interval); /*!< reseed interval */ /* Callbacks */ int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); /*!< entropy function */ void *MBEDTLS_PRIVATE(p_entropy); /*!< context for the entropy function */ #if defined(MBEDTLS_THREADING_C) /* Invariant: the mutex is initialized if and only if * md_ctx->md_info != NULL. This means that the mutex is initialized * during the initial seeding in mbedtls_hmac_drbg_seed() or * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free(). * * Note that this invariant may change without notice. Do not rely on it * and do not access the mutex directly in application code. */ mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif } mbedtls_hmac_drbg_context; /** * \brief HMAC_DRBG context initialization. * * This function makes the context ready for mbedtls_hmac_drbg_seed(), * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). * * \note The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL * by default. Override this value by calling * mbedtls_hmac_drbg_set_reseed_interval(). * * \param ctx HMAC_DRBG context to be initialized. */ void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx); /** * \brief HMAC_DRBG initial seeding. * * Set the initial seed and set up the entropy source for future reseeds. * * A typical choice for the \p f_entropy and \p p_entropy parameters is * to use the entropy module: * - \p f_entropy is mbedtls_entropy_func(); * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized * with mbedtls_entropy_init() (which registers the platform's default * entropy sources). * * You can provide a personalization string in addition to the * entropy source, to make this instantiation as unique as possible. * * \note By default, the security strength as defined by NIST is: * - 128 bits if \p md_info is SHA-1; * - 192 bits if \p md_info is SHA-224; * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512. * Note that SHA-256 is just as efficient as SHA-224. * The security strength can be reduced if a smaller * entropy length is set with * mbedtls_hmac_drbg_set_entropy_len(). * * \note The default entropy length is the security strength * (converted from bits to bytes). You can override * it by calling mbedtls_hmac_drbg_set_entropy_len(). * * \note During the initial seeding, this function calls * the entropy source to obtain a nonce * whose length is half the entropy length. */ #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * after this function returns successfully, * it is safe to call mbedtls_hmac_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * \param ctx HMAC_DRBG context to be seeded. * \param md_info MD algorithm to use for HMAC_DRBG. * \param f_entropy The entropy callback, taking as arguments the * \p p_entropy context, the buffer to fill, and the * length of the buffer. * \p f_entropy is always called with a length that is * less than or equal to the entropy length. * \param p_entropy The entropy context to pass to \p f_entropy. * \param custom The personalization string. * This can be \c NULL, in which case the personalization * string is empty regardless of the value of \p len. * \param len The length of the personalization string. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT * and also at most * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \c entropy_len * 3 / 2 * where \c entropy_len is the entropy length * described above. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is * invalid. * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough * memory to allocate context data. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED * if the call to \p f_entropy failed. */ int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx, const mbedtls_md_info_t *md_info, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len); /** * \brief Initialisation of simplified HMAC_DRBG (never reseeds). * * This function is meant for use in algorithms that need a pseudorandom * input such as deterministic ECDSA. */ #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * after this function returns successfully, * it is safe to call mbedtls_hmac_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * \param ctx HMAC_DRBG context to be initialised. * \param md_info MD algorithm to use for HMAC_DRBG. * \param data Concatenation of the initial entropy string and * the additional data. * \param data_len Length of \p data in bytes. * * \return \c 0 if successful. or * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is * invalid. * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough * memory to allocate context data. */ int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx, const mbedtls_md_info_t *md_info, const unsigned char *data, size_t data_len); /** * \brief This function turns prediction resistance on or off. * The default value is off. * * \note If enabled, entropy is gathered at the beginning of * every call to mbedtls_hmac_drbg_random_with_add() * or mbedtls_hmac_drbg_random(). * Only use this if your entropy source has sufficient * throughput. * * \param ctx The HMAC_DRBG context. * \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF. */ void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx, int resistance); /** * \brief This function sets the amount of entropy grabbed on each * seed or reseed. * * See the documentation of mbedtls_hmac_drbg_seed() for the default value. * * \param ctx The HMAC_DRBG context. * \param len The amount of entropy to grab, in bytes. */ void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len); /** * \brief Set the reseed interval. * * The reseed interval is the number of calls to mbedtls_hmac_drbg_random() * or mbedtls_hmac_drbg_random_with_add() after which the entropy function * is called again. * * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL. * * \param ctx The HMAC_DRBG context. * \param interval The reseed interval. */ void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval); /** * \brief This function updates the state of the HMAC_DRBG context. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param ctx The HMAC_DRBG context. * \param additional The data to update the state with. * If this is \c NULL, there is no additional data. * \param add_len Length of \p additional in bytes. * Unused if \p additional is \c NULL. * * \return \c 0 on success, or an error from the underlying * hash calculation. */ int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t add_len); /** * \brief This function reseeds the HMAC_DRBG context, that is * extracts data from the entropy source. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param ctx The HMAC_DRBG context. * \param additional Additional data to add to the state. * If this is \c NULL, there is no additional data * and \p len should be \c 0. * \param len The length of the additional data. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT * and also at most * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \c entropy_len * where \c entropy_len is the entropy length * (see mbedtls_hmac_drbg_set_entropy_len()). * * \return \c 0 if successful. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED * if a call to the entropy function failed. */ int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t len); /** * \brief This function updates an HMAC_DRBG instance with additional * data and uses it to generate random data. * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param p_rng The HMAC_DRBG context. This must be a pointer to a * #mbedtls_hmac_drbg_context structure. * \param output The buffer to fill. * \param output_len The length of the buffer in bytes. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. * \param additional Additional data to update with. * If this is \c NULL, there is no additional data * and \p add_len should be \c 0. * \param add_len The length of the additional data. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED * if a call to the entropy source failed. * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT. */ int mbedtls_hmac_drbg_random_with_add(void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len); /** * \brief This function uses HMAC_DRBG to generate random data. * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. */ #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * it is safe to call mbedtls_ctr_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * \param p_rng The HMAC_DRBG context. This must be a pointer to a * #mbedtls_hmac_drbg_context structure. * \param output The buffer to fill. * \param out_len The length of the buffer in bytes. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED * if a call to the entropy source failed. * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. */ int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len); /** * \brief This function resets HMAC_DRBG context to the state immediately * after initial call of mbedtls_hmac_drbg_init(). * * \param ctx The HMAC_DRBG context to free. */ void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx); #if defined(MBEDTLS_FS_IO) /** * \brief This function writes a seed file. * * \param ctx The HMAC_DRBG context. * \param path The name of the file. * * \return \c 0 on success. * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed * failure. */ int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path); /** * \brief This function reads and updates a seed file. The seed * is added to this instance. * * \param ctx The HMAC_DRBG context. * \param path The name of the file. * * \return \c 0 on success. * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on * reseed failure. * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing * seed file is too large. */ int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /** * \brief The HMAC_DRBG Checkup routine. * * \return \c 0 if successful. * \return \c 1 if the test failed. */ int mbedtls_hmac_drbg_self_test(int verbose); #endif #ifdef __cplusplus } #endif #endif /* hmac_drbg.h */ webfakes/src/mbedtls/include/mbedtls/build_info.h0000644000176200001440000001402314740737024021632 0ustar liggesusers/** * \file mbedtls/build_info.h * * \brief Build-time configuration info * * Include this file if you need to depend on the * configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BUILD_INFO_H #define MBEDTLS_BUILD_INFO_H /* * This set of compile-time defines can be used to determine the version number * of the Mbed TLS library used. Run-time variables for the same can be found in * version.h */ /** * The version number x.y.z is split into three parts. * Major, Minor, Patchlevel */ #define MBEDTLS_VERSION_MAJOR 3 #define MBEDTLS_VERSION_MINOR 6 #define MBEDTLS_VERSION_PATCH 2 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ #define MBEDTLS_VERSION_NUMBER 0x03060200 #define MBEDTLS_VERSION_STRING "3.6.2" #define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.6.2" /* Macros for build-time platform detection */ #if !defined(MBEDTLS_ARCH_IS_ARM64) && \ (defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) #define MBEDTLS_ARCH_IS_ARM64 #endif #if !defined(MBEDTLS_ARCH_IS_ARM32) && \ (defined(__arm__) || defined(_M_ARM) || \ defined(_M_ARMT) || defined(__thumb__) || defined(__thumb2__)) #define MBEDTLS_ARCH_IS_ARM32 #endif #if !defined(MBEDTLS_ARCH_IS_X64) && \ (defined(__amd64__) || defined(__x86_64__) || \ ((defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC))) #define MBEDTLS_ARCH_IS_X64 #endif #if !defined(MBEDTLS_ARCH_IS_X86) && \ (defined(__i386__) || defined(_X86_) || \ (defined(_M_IX86) && !defined(_M_I86))) #define MBEDTLS_ARCH_IS_X86 #endif #if !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ (defined(_M_ARM64) || defined(_M_ARM64EC)) #define MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64 #endif /* This is defined if the architecture is Armv8-A, or higher */ #if !defined(MBEDTLS_ARCH_IS_ARMV8_A) #if defined(__ARM_ARCH) && defined(__ARM_ARCH_PROFILE) #if (__ARM_ARCH >= 8) && (__ARM_ARCH_PROFILE == 'A') /* GCC, clang, armclang and IAR */ #define MBEDTLS_ARCH_IS_ARMV8_A #endif #elif defined(__ARM_ARCH_8A) /* Alternative defined by clang */ #define MBEDTLS_ARCH_IS_ARMV8_A #elif defined(_M_ARM64) || defined(_M_ARM64EC) /* MSVC ARM64 is at least Armv8.0-A */ #define MBEDTLS_ARCH_IS_ARMV8_A #endif #endif #if defined(__GNUC__) && !defined(__ARMCC_VERSION) && !defined(__clang__) \ && !defined(__llvm__) && !defined(__INTEL_COMPILER) /* Defined if the compiler really is gcc and not clang, etc */ #define MBEDTLS_COMPILER_IS_GCC #define MBEDTLS_GCC_VERSION \ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #endif #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) #define _CRT_SECURE_NO_DEPRECATE 1 #endif /* Define `inline` on some non-C99-compliant compilers. */ #if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ !defined(inline) && !defined(__cplusplus) #define inline __inline #endif #if defined(MBEDTLS_CONFIG_FILES_READ) #error "Something went wrong: MBEDTLS_CONFIG_FILES_READ defined before reading the config files!" #endif #if defined(MBEDTLS_CONFIG_IS_FINALIZED) #error "Something went wrong: MBEDTLS_CONFIG_IS_FINALIZED defined before reading the config files!" #endif /* X.509, TLS and non-PSA crypto configuration */ #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/mbedtls_config.h" #else #include MBEDTLS_CONFIG_FILE #endif #if defined(MBEDTLS_CONFIG_VERSION) && ( \ MBEDTLS_CONFIG_VERSION < 0x03000000 || \ MBEDTLS_CONFIG_VERSION > MBEDTLS_VERSION_NUMBER) #error "Invalid config version, defined value of MBEDTLS_CONFIG_VERSION is unsupported" #endif /* Target and application specific configurations * * Allow user to override any previous default. * */ #if defined(MBEDTLS_USER_CONFIG_FILE) #include MBEDTLS_USER_CONFIG_FILE #endif /* PSA crypto configuration */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) #if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE) #include MBEDTLS_PSA_CRYPTO_CONFIG_FILE #else #include "psa/crypto_config.h" #endif #if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE) #include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE #endif #endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */ /* Indicate that all configuration files have been read. * It is now time to adjust the configuration (follow through on dependencies, * make PSA and legacy crypto consistent, etc.). */ #define MBEDTLS_CONFIG_FILES_READ /* Auto-enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY if * MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH and MBEDTLS_CTR_DRBG_C defined * to ensure a 128-bit key size in CTR_DRBG. */ #if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && defined(MBEDTLS_CTR_DRBG_C) #define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY #endif /* Auto-enable MBEDTLS_MD_C if needed by a module that didn't require it * in a previous release, to ensure backwards compatibility. */ #if defined(MBEDTLS_PKCS5_C) #define MBEDTLS_MD_C #endif /* PSA crypto specific configuration options * - If config_psa.h reads a configuration option in preprocessor directive, * this symbol should be set before its inclusion. (e.g. MBEDTLS_MD_C) * - If config_psa.h writes a configuration option in conditional directive, * this symbol should be consulted after its inclusion. * (e.g. MBEDTLS_MD_LIGHT) */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* PSA_WANT_xxx influences MBEDTLS_xxx */ || \ defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */ || \ defined(MBEDTLS_PSA_CRYPTO_CLIENT) /* The same as the previous, but with separation only */ #include "mbedtls/config_psa.h" #endif #include "mbedtls/config_adjust_legacy_crypto.h" #include "mbedtls/config_adjust_x509.h" #include "mbedtls/config_adjust_ssl.h" /* Indicate that all configuration symbols are set, * even the ones that are calculated programmatically. * It is now safe to query the configuration (to check it, to size buffers, * etc.). */ #define MBEDTLS_CONFIG_IS_FINALIZED #include "mbedtls/check_config.h" #endif /* MBEDTLS_BUILD_INFO_H */ webfakes/src/mbedtls/include/mbedtls/asn1write.h0000644000176200001440000004025414740737024021442 0ustar liggesusers/** * \file asn1write.h * * \brief ASN.1 buffer writing functionality */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ASN1_WRITE_H #define MBEDTLS_ASN1_WRITE_H #include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #define MBEDTLS_ASN1_CHK_ADD(g, f) \ do \ { \ if ((ret = (f)) < 0) \ return ret; \ else \ (g) += ret; \ } while (0) #define MBEDTLS_ASN1_CHK_CLEANUP_ADD(g, f) \ do \ { \ if ((ret = (f)) < 0) \ goto cleanup; \ else \ (g) += ret; \ } while (0) #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** * \brief Write a length field in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param len The length value to write. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len); /** * \brief Write an ASN.1 tag in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param tag The tag to write. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag); #endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA*/ #if defined(MBEDTLS_ASN1_WRITE_C) /** * \brief Write raw buffer data. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param buf The data buffer to write. * \param size The length of the data buffer. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size); #if defined(MBEDTLS_BIGNUM_C) /** * \brief Write an arbitrary-precision number (#MBEDTLS_ASN1_INTEGER) * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param X The MPI to write. * It must be non-negative. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X); #endif /* MBEDTLS_BIGNUM_C */ /** * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start); /** * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param oid The OID to write. * \param oid_len The length of the OID. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len); /** * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param oid The OID of the algorithm to write. * \param oid_len The length of the algorithm's OID. * \param par_len The length of the parameters, which must be already written. * If 0, NULL parameters are added * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len); /** * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param oid The OID of the algorithm to write. * \param oid_len The length of the algorithm's OID. * \param par_len The length of the parameters, which must be already written. * \param has_par If there are any parameters. If 0, par_len must be 0. If 1 * and \p par_len is 0, NULL parameters are added. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len, int has_par); /** * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param boolean The boolean value to write, either \c 0 or \c 1. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean); /** * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param val The integer value to write. * It must be non-negative. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val); /** * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param val The integer value to write. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val); /** * \brief Write a string in ASN.1 format using a specific * string encoding tag. * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param tag The string encoding tag to write, e.g. * #MBEDTLS_ASN1_UTF8_STRING. * \param text The string to write. * \param text_len The length of \p text in bytes (which might * be strictly larger than the number of characters). * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag, const char *text, size_t text_len); /** * \brief Write a string in ASN.1 format using the PrintableString * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param text The string to write. * \param text_len The length of \p text in bytes (which might * be strictly larger than the number of characters). * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); /** * \brief Write a UTF8 string in ASN.1 format using the UTF8String * string encoding tag (#MBEDTLS_ASN1_UTF8_STRING). * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param text The string to write. * \param text_len The length of \p text in bytes (which might * be strictly larger than the number of characters). * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); /** * \brief Write a string in ASN.1 format using the IA5String * string encoding tag (#MBEDTLS_ASN1_IA5_STRING). * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param text The string to write. * \param text_len The length of \p text in bytes (which might * be strictly larger than the number of characters). * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); /** * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and * value in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param buf The bitstring to write. * \param bits The total number of bits in the bitstring. * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits); /** * \brief This function writes a named bitstring tag * (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format. * * As stated in RFC 5280 Appendix B, trailing zeroes are * omitted when encoding named bitstrings in DER. * * \note This function works backwards within the data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer which is used for bounds-checking. * \param buf The bitstring to write. * \param bits The total number of bits in the bitstring. * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_named_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits); /** * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) * and value in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param buf The buffer holding the data to write. * \param size The length of the data buffer \p buf. * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size); /** * \brief Create or find a specific named_data entry for writing in a * sequence or list based on the OID. If not already in there, * a new entry is added to the head of the list. * Warning: Destructive behaviour for the val data! * * \param list The pointer to the location of the head of the list to seek * through (will be updated in case of a new entry). * \param oid The OID to look for. * \param oid_len The size of the OID. * \param val The associated data to store. If this is \c NULL, * no data is copied to the new or existing buffer. * \param val_len The minimum length of the data buffer needed. * If this is 0, do not allocate a buffer for the associated * data. * If the OID was already present, enlarge, shrink or free * the existing buffer to fit \p val_len. * * \return A pointer to the new / existing entry on success. * \return \c NULL if there was a memory allocation error. */ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(mbedtls_asn1_named_data **list, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len); #ifdef __cplusplus } #endif #endif /* MBEDTLS_ASN1_WRITE_C */ #endif /* MBEDTLS_ASN1_WRITE_H */ webfakes/src/mbedtls/include/mbedtls/sha1.h0000644000176200001440000001651514740737024020364 0ustar liggesusers/** * \file sha1.h * * \brief This file contains SHA-1 definitions and functions. * * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in * FIPS 180-4: Secure Hash Standard (SHS). * * \warning SHA-1 is considered a weak message digest and its use constitutes * a security risk. We recommend considering stronger message * digests instead. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA1_H #define MBEDTLS_SHA1_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** SHA-1 input data was malformed. */ #define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_SHA1_ALT) // Regular implementation // /** * \brief The SHA-1 context structure. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ typedef struct mbedtls_sha1_context { uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< The intermediate digest state. */ unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ } mbedtls_sha1_context; #else /* MBEDTLS_SHA1_ALT */ #include "sha1_alt.h" #endif /* MBEDTLS_SHA1_ALT */ /** * \brief This function initializes a SHA-1 context. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to initialize. * This must not be \c NULL. * */ void mbedtls_sha1_init(mbedtls_sha1_context *ctx); /** * \brief This function clears a SHA-1 context. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to clear. This may be \c NULL, * in which case this function does nothing. If it is * not \c NULL, it must point to an initialized * SHA-1 context. * */ void mbedtls_sha1_free(mbedtls_sha1_context *ctx); /** * \brief This function clones the state of a SHA-1 context. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param dst The SHA-1 context to clone to. This must be initialized. * \param src The SHA-1 context to clone from. This must be initialized. * */ void mbedtls_sha1_clone(mbedtls_sha1_context *dst, const mbedtls_sha1_context *src); /** * \brief This function starts a SHA-1 checksum calculation. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to initialize. This must be initialized. * * \return \c 0 on success. * \return A negative error code on failure. * */ int mbedtls_sha1_starts(mbedtls_sha1_context *ctx); /** * \brief This function feeds an input buffer into an ongoing SHA-1 * checksum calculation. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context. This must be initialized * and have a hash operation started. * \param input The buffer holding the input data. * This must be a readable buffer of length \p ilen Bytes. * \param ilen The length of the input data \p input in Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the SHA-1 operation, and writes * the result to the output buffer. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to use. This must be initialized and * have a hash operation started. * \param output The SHA-1 checksum result. This must be a writable * buffer of length \c 20 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20]); /** * \brief SHA-1 process data block (internal use only). * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to use. This must be initialized. * \param data The data block being processed. This must be a * readable buffer of length \c 64 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. * */ int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64]); /** * \brief This function calculates the SHA-1 checksum of a buffer. * * The function allocates the context, performs the * calculation, and frees the context. * * The SHA-1 result is calculated as * output = SHA-1(input buffer). * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param input The buffer holding the input data. * This must be a readable buffer of length \p ilen Bytes. * \param ilen The length of the input data \p input in Bytes. * \param output The SHA-1 checksum result. * This must be a writable buffer of length \c 20 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. * */ int mbedtls_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]); #if defined(MBEDTLS_SELF_TEST) /** * \brief The SHA-1 checkup routine. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \return \c 0 on success. * \return \c 1 on failure. * */ int mbedtls_sha1_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_sha1.h */ webfakes/src/mbedtls/include/mbedtls/chachapoly.h0000644000176200001440000003635514740737024021647 0ustar liggesusers/** * \file chachapoly.h * * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and * functions. * * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption * with Associated Data (AEAD) that can be used to encrypt and * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel * Bernstein and was standardized in RFC 7539. * * \author Daniel King */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CHACHAPOLY_H #define MBEDTLS_CHACHAPOLY_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" /* for shared error codes */ #include "mbedtls/poly1305.h" /** The requested operation is not permitted in the current state. */ #define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /** Authenticated decryption failed: data was not authentic. */ #define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 #ifdef __cplusplus extern "C" { #endif typedef enum { MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ } mbedtls_chachapoly_mode_t; #if !defined(MBEDTLS_CHACHAPOLY_ALT) #include "mbedtls/chacha20.h" typedef struct mbedtls_chachapoly_context { mbedtls_chacha20_context MBEDTLS_PRIVATE(chacha20_ctx); /**< The ChaCha20 context. */ mbedtls_poly1305_context MBEDTLS_PRIVATE(poly1305_ctx); /**< The Poly1305 context. */ uint64_t MBEDTLS_PRIVATE(aad_len); /**< The length (bytes) of the Additional Authenticated Data. */ uint64_t MBEDTLS_PRIVATE(ciphertext_len); /**< The length (bytes) of the ciphertext. */ int MBEDTLS_PRIVATE(state); /**< The current state of the context. */ mbedtls_chachapoly_mode_t MBEDTLS_PRIVATE(mode); /**< Cipher mode (encrypt or decrypt). */ } mbedtls_chachapoly_context; #else /* !MBEDTLS_CHACHAPOLY_ALT */ #include "chachapoly_alt.h" #endif /* !MBEDTLS_CHACHAPOLY_ALT */ /** * \brief This function initializes the specified ChaCha20-Poly1305 context. * * It must be the first API called before using * the context. It must be followed by a call to * \c mbedtls_chachapoly_setkey() before any operation can be * done, and to \c mbedtls_chachapoly_free() once all * operations with that context have been finished. * * In order to encrypt or decrypt full messages at once, for * each message you should make a single call to * \c mbedtls_chachapoly_crypt_and_tag() or * \c mbedtls_chachapoly_auth_decrypt(). * * In order to encrypt messages piecewise, for each * message you should make a call to * \c mbedtls_chachapoly_starts(), then 0 or more calls to * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to * \c mbedtls_chachapoly_update(), then one call to * \c mbedtls_chachapoly_finish(). * * \warning Decryption with the piecewise API is discouraged! Always * use \c mbedtls_chachapoly_auth_decrypt() when possible! * * If however this is not possible because the data is too * large to fit in memory, you need to: * * - call \c mbedtls_chachapoly_starts() and (if needed) * \c mbedtls_chachapoly_update_aad() as above, * - call \c mbedtls_chachapoly_update() multiple times and * ensure its output (the plaintext) is NOT used in any other * way than placing it in temporary storage at this point, * - call \c mbedtls_chachapoly_finish() to compute the * authentication tag and compared it in constant time to the * tag received with the ciphertext. * * If the tags are not equal, you must immediately discard * all previous outputs of \c mbedtls_chachapoly_update(), * otherwise you can now safely use the plaintext. * * \param ctx The ChachaPoly context to initialize. Must not be \c NULL. */ void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx); /** * \brief This function releases and clears the specified * ChaCha20-Poly1305 context. * * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which * case this function is a no-op. */ void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx); /** * \brief This function sets the ChaCha20-Poly1305 * symmetric encryption key. * * \param ctx The ChaCha20-Poly1305 context to which the key should be * bound. This must be initialized. * \param key The \c 256 Bit (\c 32 Bytes) key. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx, const unsigned char key[32]); /** * \brief This function starts a ChaCha20-Poly1305 encryption or * decryption operation. * * \warning You must never use the same nonce twice with the same key. * This would void any confidentiality and authenticity * guarantees for the messages encrypted with the same nonce * and key. * * \note If the context is being used for AAD only (no data to * encrypt or decrypt) then \p mode can be set to any value. * * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * * \param ctx The ChaCha20-Poly1305 context. This must be initialized * and bound to a key. * \param nonce The nonce/IV to use for the message. * This must be a readable buffer of length \c 12 Bytes. * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx, const unsigned char nonce[12], mbedtls_chachapoly_mode_t mode); /** * \brief This function feeds additional data to be authenticated * into an ongoing ChaCha20-Poly1305 operation. * * The Additional Authenticated Data (AAD), also called * Associated Data (AD) is only authenticated but not * encrypted nor included in the encrypted output. It is * usually transmitted separately from the ciphertext or * computed locally by each party. * * \note This function is called before data is encrypted/decrypted. * I.e. call this function to process the AAD before calling * \c mbedtls_chachapoly_update(). * * You may call this function multiple times to process * an arbitrary amount of AAD. It is permitted to call * this function 0 times, if no AAD is used. * * This function cannot be called any more if data has * been processed by \c mbedtls_chachapoly_update(), * or if the context has been finished. * * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * * \param ctx The ChaCha20-Poly1305 context. This must be initialized * and bound to a key. * \param aad_len The length in Bytes of the AAD. The length has no * restrictions. * \param aad Buffer containing the AAD. * This pointer can be \c NULL if `aad_len == 0`. * * \return \c 0 on success. * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA * if \p ctx or \p aad are NULL. * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE * if the operations has not been started or has been * finished, or if the AAD has been finished. */ int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx, const unsigned char *aad, size_t aad_len); /** * \brief Thus function feeds data to be encrypted or decrypted * into an on-going ChaCha20-Poly1305 * operation. * * The direction (encryption or decryption) depends on the * mode that was given when calling * \c mbedtls_chachapoly_starts(). * * You may call this function multiple times to process * an arbitrary amount of data. It is permitted to call * this function 0 times, if no data is to be encrypted * or decrypted. * * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. * \param len The length (in bytes) of the data to encrypt or decrypt. * \param input The buffer containing the data to encrypt or decrypt. * This pointer can be \c NULL if `len == 0`. * \param output The buffer to where the encrypted or decrypted data is * written. This must be able to hold \p len bytes. * This pointer can be \c NULL if `len == 0`. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE * if the operation has not been started or has been * finished. * \return Another negative error code on other kinds of failure. */ int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx, size_t len, const unsigned char *input, unsigned char *output); /** * \brief This function finished the ChaCha20-Poly1305 operation and * generates the MAC (authentication tag). * * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. * * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE * if the operation has not been started or has been * finished. * \return Another negative error code on other kinds of failure. */ int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx, unsigned char mac[16]); /** * \brief This function performs a complete ChaCha20-Poly1305 * authenticated encryption with the previously-set key. * * \note Before using this function, you must set the key with * \c mbedtls_chachapoly_setkey(). * * \warning You must never use the same nonce twice with the same key. * This would void any confidentiality and authenticity * guarantees for the messages encrypted with the same nonce * and key. * * \param ctx The ChaCha20-Poly1305 context to use (holds the key). * This must be initialized. * \param length The length (in bytes) of the data to encrypt or decrypt. * \param nonce The 96-bit (12 bytes) nonce/IV to use. * \param aad The buffer containing the additional authenticated * data (AAD). This pointer can be \c NULL if `aad_len == 0`. * \param aad_len The length (in bytes) of the AAD data to process. * \param input The buffer containing the data to encrypt or decrypt. * This pointer can be \c NULL if `ilen == 0`. * \param output The buffer to where the encrypted or decrypted data * is written. This pointer can be \c NULL if `ilen == 0`. * \param tag The buffer to where the computed 128-bit (16 bytes) MAC * is written. This must not be \c NULL. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char *input, unsigned char *output, unsigned char tag[16]); /** * \brief This function performs a complete ChaCha20-Poly1305 * authenticated decryption with the previously-set key. * * \note Before using this function, you must set the key with * \c mbedtls_chachapoly_setkey(). * * \param ctx The ChaCha20-Poly1305 context to use (holds the key). * \param length The length (in Bytes) of the data to decrypt. * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use. * \param aad The buffer containing the additional authenticated data (AAD). * This pointer can be \c NULL if `aad_len == 0`. * \param aad_len The length (in bytes) of the AAD data to process. * \param tag The buffer holding the authentication tag. * This must be a readable buffer of length \c 16 Bytes. * \param input The buffer containing the data to decrypt. * This pointer can be \c NULL if `ilen == 0`. * \param output The buffer to where the decrypted data is written. * This pointer can be \c NULL if `ilen == 0`. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED * if the data was not authentic. * \return Another negative error code on other kinds of failure. */ int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char tag[16], const unsigned char *input, unsigned char *output); #if defined(MBEDTLS_SELF_TEST) /** * \brief The ChaCha20-Poly1305 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_chachapoly_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CHACHAPOLY_H */ webfakes/src/mbedtls/include/mbedtls/sha512.h0000644000176200001440000001620614740737024020530 0ustar liggesusers/** * \file sha512.h * \brief This file contains SHA-384 and SHA-512 definitions and functions. * * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA512_H #define MBEDTLS_SHA512_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** SHA-512 input data was malformed. */ #define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_SHA512_ALT) // Regular implementation // /** * \brief The SHA-512 context structure. * * The structure is used both for SHA-384 and for SHA-512 * checksum calculations. The choice between these two is * made in the call to mbedtls_sha512_starts(). */ typedef struct mbedtls_sha512_context { uint64_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ uint64_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ unsigned char MBEDTLS_PRIVATE(buffer)[128]; /*!< The data block being processed. */ #if defined(MBEDTLS_SHA384_C) int MBEDTLS_PRIVATE(is384); /*!< Determines which function to use: 0: Use SHA-512, or 1: Use SHA-384. */ #endif } mbedtls_sha512_context; #else /* MBEDTLS_SHA512_ALT */ #include "sha512_alt.h" #endif /* MBEDTLS_SHA512_ALT */ /** * \brief This function initializes a SHA-512 context. * * \param ctx The SHA-512 context to initialize. This must * not be \c NULL. */ void mbedtls_sha512_init(mbedtls_sha512_context *ctx); /** * \brief This function clears a SHA-512 context. * * \param ctx The SHA-512 context to clear. This may be \c NULL, * in which case this function does nothing. If it * is not \c NULL, it must point to an initialized * SHA-512 context. */ void mbedtls_sha512_free(mbedtls_sha512_context *ctx); /** * \brief This function clones the state of a SHA-512 context. * * \param dst The destination context. This must be initialized. * \param src The context to clone. This must be initialized. */ void mbedtls_sha512_clone(mbedtls_sha512_context *dst, const mbedtls_sha512_context *src); /** * \brief This function starts a SHA-384 or SHA-512 checksum * calculation. * * \param ctx The SHA-512 context to use. This must be initialized. * \param is384 Determines which function to use. This must be * either \c 0 for SHA-512, or \c 1 for SHA-384. * * \note is384 must be defined accordingly to the enabled * MBEDTLS_SHA384_C/MBEDTLS_SHA512_C symbols otherwise the * function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384); /** * \brief This function feeds an input buffer into an ongoing * SHA-512 checksum calculation. * * \param ctx The SHA-512 context. This must be initialized * and have a hash operation started. * \param input The buffer holding the input data. This must * be a readable buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha512_update(mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the SHA-512 operation, and writes * the result to the output buffer. * * \param ctx The SHA-512 context. This must be initialized * and have a hash operation started. * \param output The SHA-384 or SHA-512 checksum result. * This must be a writable buffer of length \c 64 bytes * for SHA-512, \c 48 bytes for SHA-384. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha512_finish(mbedtls_sha512_context *ctx, unsigned char *output); /** * \brief This function processes a single data block within * the ongoing SHA-512 computation. * This function is for internal use only. * * \param ctx The SHA-512 context. This must be initialized. * \param data The buffer holding one block of data. This * must be a readable buffer of length \c 128 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[128]); /** * \brief This function calculates the SHA-512 or SHA-384 * checksum of a buffer. * * The function allocates the context, performs the * calculation, and frees the context. * * The SHA-512 result is calculated as * output = SHA-512(input buffer). * * \param input The buffer holding the input data. This must be * a readable buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * \param output The SHA-384 or SHA-512 checksum result. * This must be a writable buffer of length \c 64 bytes * for SHA-512, \c 48 bytes for SHA-384. * \param is384 Determines which function to use. This must be either * \c 0 for SHA-512, or \c 1 for SHA-384. * * \note is384 must be defined accordingly with the supported * symbols in the config file. If: * - is384 is 0, but \c MBEDTLS_SHA384_C is not defined, or * - is384 is 1, but \c MBEDTLS_SHA512_C is not defined * then the function will return * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha512(const unsigned char *input, size_t ilen, unsigned char *output, int is384); #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SHA384_C) /** * \brief The SHA-384 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha384_self_test(int verbose); #endif /* MBEDTLS_SHA384_C */ #if defined(MBEDTLS_SHA512_C) /** * \brief The SHA-512 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha512_self_test(int verbose); #endif /* MBEDTLS_SHA512_C */ #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_sha512.h */ webfakes/src/mbedtls/include/mbedtls/config_psa.h0000644000176200001440000000357414740737024021641 0ustar liggesusers/** * \file mbedtls/config_psa.h * \brief PSA crypto configuration options (set of defines) * * This set of compile-time options takes settings defined in * include/mbedtls/mbedtls_config.h and include/psa/crypto_config.h and uses * those definitions to define symbols used in the library code. * * Users and integrators should not edit this file, please edit * include/mbedtls/mbedtls_config.h for MBEDTLS_XXX settings or * include/psa/crypto_config.h for PSA_WANT_XXX settings. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_PSA_H #define MBEDTLS_CONFIG_PSA_H #include "psa/crypto_legacy.h" #include "psa/crypto_adjust_config_synonyms.h" #include "psa/crypto_adjust_config_dependencies.h" #include "mbedtls/config_adjust_psa_superset_legacy.h" #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* Require built-in implementations based on PSA requirements */ /* We need this to have a complete list of requirements * before we deduce what built-ins are required. */ #include "psa/crypto_adjust_config_key_pair_types.h" #if defined(MBEDTLS_PSA_CRYPTO_C) /* If we are implementing PSA crypto ourselves, then we want to enable the * required built-ins. Otherwise, PSA features will be provided by the server. */ #include "mbedtls/config_adjust_legacy_from_psa.h" #endif #else /* MBEDTLS_PSA_CRYPTO_CONFIG */ /* Infer PSA requirements from Mbed TLS capabilities */ #include "mbedtls/config_adjust_psa_from_legacy.h" /* Hopefully the file above will have enabled keypair symbols in a consistent * way, but including this here fixes them if that wasn't the case. */ #include "psa/crypto_adjust_config_key_pair_types.h" #endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ #if defined(PSA_WANT_ALG_JPAKE) #define PSA_WANT_ALG_SOME_PAKE 1 #endif #include "psa/crypto_adjust_auto_enabled.h" #endif /* MBEDTLS_CONFIG_PSA_H */ webfakes/src/mbedtls/include/mbedtls/chacha20.h0000644000176200001440000001710514740737024021075 0ustar liggesusers/** * \file chacha20.h * * \brief This file contains ChaCha20 definitions and functions. * * ChaCha20 is a stream cipher that can encrypt and decrypt * information. ChaCha was created by Daniel Bernstein as a variant of * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf * ChaCha20 is the variant with 20 rounds, that was also standardized * in RFC 7539. * * \author Daniel King */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CHACHA20_H #define MBEDTLS_CHACHA20_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** Invalid input parameter(s). */ #define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_CHACHA20_ALT) typedef struct mbedtls_chacha20_context { uint32_t MBEDTLS_PRIVATE(state)[16]; /*! The state (before round operations). */ uint8_t MBEDTLS_PRIVATE(keystream8)[64]; /*! Leftover keystream bytes. */ size_t MBEDTLS_PRIVATE(keystream_bytes_used); /*! Number of keystream bytes already used. */ } mbedtls_chacha20_context; #else /* MBEDTLS_CHACHA20_ALT */ #include "chacha20_alt.h" #endif /* MBEDTLS_CHACHA20_ALT */ /** * \brief This function initializes the specified ChaCha20 context. * * It must be the first API called before using * the context. * * It is usually followed by calls to * \c mbedtls_chacha20_setkey() and * \c mbedtls_chacha20_starts(), then one or more calls to * to \c mbedtls_chacha20_update(), and finally to * \c mbedtls_chacha20_free(). * * \param ctx The ChaCha20 context to initialize. * This must not be \c NULL. */ void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx); /** * \brief This function releases and clears the specified * ChaCha20 context. * * \param ctx The ChaCha20 context to clear. This may be \c NULL, * in which case this function is a no-op. If it is not * \c NULL, it must point to an initialized context. * */ void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx); /** * \brief This function sets the encryption/decryption key. * * \note After using this function, you must also call * \c mbedtls_chacha20_starts() to set a nonce before you * start encrypting/decrypting data with * \c mbedtls_chacha_update(). * * \param ctx The ChaCha20 context to which the key should be bound. * It must be initialized. * \param key The encryption/decryption key. This must be \c 32 Bytes * in length. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. */ int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx, const unsigned char key[32]); /** * \brief This function sets the nonce and initial counter value. * * \note A ChaCha20 context can be re-used with the same key by * calling this function to change the nonce. * * \warning You must never use the same nonce twice with the same key. * This would void any confidentiality guarantees for the * messages encrypted with the same nonce and key. * * \param ctx The ChaCha20 context to which the nonce should be bound. * It must be initialized and bound to a key. * \param nonce The nonce. This must be \c 12 Bytes in size. * \param counter The initial counter value. This is usually \c 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is * NULL. */ int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx, const unsigned char nonce[12], uint32_t counter); /** * \brief This function encrypts or decrypts data. * * Since ChaCha20 is a stream cipher, the same operation is * used for encrypting and decrypting data. * * \note The \p input and \p output pointers must either be equal or * point to non-overlapping buffers. * * \note \c mbedtls_chacha20_setkey() and * \c mbedtls_chacha20_starts() must be called at least once * to setup the context before this function can be called. * * \note This function can be called multiple times in a row in * order to encrypt of decrypt data piecewise with the same * key and nonce. * * \param ctx The ChaCha20 context to use for encryption or decryption. * It must be initialized and bound to a key and nonce. * \param size The length of the input data in Bytes. * \param input The buffer holding the input data. * This pointer can be \c NULL if `size == 0`. * \param output The buffer holding the output data. * This must be able to hold \p size Bytes. * This pointer can be \c NULL if `size == 0`. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx, size_t size, const unsigned char *input, unsigned char *output); /** * \brief This function encrypts or decrypts data with ChaCha20 and * the given key and nonce. * * Since ChaCha20 is a stream cipher, the same operation is * used for encrypting and decrypting data. * * \warning You must never use the same (key, nonce) pair more than * once. This would void any confidentiality guarantees for * the messages encrypted with the same nonce and key. * * \note The \p input and \p output pointers must either be equal or * point to non-overlapping buffers. * * \param key The encryption/decryption key. * This must be \c 32 Bytes in length. * \param nonce The nonce. This must be \c 12 Bytes in size. * \param counter The initial counter value. This is usually \c 0. * \param size The length of the input data in Bytes. * \param input The buffer holding the input data. * This pointer can be \c NULL if `size == 0`. * \param output The buffer holding the output data. * This must be able to hold \p size Bytes. * This pointer can be \c NULL if `size == 0`. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chacha20_crypt(const unsigned char key[32], const unsigned char nonce[12], uint32_t counter, size_t size, const unsigned char *input, unsigned char *output); #if defined(MBEDTLS_SELF_TEST) /** * \brief The ChaCha20 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_chacha20_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CHACHA20_H */ webfakes/src/mbedtls/include/mbedtls/x509_crl.h0000644000176200001440000001435014740737024021070 0ustar liggesusers/** * \file x509_crl.h * * \brief X.509 certificate revocation list parsing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_CRL_H #define MBEDTLS_X509_CRL_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/x509.h" #ifdef __cplusplus extern "C" { #endif /** * \addtogroup x509_module * \{ */ /** * \name Structures and functions for parsing CRLs * \{ */ /** * Certificate revocation list entry. * Contains the CA-specific serial numbers and revocation dates. * * Some fields of this structure are publicly readable. Do not modify * them except via Mbed TLS library functions: the effect of modifying * those fields or the data that those fields points to is unspecified. */ typedef struct mbedtls_x509_crl_entry { /** Direct access to the whole entry inside the containing buffer. */ mbedtls_x509_buf raw; /** The serial number of the revoked certificate. */ mbedtls_x509_buf serial; /** The revocation date of this entry. */ mbedtls_x509_time revocation_date; /** Direct access to the list of CRL entry extensions * (an ASN.1 constructed sequence). * * If there are no extensions, `entry_ext.len == 0` and * `entry_ext.p == NULL`. */ mbedtls_x509_buf entry_ext; /** Next element in the linked list of entries. * \p NULL indicates the end of the list. * Do not modify this field directly. */ struct mbedtls_x509_crl_entry *next; } mbedtls_x509_crl_entry; /** * Certificate revocation list structure. * Every CRL may have multiple entries. */ typedef struct mbedtls_x509_crl { mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ int version; /**< CRL version (1=v1, 2=v2) */ mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ mbedtls_x509_time this_update; mbedtls_x509_time next_update; mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ mbedtls_x509_buf crl_ext; mbedtls_x509_buf MBEDTLS_PRIVATE(sig_oid2); mbedtls_x509_buf MBEDTLS_PRIVATE(sig); mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ /** Next element in the linked list of CRL. * \p NULL indicates the end of the list. * Do not modify this field directly. */ struct mbedtls_x509_crl *next; } mbedtls_x509_crl; /** * \brief Parse a DER-encoded CRL and append it to the chained list * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain points to the start of the chain * \param buf buffer holding the CRL data in DER format * \param buflen size of the buffer * (including the terminating null byte for PEM data) * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen); /** * \brief Parse one or more CRLs and append them to the chained list * * \note Multiple CRLs are accepted only if using PEM format * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain points to the start of the chain * \param buf buffer holding the CRL data in PEM or DER format * \param buflen size of the buffer * (including the terminating null byte for PEM data) * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen); #if defined(MBEDTLS_FS_IO) /** * \brief Load one or more CRLs and append them to the chained list * * \note Multiple CRLs are accepted only if using PEM format * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain points to the start of the chain * \param path filename to read the CRLs from (in PEM or DER encoding) * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path); #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Returns an informational string about the CRL. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param prefix A line prefix * \param crl The X509 CRL to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crl *crl); #endif /* !MBEDTLS_X509_REMOVE_INFO */ /** * \brief Initialize a CRL (chain) * * \param crl CRL chain to initialize */ void mbedtls_x509_crl_init(mbedtls_x509_crl *crl); /** * \brief Unallocate all CRL data * * \param crl CRL chain to free */ void mbedtls_x509_crl_free(mbedtls_x509_crl *crl); /** \} name Structures and functions for parsing CRLs */ /** \} addtogroup x509_module */ #ifdef __cplusplus } #endif #endif /* mbedtls_x509_crl.h */ webfakes/src/mbedtls/include/mbedtls/ssl_cache.h0000644000176200001440000001374014740737024021451 0ustar liggesusers/** * \file ssl_cache.h * * \brief SSL session cache implementation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CACHE_H #define MBEDTLS_SSL_CACHE_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ssl.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) #define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ #endif #if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) #define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ #endif /** \} name SECTION: Module settings */ #ifdef __cplusplus extern "C" { #endif typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; /** * \brief This structure is used for storing cache entries */ struct mbedtls_ssl_cache_entry { #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t MBEDTLS_PRIVATE(timestamp); /*!< entry timestamp */ #endif unsigned char MBEDTLS_PRIVATE(session_id)[32]; /*!< session ID */ size_t MBEDTLS_PRIVATE(session_id_len); unsigned char *MBEDTLS_PRIVATE(session); /*!< serialized session */ size_t MBEDTLS_PRIVATE(session_len); mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(next); /*!< chain pointer */ }; /** * \brief Cache context */ struct mbedtls_ssl_cache_context { mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(chain); /*!< start of the chain */ int MBEDTLS_PRIVATE(timeout); /*!< cache entry timeout */ int MBEDTLS_PRIVATE(max_entries); /*!< maximum entries */ #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< mutex */ #endif }; /** * \brief Initialize an SSL cache context * * \param cache SSL cache context */ void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache); /** * \brief Cache get callback implementation * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param data The SSL cache context to use. * \param session_id The pointer to the buffer holding the session ID * for the session to load. * \param session_id_len The length of \p session_id in bytes. * \param session The address at which to store the session * associated with \p session_id, if present. * * \return \c 0 on success. * \return #MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND if there is * no cache entry with specified session ID found, or * any other negative error code for other failures. */ int mbedtls_ssl_cache_get(void *data, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_session *session); /** * \brief Cache set callback implementation * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param data The SSL cache context to use. * \param session_id The pointer to the buffer holding the session ID * associated to \p session. * \param session_id_len The length of \p session_id in bytes. * \param session The session to store. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_ssl_cache_set(void *data, unsigned char const *session_id, size_t session_id_len, const mbedtls_ssl_session *session); /** * \brief Remove the cache entry by the session ID * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param data The SSL cache context to use. * \param session_id The pointer to the buffer holding the session ID * associated to session. * \param session_id_len The length of \p session_id in bytes. * * \return \c 0 on success. This indicates the cache entry for * the session with provided ID is removed or does not * exist. * \return A negative error code on failure. */ int mbedtls_ssl_cache_remove(void *data, unsigned char const *session_id, size_t session_id_len); #if defined(MBEDTLS_HAVE_TIME) /** * \brief Set the cache timeout * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) * * A timeout of 0 indicates no timeout. * * \param cache SSL cache context * \param timeout cache entry timeout in seconds */ void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout); /** * \brief Get the cache timeout * * A timeout of 0 indicates no timeout. * * \param cache SSL cache context * * \return cache entry timeout in seconds */ static inline int mbedtls_ssl_cache_get_timeout(mbedtls_ssl_cache_context *cache) { return cache->MBEDTLS_PRIVATE(timeout); } #endif /* MBEDTLS_HAVE_TIME */ /** * \brief Set the maximum number of cache entries * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) * * \param cache SSL cache context * \param max cache entry maximum */ void mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max); /** * \brief Free referenced items in a cache context and clear memory * * \param cache SSL cache context */ void mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache); #ifdef __cplusplus } #endif #endif /* ssl_cache.h */ webfakes/src/mbedtls/include/mbedtls/ctr_drbg.h0000644000176200001440000006155114740737024021316 0ustar liggesusers/** * \file ctr_drbg.h * * \brief This file contains definitions and functions for the * CTR_DRBG pseudorandom generator. * * CTR_DRBG is a standardized way of building a PRNG from a block-cipher * in counter mode operation, as defined in NIST SP 800-90A: * Recommendation for Random Number Generation Using Deterministic Random * Bit Generators. * * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time) * as the underlying block cipher, with a derivation function. * * The security strength as defined in NIST SP 800-90A is * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is * kept at its default value (and not overridden in mbedtls_config.h) and that the * DRBG instance is set up with default parameters. * See the documentation of mbedtls_ctr_drbg_seed() for more * information. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CTR_DRBG_H #define MBEDTLS_CTR_DRBG_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" /* The CTR_DRBG implementation can either directly call the low-level AES * module (gated by MBEDTLS_AES_C) or call the PSA API to perform AES * operations. Calling the AES module directly is the default, both for * maximum backward compatibility and because it's a bit more efficient * (less glue code). * * When MBEDTLS_AES_C is disabled, the CTR_DRBG module calls PSA crypto and * thus benefits from the PSA AES accelerator driver. * It is technically possible to enable MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO * to use PSA even when MBEDTLS_AES_C is enabled, but there is very little * reason to do so other than testing purposes and this is not officially * supported. */ #if !defined(MBEDTLS_AES_C) #define MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO #endif #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) #include "psa/crypto.h" #else #include "mbedtls/aes.h" #endif #include "entropy.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /** The entropy source failed. */ #define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /** The requested random buffer length is too big. */ #define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /** The input (entropy + additional data) is too large. */ #define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /** Read or write error in file. */ #define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A #define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) #define MBEDTLS_CTR_DRBG_KEYSIZE 16 /**< The key size in bytes used by the cipher. * * Compile-time choice: 16 bytes (128 bits) * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled. */ #else #define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size in bytes used by the cipher. * * Compile-time choice: 32 bytes (256 bits) * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled. */ #endif #define MBEDTLS_CTR_DRBG_KEYBITS (MBEDTLS_CTR_DRBG_KEYSIZE * 8) /**< The key size for the DRBG operation, in bits. */ #define MBEDTLS_CTR_DRBG_SEEDLEN (MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE) /**< The seed length, calculated as (counter + AES key). */ /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them using the compiler command * line. * \{ */ /** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN * * \brief The amount of entropy used per seed by default, in bytes. */ #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) /** This is 48 bytes because the entropy module uses SHA-512. */ #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ /** This is 32 bytes because the entropy module uses SHA-256. */ #if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) /** \warning To achieve a 256-bit security strength, you must pass a nonce * to mbedtls_ctr_drbg_seed(). */ #endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */ #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ #endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) #define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< The interval before reseed is performed by default. */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) #define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< The maximum number of additional input Bytes. */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) #define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< The maximum number of requested Bytes per call. */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) #define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< The maximum size of seed or reseed buffer in bytes. */ #endif /** \} name SECTION: Module settings */ #define MBEDTLS_CTR_DRBG_PR_OFF 0 /**< Prediction resistance is disabled. */ #define MBEDTLS_CTR_DRBG_PR_ON 1 /**< Prediction resistance is enabled. */ #ifdef __cplusplus extern "C" { #endif #if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 /** The default length of the nonce read from the entropy source. * * This is \c 0 because a single read from the entropy source is sufficient * to include a nonce. * See the documentation of mbedtls_ctr_drbg_seed() for more information. */ #define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0 #else /** The default length of the nonce read from the entropy source. * * This is half of the default entropy length because a single read from * the entropy source does not provide enough material to form a nonce. * See the documentation of mbedtls_ctr_drbg_seed() for more information. */ #define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN (MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1) / 2 #endif #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) typedef struct mbedtls_ctr_drbg_psa_context { mbedtls_svc_key_id_t key_id; psa_cipher_operation_t operation; } mbedtls_ctr_drbg_psa_context; #endif /** * \brief The CTR_DRBG context structure. */ typedef struct mbedtls_ctr_drbg_context { unsigned char MBEDTLS_PRIVATE(counter)[16]; /*!< The counter (V). */ int MBEDTLS_PRIVATE(reseed_counter); /*!< The reseed counter. * This is the number of requests that have * been made since the last (re)seeding, * minus one. * Before the initial seeding, this field * contains the amount of entropy in bytes * to use as a nonce for the initial seeding, * or -1 if no nonce length has been explicitly * set (see mbedtls_ctr_drbg_set_nonce_len()). */ int MBEDTLS_PRIVATE(prediction_resistance); /*!< This determines whether prediction resistance is enabled, that is whether to systematically reseed before each random generation. */ size_t MBEDTLS_PRIVATE(entropy_len); /*!< The amount of entropy grabbed on each seed or reseed operation, in bytes. */ int MBEDTLS_PRIVATE(reseed_interval); /*!< The reseed interval. * This is the maximum number of requests * that can be made between reseedings. */ #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) mbedtls_ctr_drbg_psa_context MBEDTLS_PRIVATE(psa_ctx); /*!< The PSA context. */ #else mbedtls_aes_context MBEDTLS_PRIVATE(aes_ctx); /*!< The AES context. */ #endif /* * Callbacks (Entropy) */ int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); /*!< The entropy callback function. */ void *MBEDTLS_PRIVATE(p_entropy); /*!< The context for the entropy function. */ #if defined(MBEDTLS_THREADING_C) /* Invariant: the mutex is initialized if and only if f_entropy != NULL. * This means that the mutex is initialized during the initial seeding * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free(). * * Note that this invariant may change without notice. Do not rely on it * and do not access the mutex directly in application code. */ mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif } mbedtls_ctr_drbg_context; /** * \brief This function initializes the CTR_DRBG context, * and prepares it for mbedtls_ctr_drbg_seed() * or mbedtls_ctr_drbg_free(). * * \note The reseed interval is * #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default. * You can override it by calling * mbedtls_ctr_drbg_set_reseed_interval(). * * \param ctx The CTR_DRBG context to initialize. */ void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx); /** * \brief This function seeds and sets up the CTR_DRBG * entropy source for future reseeds. * * A typical choice for the \p f_entropy and \p p_entropy parameters is * to use the entropy module: * - \p f_entropy is mbedtls_entropy_func(); * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized * with mbedtls_entropy_init() (which registers the platform's default * entropy sources). * * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). * * The entropy nonce length is: * - \c 0 if the entropy length is at least 3/2 times the entropy length, * which guarantees that the security strength is the maximum permitted * by the key size and entropy length according to NIST SP 800-90A §10.2.1; * - Half the entropy length otherwise. * You can override it by calling mbedtls_ctr_drbg_set_nonce_len(). * With the default entropy length, the entropy nonce length is * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN. * * You can provide a nonce and personalization string in addition to the * entropy source, to make this instantiation as unique as possible. * See SP 800-90A §8.6.7 for more details about nonces. * * The _seed_material_ value passed to the derivation function in * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2 * is the concatenation of the following strings: * - A string obtained by calling \p f_entropy function for the entropy * length. */ #if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0 /** * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string * obtained by calling \p f_entropy function for the specified length. */ #else /** * - A string obtained by calling \p f_entropy function for the entropy nonce * length. If the entropy nonce length is \c 0, this function does not * make a second call to \p f_entropy. */ #endif #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * after this function returns successfully, * it is safe to call mbedtls_ctr_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * - The \p custom string. * * \note To achieve the nominal security strength permitted * by CTR_DRBG, the entropy length must be: * - at least 16 bytes for a 128-bit strength * (maximum achievable strength when using AES-128); * - at least 32 bytes for a 256-bit strength * (maximum achievable strength when using AES-256). * * In addition, if you do not pass a nonce in \p custom, * the sum of the entropy length * and the entropy nonce length must be: * - at least 24 bytes for a 128-bit strength * (maximum achievable strength when using AES-128); * - at least 48 bytes for a 256-bit strength * (maximum achievable strength when using AES-256). * * \param ctx The CTR_DRBG context to seed. * It must have been initialized with * mbedtls_ctr_drbg_init(). * After a successful call to mbedtls_ctr_drbg_seed(), * you may not call mbedtls_ctr_drbg_seed() again on * the same context unless you call * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() * again first. * After a failed call to mbedtls_ctr_drbg_seed(), * you must call mbedtls_ctr_drbg_free(). * \param f_entropy The entropy callback, taking as arguments the * \p p_entropy context, the buffer to fill, and the * length of the buffer. * \p f_entropy is always called with a buffer size * less than or equal to the entropy length. * \param p_entropy The entropy context to pass to \p f_entropy. * \param custom The personalization string. * This can be \c NULL, in which case the personalization * string is empty regardless of the value of \p len. * \param len The length of the personalization string. * This must be at most * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. */ int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len); /** * \brief This function resets CTR_DRBG context to the state immediately * after initial call of mbedtls_ctr_drbg_init(). * * \param ctx The CTR_DRBG context to clear. */ void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx); /** * \brief This function turns prediction resistance on or off. * The default value is off. * * \note If enabled, entropy is gathered at the beginning of * every call to mbedtls_ctr_drbg_random_with_add() * or mbedtls_ctr_drbg_random(). * Only use this if your entropy source has sufficient * throughput. * * \param ctx The CTR_DRBG context. * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. */ void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx, int resistance); /** * \brief This function sets the amount of entropy grabbed on each * seed or reseed. * * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN. * * \note The security strength of CTR_DRBG is bounded by the * entropy length. Thus: * - When using AES-256 * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled, * which is the default), * \p len must be at least 32 (in bytes) * to achieve a 256-bit strength. * - When using AES-128 * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled) * \p len must be at least 16 (in bytes) * to achieve a 128-bit strength. * * \param ctx The CTR_DRBG context. * \param len The amount of entropy to grab, in bytes. * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT * and at most the maximum length accepted by the * entropy function that is set in the context. */ void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, size_t len); /** * \brief This function sets the amount of entropy grabbed * as a nonce for the initial seeding. * * Call this function before calling mbedtls_ctr_drbg_seed() to read * a nonce from the entropy source during the initial seeding. * * \param ctx The CTR_DRBG context. * \param len The amount of entropy to grab for the nonce, in bytes. * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT * and at most the maximum length accepted by the * entropy function that is set in the context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is * more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED * if the initial seeding has already taken place. */ int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx, size_t len); /** * \brief This function sets the reseed interval. * * The reseed interval is the number of calls to mbedtls_ctr_drbg_random() * or mbedtls_ctr_drbg_random_with_add() after which the entropy function * is called again. * * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. * * \param ctx The CTR_DRBG context. * \param interval The reseed interval. */ void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, int interval); /** * \brief This function reseeds the CTR_DRBG context, that is * extracts data from the entropy source. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param ctx The CTR_DRBG context. * \param additional Additional data to add to the state. Can be \c NULL. * \param len The length of the additional data. * This must be less than * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len * where \c entropy_len is the entropy length * configured for the context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. */ int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len); /** * \brief This function updates the state of the CTR_DRBG context. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param ctx The CTR_DRBG context. * \param additional The data to update the state with. This must not be * \c NULL unless \p add_len is \c 0. * \param add_len Length of \p additional in bytes. This must be at * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if * \p add_len is more than * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * \return An error from the underlying AES cipher on failure. */ int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t add_len); /** * \brief This function updates a CTR_DRBG instance with additional * data and uses it to generate random data. * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. * \param output_len The length of the buffer in bytes. * \param additional Additional data to update. Can be \c NULL, in which * case the additional data is empty regardless of * the value of \p add_len. * \param add_len The length of the additional data * if \p additional is not \c NULL. * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT * and less than * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len * where \c entropy_len is the entropy length * configured for the context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. */ int mbedtls_ctr_drbg_random_with_add(void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len); /** * \brief This function uses CTR_DRBG to generate random data. * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. */ #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * it is safe to call mbedtls_ctr_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. * \param output_len The length of the buffer in bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. */ int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, size_t output_len); #if defined(MBEDTLS_FS_IO) /** * \brief This function writes a seed file. * * \param ctx The CTR_DRBG context. * \param path The name of the file. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed * failure. */ int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path); /** * \brief This function reads and updates a seed file. The seed * is added to this instance. * * \param ctx The CTR_DRBG context. * \param path The name of the file. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on * reseed failure. * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing * seed file is too large. */ int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /** * \brief The CTR_DRBG checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_ctr_drbg_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* ctr_drbg.h */ webfakes/src/mbedtls/include/mbedtls/net_sockets.h0000644000176200001440000002655614740737024022057 0ustar liggesusers/** * \file net_sockets.h * * \brief Network sockets abstraction layer to integrate Mbed TLS into a * BSD-style sockets API. * * The network sockets module provides an example integration of the * Mbed TLS library into a BSD sockets implementation. The module is * intended to be an example of how Mbed TLS can be integrated into a * networking stack, as well as to be Mbed TLS's network integration * for its supported platforms. * * The module is intended only to be used with the Mbed TLS library and * is not intended to be used by third party application software * directly. * * The supported platforms are as follows: * * Microsoft Windows and Windows CE * * POSIX/Unix platforms including Linux, OS X * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_NET_SOCKETS_H #define MBEDTLS_NET_SOCKETS_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ssl.h" #include #include /** Failed to open a socket. */ #define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /** The connection to the given server / port failed. */ #define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /** Binding of the socket failed. */ #define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /** Could not listen on the socket. */ #define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /** Could not accept the incoming connection. */ #define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /** Reading information from the socket failed. */ #define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /** Sending information through the socket failed. */ #define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /** Connection was reset by peer. */ #define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /** Failed to get an IP address for the given hostname. */ #define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /** Buffer is too small to hold the data. */ #define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /** The context is invalid, eg because it was free()ed. */ #define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /** Polling the net context failed. */ #define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 /** Input invalid. */ #define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 #define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ #define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ #define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ #define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */ #define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */ #ifdef __cplusplus extern "C" { #endif /** * Wrapper type for sockets. * * Currently backed by just a file descriptor, but might be more in the future * (eg two file descriptors for combined IPv4 + IPv6 support, or additional * structures for hand-made UDP demultiplexing). */ typedef struct mbedtls_net_context { /** The underlying file descriptor. * * This field is only guaranteed to be present on POSIX/Unix-like platforms. * On other platforms, it may have a different type, have a different * meaning, or be absent altogether. */ int fd; } mbedtls_net_context; /** * \brief Initialize a context * Just makes the context ready to be used or freed safely. * * \param ctx Context to initialize */ void mbedtls_net_init(mbedtls_net_context *ctx); /** * \brief Initiate a connection with host:port in the given protocol * * \param ctx Socket to use * \param host Host to connect to * \param port Port to connect to * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP * * \return 0 if successful, or one of: * MBEDTLS_ERR_NET_SOCKET_FAILED, * MBEDTLS_ERR_NET_UNKNOWN_HOST, * MBEDTLS_ERR_NET_CONNECT_FAILED * * \note Sets the socket in connected mode even with UDP. */ int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto); /** * \brief Create a receiving socket on bind_ip:port in the chosen * protocol. If bind_ip == NULL, all interfaces are bound. * * \param ctx Socket to use * \param bind_ip IP to bind to, can be NULL * \param port Port number to use * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP * * \return 0 if successful, or one of: * MBEDTLS_ERR_NET_SOCKET_FAILED, * MBEDTLS_ERR_NET_UNKNOWN_HOST, * MBEDTLS_ERR_NET_BIND_FAILED, * MBEDTLS_ERR_NET_LISTEN_FAILED * * \note Regardless of the protocol, opens the sockets and binds it. * In addition, make the socket listening if protocol is TCP. */ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto); /** * \brief Accept a connection from a remote client * * \param bind_ctx Relevant socket * \param client_ctx Will contain the connected client socket * \param client_ip Will contain the client IP address, can be NULL * \param buf_size Size of the client_ip buffer * \param cip_len Will receive the size of the client IP written, * can be NULL if client_ip is null * * \return 0 if successful, or * MBEDTLS_ERR_NET_SOCKET_FAILED, * MBEDTLS_ERR_NET_BIND_FAILED, * MBEDTLS_ERR_NET_ACCEPT_FAILED, or * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to * non-blocking and accept() would block. */ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, void *client_ip, size_t buf_size, size_t *cip_len); /** * \brief Check and wait for the context to be ready for read/write * * \note The current implementation of this function uses * select() and returns an error if the file descriptor * is \c FD_SETSIZE or greater. * * \param ctx Socket to check * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and * MBEDTLS_NET_POLL_WRITE specifying the events * to wait for: * - If MBEDTLS_NET_POLL_READ is set, the function * will return as soon as the net context is available * for reading. * - If MBEDTLS_NET_POLL_WRITE is set, the function * will return as soon as the net context is available * for writing. * \param timeout Maximal amount of time to wait before returning, * in milliseconds. If \c timeout is zero, the * function returns immediately. If \c timeout is * -1u, the function blocks potentially indefinitely. * * \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE * on success or timeout, or a negative return code otherwise. */ int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout); /** * \brief Set the socket blocking * * \param ctx Socket to set * * \return 0 if successful, or a non-zero error code */ int mbedtls_net_set_block(mbedtls_net_context *ctx); /** * \brief Set the socket non-blocking * * \param ctx Socket to set * * \return 0 if successful, or a non-zero error code */ int mbedtls_net_set_nonblock(mbedtls_net_context *ctx); /** * \brief Portable usleep helper * * \param usec Amount of microseconds to sleep * * \note Real amount of time slept will not be less than * select()'s timeout granularity (typically, 10ms). */ void mbedtls_net_usleep(unsigned long usec); /** * \brief Read at most 'len' characters. If no error occurs, * the actual amount read is returned. * * \param ctx Socket * \param buf The buffer to write to * \param len Maximum length of the buffer * * \return the number of bytes received, * or a non-zero error code; with a non-blocking socket, * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. */ int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len); /** * \brief Write at most 'len' characters. If no error occurs, * the actual amount read is returned. * * \param ctx Socket * \param buf The buffer to read from * \param len The length of the buffer * * \return the number of bytes sent, * or a non-zero error code; with a non-blocking socket, * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. */ int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len); /** * \brief Read at most 'len' characters, blocking for at most * 'timeout' seconds. If no error occurs, the actual amount * read is returned. * * \note The current implementation of this function uses * select() and returns an error if the file descriptor * is \c FD_SETSIZE or greater. * * \param ctx Socket * \param buf The buffer to write to * \param len Maximum length of the buffer * \param timeout Maximum number of milliseconds to wait for data * 0 means no timeout (wait forever) * * \return The number of bytes received if successful. * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out. * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. * Another negative error code (MBEDTLS_ERR_NET_xxx) * for other failures. * * \note This function will block (until data becomes available or * timeout is reached) even if the socket is set to * non-blocking. Handling timeouts with non-blocking reads * requires a different strategy. */ int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout); /** * \brief Closes down the connection and free associated data * * \param ctx The context to close * * \note This function frees and clears data associated with the * context but does not free the memory pointed to by \p ctx. * This memory is the responsibility of the caller. */ void mbedtls_net_close(mbedtls_net_context *ctx); /** * \brief Gracefully shutdown the connection and free associated data * * \param ctx The context to free * * \note This function frees and clears data associated with the * context but does not free the memory pointed to by \p ctx. * This memory is the responsibility of the caller. */ void mbedtls_net_free(mbedtls_net_context *ctx); #ifdef __cplusplus } #endif #endif /* net_sockets.h */ webfakes/src/mbedtls/include/mbedtls/base64.h0000644000176200001440000000506514740737024020612 0ustar liggesusers/** * \file base64.h * * \brief RFC 1521 base64 encoding/decoding */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BASE64_H #define MBEDTLS_BASE64_H #include "mbedtls/build_info.h" #include /** Output buffer too small. */ #define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /** Invalid character in input. */ #define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C #ifdef __cplusplus extern "C" { #endif /** * \brief Encode a buffer into base64 format * * \param dst destination buffer * \param dlen size of the destination buffer * \param olen number of bytes written * \param src source buffer * \param slen amount of data to be encoded * * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. * *olen is always updated to reflect the amount * of data that has (or would have) been written. * If that length cannot be represented, then no data is * written to the buffer and *olen is set to the maximum * length representable as a size_t. * * \note Call this function with dlen = 0 to obtain the * required buffer size in *olen */ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen); /** * \brief Decode a base64-formatted buffer * * \param dst destination buffer (can be NULL for checking size) * \param dlen size of the destination buffer * \param olen number of bytes written * \param src source buffer * \param slen amount of data to be decoded * * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is * not correct. *olen is always updated to reflect the amount * of data that has (or would have) been written. * * \note Call this function with *dst = NULL or dlen = 0 to obtain * the required buffer size in *olen */ int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_base64_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* base64.h */ webfakes/src/mbedtls/include/mbedtls/error.h0000644000176200001440000001461714740737024020662 0ustar liggesusers/** * \file error.h * * \brief Error to string translation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ERROR_H #define MBEDTLS_ERROR_H #include "mbedtls/build_info.h" #include /** * Error code layout. * * Currently we try to keep all error codes within the negative space of 16 * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In * addition we'd like to give two layers of information on the error if * possible. * * For that purpose the error codes are segmented in the following manner: * * 16 bit error code bit-segmentation * * 1 bit - Unused (sign bit) * 3 bits - High level module ID * 5 bits - Module-dependent error code * 7 bits - Low level module errors * * For historical reasons, low-level error codes are divided in even and odd, * even codes were assigned first, and -1 is reserved for other errors. * * Low-level module errors (0x0002-0x007E, 0x0001-0x007F) * * Module Nr Codes assigned * ERROR 2 0x006E 0x0001 * MPI 7 0x0002-0x0010 * GCM 3 0x0012-0x0016 0x0013-0x0013 * THREADING 3 0x001A-0x001E * AES 5 0x0020-0x0022 0x0021-0x0025 * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 * BASE64 2 0x002A-0x002C * OID 1 0x002E-0x002E 0x000B-0x000B * PADLOCK 1 0x0030-0x0030 * DES 2 0x0032-0x0032 0x0033-0x0033 * CTR_DBRG 4 0x0034-0x003A * ENTROPY 3 0x003C-0x0040 0x003D-0x003F * NET 13 0x0042-0x0052 0x0043-0x0049 * ARIA 4 0x0058-0x005E * ASN1 7 0x0060-0x006C * CMAC 1 0x007A-0x007A * PBKDF2 1 0x007C-0x007C * HMAC_DRBG 4 0x0003-0x0009 * CCM 3 0x000D-0x0011 * MD5 1 0x002F-0x002F * RIPEMD160 1 0x0031-0x0031 * SHA1 1 0x0035-0x0035 0x0073-0x0073 * SHA256 1 0x0037-0x0037 0x0074-0x0074 * SHA512 1 0x0039-0x0039 0x0075-0x0075 * SHA-3 1 0x0076-0x0076 * CHACHA20 3 0x0051-0x0055 * POLY1305 3 0x0057-0x005B * CHACHAPOLY 2 0x0054-0x0056 * PLATFORM 2 0x0070-0x0072 * LMS 5 0x0011-0x0019 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors * PEM 1 9 * PKCS#12 1 4 (Started from top) * X509 2 20 * PKCS5 2 4 (Started from top) * DHM 3 11 * PK 3 15 (Started from top) * RSA 4 11 * ECP 4 10 (Started from top) * MD 5 5 * HKDF 5 1 (Started from top) * PKCS7 5 12 (Started from 0x5300) * SSL 5 2 (Started from 0x5F00) * CIPHER 6 8 (Started from 0x6080) * SSL 6 22 (Started from top, plus 0x6000) * SSL 7 20 (Started from 0x7000, gaps at * 0x7380, 0x7900-0x7980, 0x7A80-0x7E80) * * Module dependent error code (5 bits 0x.00.-0x.F8.) */ #ifdef __cplusplus extern "C" { #endif /** Generic error */ #define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 /** This is a bug in the library */ #define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E /** Hardware accelerator failed */ #define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /** The requested feature is not supported by the platform */ #define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /** * \brief Combines a high-level and low-level error code together. * * Wrapper macro for mbedtls_error_add(). See that function for * more details. */ #define MBEDTLS_ERROR_ADD(high, low) \ mbedtls_error_add(high, low, __FILE__, __LINE__) #if defined(MBEDTLS_TEST_HOOKS) /** * \brief Testing hook called before adding/combining two error codes together. * Only used when invasive testing is enabled via MBEDTLS_TEST_HOOKS. */ extern void (*mbedtls_test_hook_error_add)(int, int, const char *, int); #endif /** * \brief Combines a high-level and low-level error code together. * * This function can be called directly however it is usually * called via the #MBEDTLS_ERROR_ADD macro. * * While a value of zero is not a negative error code, it is still an * error code (that denotes success) and can be combined with both a * negative error code or another value of zero. * * \note When invasive testing is enabled via #MBEDTLS_TEST_HOOKS, also try to * call \link mbedtls_test_hook_error_add \endlink. * * \param high high-level error code. See error.h for more details. * \param low low-level error code. See error.h for more details. * \param file file where this error code addition occurred. * \param line line where this error code addition occurred. */ static inline int mbedtls_error_add(int high, int low, const char *file, int line) { #if defined(MBEDTLS_TEST_HOOKS) if (*mbedtls_test_hook_error_add != NULL) { (*mbedtls_test_hook_error_add)(high, low, file, line); } #endif (void) file; (void) line; return high + low; } /** * \brief Translate an Mbed TLS error code into a string representation. * The result is truncated if necessary and always includes a * terminating null byte. * * \param errnum error code * \param buffer buffer to place representation in * \param buflen length of the buffer */ void mbedtls_strerror(int errnum, char *buffer, size_t buflen); /** * \brief Translate the high-level part of an Mbed TLS error code into a string * representation. * * This function returns a const pointer to an un-modifiable string. The caller * must not try to modify the string. It is intended to be used mostly for * logging purposes. * * \param error_code error code * * \return The string representation of the error code, or \c NULL if the error * code is unknown. */ const char *mbedtls_high_level_strerr(int error_code); /** * \brief Translate the low-level part of an Mbed TLS error code into a string * representation. * * This function returns a const pointer to an un-modifiable string. The caller * must not try to modify the string. It is intended to be used mostly for * logging purposes. * * \param error_code error code * * \return The string representation of the error code, or \c NULL if the error * code is unknown. */ const char *mbedtls_low_level_strerr(int error_code); #ifdef __cplusplus } #endif #endif /* error.h */ webfakes/src/mbedtls/include/mbedtls/ecp.h0000644000176200001440000021110114740737024020263 0ustar liggesusers/** * \file ecp.h * * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). * * The use of ECP in cryptography and TLS is defined in * Standards for Efficient Cryptography Group (SECG): SEC1 * Elliptic Curve Cryptography and * RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites * for Transport Layer Security (TLS). * * RFC-2409: The Internet Key Exchange (IKE) defines ECP * group types. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECP_H #define MBEDTLS_ECP_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include "mbedtls/bignum.h" /* * ECP error codes */ /** Bad input parameters to function. */ #define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /** The buffer is too small to write to. */ #define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /** The requested feature is not available, for example, the requested curve is not supported. */ #define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /** The signature is not valid. */ #define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /** Memory allocation failed. */ #define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /** Generation of random value, such as ephemeral key, failed. */ #define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /** Invalid private or public key. */ #define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /** The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /** Operation in progress, call again with the same parameters to continue. */ #define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /* Flags indicating whether to include code that is specific to certain * types of curves. These flags are for internal library use only. */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) #define MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #define MBEDTLS_ECP_MONTGOMERY_ENABLED #endif #ifdef __cplusplus extern "C" { #endif /** * Domain-parameter identifiers: curve, subgroup, and generator. * * \note Only curves over prime fields are supported. * * \warning This library does not support validation of arbitrary domain * parameters. Therefore, only standardized domain parameters from trusted * sources should be used. See mbedtls_ecp_group_load(). */ /* Note: when adding a new curve: * - Add it at the end of this enum, otherwise you'll break the ABI by * changing the numerical value for existing curves. * - Increment MBEDTLS_ECP_DP_MAX below if needed. * - Update the calculation of MBEDTLS_ECP_MAX_BITS below. * - Add the corresponding MBEDTLS_ECP_DP_xxx_ENABLED macro definition to * mbedtls_config.h. * - List the curve as a dependency of MBEDTLS_ECP_C and * MBEDTLS_ECDSA_C if supported in check_config.h. * - Add the curve to the appropriate curve type macro * MBEDTLS_ECP_yyy_ENABLED above. * - Add the necessary definitions to ecp_curves.c. * - Add the curve to the ecp_supported_curves array in ecp.c. * - Add the curve to applicable profiles in x509_crt.c. * - Add the curve to applicable presets in ssl_tls.c. */ typedef enum { MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ } mbedtls_ecp_group_id; /** * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. */ #define MBEDTLS_ECP_DP_MAX 14 /* * Curve types */ typedef enum { MBEDTLS_ECP_TYPE_NONE = 0, MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ MBEDTLS_ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ } mbedtls_ecp_curve_type; /** * Curve information, for use by other modules. * * The fields of this structure are part of the public API and can be * accessed directly by applications. Future versions of the library may * add extra fields or reorder existing fields. */ typedef struct mbedtls_ecp_curve_info { mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ uint16_t bit_size; /*!< The curve size in bits. */ const char *name; /*!< A human-friendly name. */ } mbedtls_ecp_curve_info; /** * \brief The ECP point structure, in Jacobian coordinates. * * \note All functions expect and return points satisfying * the following condition: Z == 0 or * Z == 1. Other values of \p Z are * used only by internal functions. * The point is zero, or "at infinity", if Z == 0. * Otherwise, \p X and \p Y are its standard (affine) * coordinates. */ typedef struct mbedtls_ecp_point { mbedtls_mpi MBEDTLS_PRIVATE(X); /*!< The X coordinate of the ECP point. */ mbedtls_mpi MBEDTLS_PRIVATE(Y); /*!< The Y coordinate of the ECP point. */ mbedtls_mpi MBEDTLS_PRIVATE(Z); /*!< The Z coordinate of the ECP point. */ } mbedtls_ecp_point; #if !defined(MBEDTLS_ECP_ALT) /* * default Mbed TLS elliptic curve arithmetic implementation * * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an * alternative implementation for the whole module and it will replace this * one.) */ /** * \brief The ECP group structure. * * We consider two types of curve equations: *
  • Short Weierstrass: y^2 = x^3 + A x + B mod P * (SEC1 + RFC-4492)
  • *
  • Montgomery: y^2 = x^3 + A x^2 + x mod P (Curve25519, * Curve448)
* In both cases, the generator (\p G) for a prime-order subgroup is fixed. * * For Short Weierstrass, this subgroup is the whole curve, and its * cardinality is denoted by \p N. Our code requires that \p N is an * odd prime as mbedtls_ecp_mul() requires an odd number, and * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. * * The default implementation only initializes \p A without setting it to the * authentic value for curves with A = -3(SECP256R1, etc), in which * case you need to load \p A by yourself when using domain parameters directly, * for example: * \code * mbedtls_mpi_init(&A); * mbedtls_ecp_group_init(&grp); * CHECK_RETURN(mbedtls_ecp_group_load(&grp, grp_id)); * if (mbedtls_ecp_group_a_is_minus_3(&grp)) { * CHECK_RETURN(mbedtls_mpi_sub_int(&A, &grp.P, 3)); * } else { * CHECK_RETURN(mbedtls_mpi_copy(&A, &grp.A)); * } * * do_something_with_a(&A); * * cleanup: * mbedtls_mpi_free(&A); * mbedtls_ecp_group_free(&grp); * \endcode * * For Montgomery curves, we do not store \p A, but (A + 2) / 4, * which is the quantity used in the formulas. Additionally, \p nbits is * not the size of \p N but the required size for private keys. * * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the * range of 0..2^(2*pbits)-1, and transforms it in-place to an integer * which is congruent mod \p P to the given MPI, and is close enough to \p pbits * in size, so that it may be efficiently brought in the 0..P-1 range by a few * additions or subtractions. Therefore, it is only an approximate modular * reduction. It must return 0 on success and non-zero on failure. * * \note Alternative implementations of the ECP module must obey the * following constraints. * * Group IDs must be distinct: if two group structures have * the same ID, then they must be identical. * * The fields \c id, \c P, \c A, \c B, \c G, \c N, * \c pbits and \c nbits must have the same type and semantics * as in the built-in implementation. * They must be available for reading, but direct modification * of these fields does not need to be supported. * They do not need to be at the same offset in the structure. */ typedef struct mbedtls_ecp_group { mbedtls_ecp_group_id id; /*!< An internal group identifier. */ mbedtls_mpi P; /*!< The prime modulus of the base field. */ mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. Note that \p A is not set to the authentic value in some cases. Refer to detailed description of ::mbedtls_ecp_group if using domain parameters in the structure. For Montgomery curves: (A + 2) / 4. */ mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. For Montgomery curves: unused. */ mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ mbedtls_mpi N; /*!< The order of \p G. */ size_t pbits; /*!< The number of bits in \p P.*/ size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. For Montgomery curves: the number of bits in the private keys. */ /* End of public fields */ unsigned int MBEDTLS_PRIVATE(h); /*!< \internal 1 if the constants are static. */ int(*MBEDTLS_PRIVATE(modp))(mbedtls_mpi *); /*!< The function for fast pseudo-reduction mod \p P (see above).*/ int(*MBEDTLS_PRIVATE(t_pre))(mbedtls_ecp_point *, void *); /*!< Unused. */ int(*MBEDTLS_PRIVATE(t_post))(mbedtls_ecp_point *, void *); /*!< Unused. */ void *MBEDTLS_PRIVATE(t_data); /*!< Unused. */ mbedtls_ecp_point *MBEDTLS_PRIVATE(T); /*!< Pre-computed points for ecp_mul_comb(). */ size_t MBEDTLS_PRIVATE(T_size); /*!< The number of dynamic allocated pre-computed points. */ } mbedtls_ecp_group; /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h, or define them using the compiler command line. * \{ */ #if !defined(MBEDTLS_ECP_WINDOW_SIZE) /* * Maximum "window" size used for point multiplication. * Default: a point where higher memory usage yields diminishing performance * returns. * Minimum value: 2. Maximum value: 7. * * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) * points used for point multiplication. This value is directly tied to EC * peak memory usage, so decreasing it by one should roughly cut memory usage * by two (if large curves are in use). * * Reduction in size may reduce speed, but larger curves are impacted first. * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): * w-size: 6 5 4 3 2 * 521 145 141 135 120 97 * 384 214 209 198 177 146 * 256 320 320 303 262 226 * 224 475 475 453 398 342 * 192 640 640 633 587 476 */ #define MBEDTLS_ECP_WINDOW_SIZE 4 /**< The maximum window size used. */ #endif /* MBEDTLS_ECP_WINDOW_SIZE */ #if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) /* * Trade code size for speed on fixed-point multiplication. * * This speeds up repeated multiplication of the generator (that is, the * multiplication in ECDSA signatures, and half of the multiplications in * ECDSA verification and ECDHE) by a factor roughly 3 to 4. * * For each n-bit Short Weierstrass curve that is enabled, this adds 4n bytes * of code size if n < 384 and 8n otherwise. * * Change this value to 0 to reduce code size. */ #define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ #endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ /** \} name SECTION: Module settings */ #else /* MBEDTLS_ECP_ALT */ #include "ecp_alt.h" #endif /* MBEDTLS_ECP_ALT */ /** * The maximum size of the groups, that is, of \c N and \c P. */ #if !defined(MBEDTLS_ECP_LIGHT) /* Dummy definition to help code that has optional ECP support and * defines an MBEDTLS_ECP_MAX_BYTES-sized array unconditionally. */ #define MBEDTLS_ECP_MAX_BITS 1 /* Note: the curves must be listed in DECREASING size! */ #elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 521 #elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 512 #elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #define MBEDTLS_ECP_MAX_BITS 448 #elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 384 #elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 384 #elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 256 #elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 256 #elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 256 #elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #define MBEDTLS_ECP_MAX_BITS 255 #elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 225 // n is slightly above 2^224 #elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 224 #elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 192 #elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 192 #else /* !MBEDTLS_ECP_LIGHT */ #error "Missing definition of MBEDTLS_ECP_MAX_BITS" #endif /* !MBEDTLS_ECP_LIGHT */ #define MBEDTLS_ECP_MAX_BYTES ((MBEDTLS_ECP_MAX_BITS + 7) / 8) #define MBEDTLS_ECP_MAX_PT_LEN (2 * MBEDTLS_ECP_MAX_BYTES + 1) #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Internal restart context for multiplication * * \note Opaque struct */ typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; /** * \brief Internal restart context for ecp_muladd() * * \note Opaque struct */ typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; /** * \brief General context for resuming ECC operations */ typedef struct { unsigned MBEDTLS_PRIVATE(ops_done); /*!< current ops count */ unsigned MBEDTLS_PRIVATE(depth); /*!< call depth (0 = top-level) */ mbedtls_ecp_restart_mul_ctx *MBEDTLS_PRIVATE(rsm); /*!< ecp_mul_comb() sub-context */ mbedtls_ecp_restart_muladd_ctx *MBEDTLS_PRIVATE(ma); /*!< ecp_muladd() sub-context */ } mbedtls_ecp_restart_ctx; /* * Operation counts for restartable functions */ #define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ #define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ #define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ #define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ /** * \brief Internal; for restartable functions in other modules. * Check and update basic ops budget. * * \param grp Group structure * \param rs_ctx Restart context * \param ops Number of basic ops to do * * \return \c 0 if doing \p ops basic ops is still allowed, * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. */ int mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx, unsigned ops); /* Utility macro for checking and updating ops budget */ #define MBEDTLS_ECP_BUDGET(ops) \ MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, rs_ctx, \ (unsigned) (ops))); #else /* MBEDTLS_ECP_RESTARTABLE */ #define MBEDTLS_ECP_BUDGET(ops) /* no-op; for compatibility */ /* We want to declare restartable versions of existing functions anyway */ typedef void mbedtls_ecp_restart_ctx; #endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief The ECP key-pair structure. * * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. * * \note Members are deliberately in the same order as in the * ::mbedtls_ecdsa_context structure. */ typedef struct mbedtls_ecp_keypair { mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< Elliptic curve and base point */ mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< our secret value */ mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< our public value */ } mbedtls_ecp_keypair; /** * The uncompressed point format for Short Weierstrass curves * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX). */ #define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /** * The compressed point format for Short Weierstrass curves * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX). * * \warning While this format is supported for all concerned curves for * writing, when it comes to parsing, it is not supported for all * curves. Specifically, parsing compressed points on * MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1 is not * supported. */ #define MBEDTLS_ECP_PF_COMPRESSED 1 /* * Some other constants from RFC 4492 */ #define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Set the maximum number of basic operations done in a row. * * If more operations are needed to complete a computation, * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the * function performing the computation. It is then the * caller's responsibility to either call again with the same * parameters until it returns 0 or an error code; or to free * the restart context if the operation is to be aborted. * * It is strictly required that all input parameters and the * restart context be the same on successive calls for the * same operation, but output parameters need not be the * same; they must not be used until the function finally * returns 0. * * This only applies to functions whose documentation * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the * SSL module). For functions that accept a "restart context" * argument, passing NULL disables restart and makes the * function equivalent to the function with the same name * with \c _restartable removed. For functions in the ECDH * module, restart is disabled unless the function accepts * an "ECDH context" argument and * mbedtls_ecdh_enable_restart() was previously called on * that context. For function in the SSL module, restart is * only enabled for specific sides and key exchanges * (currently only for clients and ECDHE-ECDSA). * * \warning Using the PSA interruptible interfaces with keys in local * storage and no accelerator driver will also call this * function to set the values specified via those interfaces, * overwriting values previously set. Care should be taken if * mixing these two interfaces. * * \param max_ops Maximum number of basic operations done in a row. * Default: 0 (unlimited). * Lower (non-zero) values mean ECC functions will block for * a lesser maximum amount of time. * * \note A "basic operation" is defined as a rough equivalent of a * multiplication in GF(p) for the NIST P-256 curve. * As an indication, with default settings, a scalar * multiplication (full run of \c mbedtls_ecp_mul()) is: * - about 3300 basic operations for P-256 * - about 9400 basic operations for P-384 * * \note Very low values are not always respected: sometimes * functions need to block for a minimum number of * operations, and will do so even if max_ops is set to a * lower value. That minimum depends on the curve size, and * can be made lower by decreasing the value of * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the * lowest effective value for various curves and values of * that parameter (w for short): * w=6 w=5 w=4 w=3 w=2 * P-256 208 208 160 136 124 * P-384 682 416 320 272 248 * P-521 1364 832 640 544 496 * * \note This setting is currently ignored by Curve25519. */ void mbedtls_ecp_set_max_ops(unsigned max_ops); /** * \brief Check if restart is enabled (max_ops != 0) * * \return \c 0 if \c max_ops == 0 (restart disabled) * \return \c 1 otherwise (restart enabled) */ int mbedtls_ecp_restart_is_enabled(void); #endif /* MBEDTLS_ECP_RESTARTABLE */ /* * Get the type of a curve */ mbedtls_ecp_curve_type mbedtls_ecp_get_type(const mbedtls_ecp_group *grp); /** * \brief This function retrieves the information defined in * mbedtls_ecp_curve_info() for all supported curves. * * \note This function returns information about all curves * supported by the library. Some curves may not be * supported for all algorithms. Call mbedtls_ecdh_can_do() * or mbedtls_ecdsa_can_do() to check if a curve is * supported for ECDH or ECDSA. * * \return A statically allocated array. The last entry is 0. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void); /** * \brief This function retrieves the list of internal group * identifiers of all supported curves in the order of * preference. * * \note This function returns information about all curves * supported by the library. Some curves may not be * supported for all algorithms. Call mbedtls_ecdh_can_do() * or mbedtls_ecdsa_can_do() to check if a curve is * supported for ECDH or ECDSA. * * \return A statically allocated array, * terminated with MBEDTLS_ECP_DP_NONE. */ const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void); /** * \brief This function retrieves curve information from an internal * group identifier. * * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. * * \return The associated curve information on success. * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id(mbedtls_ecp_group_id grp_id); /** * \brief This function retrieves curve information from a TLS * NamedCurve value. * * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. * * \return The associated curve information on success. * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id(uint16_t tls_id); /** * \brief This function retrieves curve information from a * human-readable name. * * \param name The human-readable name. * * \return The associated curve information on success. * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name(const char *name); /** * \brief This function initializes a point as zero. * * \param pt The point to initialize. */ void mbedtls_ecp_point_init(mbedtls_ecp_point *pt); /** * \brief This function initializes an ECP group context * without loading any domain parameters. * * \note After this function is called, domain parameters * for various ECP groups can be loaded through the * mbedtls_ecp_group_load() or mbedtls_ecp_tls_read_group() * functions. */ void mbedtls_ecp_group_init(mbedtls_ecp_group *grp); /** * \brief This function initializes a key pair as an invalid one. * * \param key The key pair to initialize. */ void mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key); /** * \brief This function frees the components of a point. * * \param pt The point to free. */ void mbedtls_ecp_point_free(mbedtls_ecp_point *pt); /** * \brief This function frees the components of an ECP group. * * \param grp The group to free. This may be \c NULL, in which * case this function returns immediately. If it is not * \c NULL, it must point to an initialized ECP group. */ void mbedtls_ecp_group_free(mbedtls_ecp_group *grp); /** * \brief This function frees the components of a key pair. * * \param key The key pair to free. This may be \c NULL, in which * case this function returns immediately. If it is not * \c NULL, it must point to an initialized ECP key pair. */ void mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key); #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context. * * \param ctx The restart context to initialize. This must * not be \c NULL. */ void mbedtls_ecp_restart_init(mbedtls_ecp_restart_ctx *ctx); /** * \brief Free the components of a restart context. * * \param ctx The restart context to free. This may be \c NULL, in which * case this function returns immediately. If it is not * \c NULL, it must point to an initialized restart context. */ void mbedtls_ecp_restart_free(mbedtls_ecp_restart_ctx *ctx); #endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief This function copies the contents of point \p Q into * point \p P. * * \param P The destination point. This must be initialized. * \param Q The source point. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code for other kinds of failure. */ int mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q); /** * \brief This function copies the contents of group \p src into * group \p dst. * * \param dst The destination group. This must be initialized. * \param src The source group. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src); /** * \brief This function sets a point to the point at infinity. * * \param pt The point to set. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt); /** * \brief This function checks if a point is the point at infinity. * * \param pt The point to test. This must be initialized. * * \return \c 1 if the point is zero. * \return \c 0 if the point is non-zero. * \return A negative error code on failure. */ int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt); /** * \brief This function compares two points. * * \note This assumes that the points are normalized. Otherwise, * they may compare as "not equal" even if they are. * * \param P The first point to compare. This must be initialized. * \param Q The second point to compare. This must be initialized. * * \return \c 0 if the points are equal. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. */ int mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q); /** * \brief This function imports a non-zero point from two ASCII * strings. * * \param P The destination point. This must be initialized. * \param radix The numeric base of the input. * \param x The first affine coordinate, as a null-terminated string. * \param y The second affine coordinate, as a null-terminated string. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. */ int mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix, const char *x, const char *y); /** * \brief This function exports a point into unsigned binary data. * * \param grp The group to which the point should belong. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param P The point to export. This must be initialized. * \param format The point format. This must be either * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. * (For groups without these formats, this parameter is * ignored. But it still has to be either of the above * values.) * \param olen The address at which to store the length of * the output in Bytes. This must not be \c NULL. * \param buf The output buffer. This must be a writable buffer * of length \p buflen Bytes. * \param buflen The length of the output buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer * is too small to hold the point. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format * or the export for the given group is not implemented. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen); /** * \brief This function imports a point from unsigned binary data. * * \note This function does not check that the point actually * belongs to the given group, see mbedtls_ecp_check_pubkey() * for that. * * \note For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for * limitations. * * \param grp The group to which the point should belong. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param P The destination context to import the point to. * This must be initialized. * \param buf The input buffer. This must be a readable buffer * of length \p ilen Bytes. * \param ilen The length of the input buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the import for the * given group is not implemented. */ int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, const unsigned char *buf, size_t ilen); /** * \brief This function imports a point from a TLS ECPoint record. * * \note On function return, \p *buf is updated to point immediately * after the ECPoint record. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param pt The destination point. * \param buf The address of the pointer to the start of the input buffer. * \param len The length of the buffer. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization * failure. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. */ int mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, const unsigned char **buf, size_t len); /** * \brief This function exports a point as a TLS ECPoint record * defined in RFC 4492, Section 5.4. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param pt The point to be exported. This must be initialized. * \param format The point format to use. This must be either * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. * \param olen The address at which to store the length in Bytes * of the data written. * \param buf The target buffer. This must be a writable buffer of * length \p blen Bytes. * \param blen The length of the target buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer * is too small to hold the exported point. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, int format, size_t *olen, unsigned char *buf, size_t blen); /** * \brief This function sets up an ECP group context * from a standardized set of domain parameters. * * \note The index should be a value of the NamedCurve enum, * as defined in RFC-4492: Elliptic Curve Cryptography * (ECC) Cipher Suites for Transport Layer Security (TLS), * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. * * \param grp The group context to setup. This must be initialized. * \param id The identifier of the domain parameter set to load. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't * correspond to a known group. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id); /** * \brief This function sets up an ECP group context from a TLS * ECParameters record as defined in RFC 4492, Section 5.4. * * \note The read pointer \p buf is updated to point right after * the ECParameters record on exit. * * \param grp The group context to setup. This must be initialized. * \param buf The address of the pointer to the start of the input buffer. * \param len The length of the input buffer \c *buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not * recognized. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp, const unsigned char **buf, size_t len); /** * \brief This function extracts an elliptic curve group ID from a * TLS ECParameters record as defined in RFC 4492, Section 5.4. * * \note The read pointer \p buf is updated to point right after * the ECParameters record on exit. * * \param grp The address at which to store the group id. * This must not be \c NULL. * \param buf The address of the pointer to the start of the input buffer. * \param len The length of the input buffer \c *buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not * recognized. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp, const unsigned char **buf, size_t len); /** * \brief This function exports an elliptic curve as a TLS * ECParameters record as defined in RFC 4492, Section 5.4. * * \param grp The ECP group to be exported. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param olen The address at which to store the number of Bytes written. * This must not be \c NULL. * \param buf The buffer to write to. This must be a writable buffer * of length \p blen Bytes. * \param blen The length of the output buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output * buffer is too small to hold the exported group. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen); /** * \brief This function performs a scalar multiplication of a point * by an integer: \p R = \p m * \p P. * * It is not thread-safe to use same group in multiple threads. * * \note To prevent timing attacks, this function * executes the exact same sequence of base-field * operations for any valid \p m. It avoids any if-branch or * array index depending on the value of \p m. It also uses * \p f_rng to randomize some intermediate results. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param R The point in which to store the result of the calculation. * This must be initialized. * \param m The integer by which to multiply. This must be initialized. * \param P The point to multiply. This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c * NULL if \p f_rng doesn't need a context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private * key, or \p P is not a valid public key. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function performs multiplication of a point by * an integer: \p R = \p m * \p P in a restartable way. * * \see mbedtls_ecp_mul() * * \note This function does the same as \c mbedtls_ecp_mul(), but * it can return early and restart according to the limit set * with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param R The point in which to store the result of the calculation. * This must be initialized. * \param m The integer by which to multiply. This must be initialized. * \param P The point to multiply. This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c * NULL if \p f_rng doesn't need a context. * \param rs_ctx The restart context (NULL disables restart). * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private * key, or \p P is not a valid public key. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx); #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /** * \brief This function checks if domain parameter A of the curve is * \c -3. * * \note This function is only defined for short Weierstrass curves. * It may not be included in builds without any short * Weierstrass curve. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * * \return \c 1 if A = -3. * \return \c 0 Otherwise. */ static inline int mbedtls_ecp_group_a_is_minus_3(const mbedtls_ecp_group *grp) { return grp->A.MBEDTLS_PRIVATE(p) == NULL; } /** * \brief This function performs multiplication and addition of two * points by integers: \p R = \p m * \p P + \p n * \p Q * * It is not thread-safe to use same group in multiple threads. * * \note In contrast to mbedtls_ecp_mul(), this function does not * guarantee a constant execution flow and timing. * * \note This function is only defined for short Weierstrass curves. * It may not be included in builds without any short * Weierstrass curve. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param R The point in which to store the result of the calculation. * This must be initialized. * \param m The integer by which to multiply \p P. * This must be initialized. * \param P The point to multiply by \p m. This must be initialized. * \param n The integer by which to multiply \p Q. * This must be initialized. * \param Q The point to be multiplied by \p n. * This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not * valid private keys, or \p P or \p Q are not valid public * keys. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not * designate a short Weierstrass curve. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q); /** * \brief This function performs multiplication and addition of two * points by integers: \p R = \p m * \p P + \p n * \p Q in a * restartable way. * * \see \c mbedtls_ecp_muladd() * * \note This function works the same as \c mbedtls_ecp_muladd(), * but it can return early and restart according to the limit * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \note This function is only defined for short Weierstrass curves. * It may not be included in builds without any short * Weierstrass curve. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param R The point in which to store the result of the calculation. * This must be initialized. * \param m The integer by which to multiply \p P. * This must be initialized. * \param P The point to multiply by \p m. This must be initialized. * \param n The integer by which to multiply \p Q. * This must be initialized. * \param Q The point to be multiplied by \p n. * This must be initialized. * \param rs_ctx The restart context (NULL disables restart). * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not * valid private keys, or \p P or \p Q are not valid public * keys. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not * designate a short Weierstrass curve. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_muladd_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q, mbedtls_ecp_restart_ctx *rs_ctx); #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ /** * \brief This function checks that a point is a valid public key * on this curve. * * It only checks that the point is non-zero, has * valid coordinates and lies on the curve. It does not verify * that it is indeed a multiple of \c G. This additional * check is computationally more expensive, is not required * by standards, and should not be necessary if the group * used has a small cofactor. In particular, it is useless for * the NIST groups which all have a cofactor of 1. * * \note This function uses bare components rather than an * ::mbedtls_ecp_keypair structure, to ease use with other * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * * \param grp The ECP group the point should belong to. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param pt The point to check. This must be initialized. * * \return \c 0 if the point is a valid public key. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not * a valid public key for the given curve. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt); /** * \brief This function checks that an \c mbedtls_mpi is a * valid private key for this curve. * * \note This function uses bare components rather than an * ::mbedtls_ecp_keypair structure to ease use with other * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * * \param grp The ECP group the private key should belong to. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param d The integer to check. This must be initialized. * * \return \c 0 if the point is a valid private key. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid * private key for the given curve. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp, const mbedtls_mpi *d); /** * \brief This function generates a private key. * * \param grp The ECP group to generate a private key for. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param d The destination MPI (secret part). This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function generates a keypair with a configurable base * point. * * \note This function uses bare components rather than an * ::mbedtls_ecp_keypair structure to ease use with other * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * * \param grp The ECP group to generate a key pair for. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param G The base point to use. This must be initialized * and belong to \p grp. It replaces the default base * point \c grp->G used by mbedtls_ecp_gen_keypair(). * \param d The destination MPI (secret part). * This must be initialized. * \param Q The destination point (public part). * This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group *grp, const mbedtls_ecp_point *G, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function generates an ECP keypair. * * \note This function uses bare components rather than an * ::mbedtls_ecp_keypair structure to ease use with other * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * * \param grp The ECP group to generate a key pair for. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param d The destination MPI (secret part). * This must be initialized. * \param Q The destination point (public part). * This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function generates an ECP key. * * \param grp_id The ECP group identifier. * \param key The destination key. This must be initialized. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \brief Set the public key in a key pair object. * * \note This function does not check that the point actually * belongs to the given group. Call mbedtls_ecp_check_pubkey() * on \p Q before calling this function to check that. * * \note This function does not check that the public key matches * the private key that is already in \p key, if any. * To check the consistency of the resulting key pair object, * call mbedtls_ecp_check_pub_priv() after setting both * the public key and the private key. * * \param grp_id The ECP group identifier. * \param key The key pair object. It must be initialized. * If its group has already been set, it must match \p grp_id. * If its group has not been set, it will be set to \p grp_id. * If the public key has already been set, it is overwritten. * \param Q The public key to copy. This must be a point on the * curve indicated by \p grp_id. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p key does not * match \p grp_id. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for * the group is not implemented. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const mbedtls_ecp_point *Q); /** * \brief This function reads an elliptic curve private key. * * \note This function does not set the public key in the * key pair object. Without a public key, the key pair object * cannot be used with operations that require the public key. * Call mbedtls_ecp_keypair_calc_public() to set the public * key from the private key. Alternatively, you can call * mbedtls_ecp_set_public_key() to set the public key part, * and then optionally mbedtls_ecp_check_pub_priv() to check * that the private and public parts are consistent. * * \note If a public key has already been set in the key pair * object, this function does not check that it is consistent * with the private key. Call mbedtls_ecp_check_pub_priv() * after setting both the public key and the private key * to make that check. * * \param grp_id The ECP group identifier. * \param key The destination key. * \param buf The buffer containing the binary representation of the * key. (Big endian integer for Weierstrass curves, byte * string for Montgomery curves.) * \param buflen The length of the buffer in bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY error if the key is * invalid. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for * the group is not implemented. * \return Another negative error code on different kinds of failure. */ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const unsigned char *buf, size_t buflen); #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief This function exports an elliptic curve private key. * * \deprecated Note that although this function accepts an output * buffer that is smaller or larger than the key, most key * import interfaces require the output to have exactly * key's nominal length. It is generally simplest to * pass the key's nominal length as \c buflen, after * checking that the output buffer is large enough. * See the description of the \p buflen parameter for * how to calculate the nominal length. * To avoid this difficulty, use mbedtls_ecp_write_key_ext() * instead. * mbedtls_ecp_write_key() is deprecated and will be * removed in a future version of the library. * * \note If the private key was not set in \p key, * the output is unspecified. Future versions * may return an error in that case. * * \param key The private key. * \param buf The output buffer for containing the binary representation * of the key. * For Weierstrass curves, this is the big-endian * representation, padded with null bytes at the beginning * to reach \p buflen bytes. * For Montgomery curves, this is the standard byte string * representation (which is little-endian), padded with * null bytes at the end to reach \p buflen bytes. * \param buflen The total length of the buffer in bytes. * The length of the output is * (`grp->nbits` + 7) / 8 bytes * where `grp->nbits` is the private key size in bits. * For Weierstrass keys, if the output buffer is smaller, * leading zeros are trimmed to fit if possible. For * Montgomery keys, the output buffer must always be large * enough for the nominal length. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL or * #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the \p key * representation is larger than the available space in \p buf. * \return Another negative error code on different kinds of failure. */ int MBEDTLS_DEPRECATED mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, unsigned char *buf, size_t buflen); #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief This function exports an elliptic curve private key. * * \param key The private key. * \param olen On success, the length of the private key. * This is always (`grp->nbits` + 7) / 8 bytes * where `grp->nbits` is the private key size in bits. * \param buf The output buffer for containing the binary representation * of the key. * \param buflen The total length of the buffer in bytes. * #MBEDTLS_ECP_MAX_BYTES is always sufficient. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key * representation is larger than the available space in \p buf. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if no private key is * set in \p key. * \return Another negative error code on different kinds of failure. */ int mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key, size_t *olen, unsigned char *buf, size_t buflen); /** * \brief This function exports an elliptic curve public key. * * \note If the public key was not set in \p key, * the output is unspecified. Future versions * may return an error in that case. * * \param key The public key. * \param format The point format. This must be either * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. * (For groups without these formats, this parameter is * ignored. But it still has to be either of the above * values.) * \param olen The address at which to store the length of * the output in Bytes. This must not be \c NULL. * \param buf The output buffer. This must be a writable buffer * of length \p buflen Bytes. * \param buflen The length of the output buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer * is too small to hold the point. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format * or the export for the given group is not implemented. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key, int format, size_t *olen, unsigned char *buf, size_t buflen); /** * \brief This function checks that the keypair objects * \p pub and \p prv have the same group and the * same public point, and that the private key in * \p prv is consistent with the public key. * * \param pub The keypair structure holding the public key. This * must be initialized. If it contains a private key, that * part is ignored. * \param prv The keypair structure holding the full keypair. * This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c * NULL if \p f_rng doesn't need a context. * * \return \c 0 on success, meaning that the keys are valid and match. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX * error code on calculation failure. */ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \brief Calculate the public key from a private key in a key pair. * * \param key A keypair structure. It must have a private key set. * If the public key is set, it will be overwritten. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c * NULL if \p f_rng doesn't need a context. * * \return \c 0 on success. The key pair object can be used for * operations that require the public key. * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX * error code on calculation failure. */ int mbedtls_ecp_keypair_calc_public( mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \brief Query the group that a key pair belongs to. * * \param key The key pair to query. * * \return The group ID for the group registered in the key pair * object. * This is \c MBEDTLS_ECP_DP_NONE if no group has been set * in the key pair object. */ mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id( const mbedtls_ecp_keypair *key); /** * \brief This function exports generic key-pair parameters. * * Each of the output parameters can be a null pointer * if you do not need that parameter. * * \note If the private key or the public key was not set in \p key, * the corresponding output is unspecified. Future versions * may return an error in that case. * * \param key The key pair to export from. * \param grp Slot for exported ECP group. * It must either be null or point to an initialized ECP group. * \param d Slot for the exported secret value. * It must either be null or point to an initialized mpi. * \param Q Slot for the exported public value. * It must either be null or point to an initialized ECP point. * * \return \c 0 on success, * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if key id doesn't * correspond to a known group. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q); #if defined(MBEDTLS_SELF_TEST) /** * \brief The ECP checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_ecp_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* ecp.h */ webfakes/src/mbedtls/include/mbedtls/config_adjust_ssl.h0000644000176200001440000000653114740737024023225 0ustar liggesusers/** * \file mbedtls/config_adjust_ssl.h * \brief Adjust TLS configuration * * This is an internal header. Do not include it directly. * * Automatically enable certain dependencies. Generally, MBEDTLS_xxx * configurations need to be explicitly enabled by the user: enabling * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a * compilation error. However, we do automatically enable certain options * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option * used to identify parts of a module that are used by other module, and we * don't want to make the symbol MBEDTLS_xxx_B part of the public API. * Another case is if A didn't depend on B in earlier versions, and we * want to use B in A but we need to preserve backward compatibility with * configurations that explicitly activate MBEDTLS_xxx_A but not * MBEDTLS_xxx_B. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_SSL_H #define MBEDTLS_CONFIG_ADJUST_SSL_H #if !defined(MBEDTLS_CONFIG_FILES_READ) #error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \ "up to and including runtime errors such as buffer overflows. " \ "If you're trying to fix a complaint from check_config.h, just remove " \ "it from your configuration file: since Mbed TLS 3.0, it is included " \ "automatically at the right point." #endif /* */ /* The following blocks make it easier to disable all of TLS, * or of TLS 1.2 or 1.3 or DTLS, without having to manually disable all * key exchanges, options and extensions related to them. */ #if !defined(MBEDTLS_SSL_TLS_C) #undef MBEDTLS_SSL_CLI_C #undef MBEDTLS_SSL_SRV_C #undef MBEDTLS_SSL_PROTO_TLS1_3 #undef MBEDTLS_SSL_PROTO_TLS1_2 #undef MBEDTLS_SSL_PROTO_DTLS #endif #if !(defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)) #undef MBEDTLS_SSL_TICKET_C #endif #if !defined(MBEDTLS_SSL_PROTO_DTLS) #undef MBEDTLS_SSL_DTLS_ANTI_REPLAY #undef MBEDTLS_SSL_DTLS_CONNECTION_ID #undef MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT #undef MBEDTLS_SSL_DTLS_HELLO_VERIFY #undef MBEDTLS_SSL_DTLS_SRTP #undef MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE #endif #if !defined(MBEDTLS_SSL_PROTO_TLS1_2) #undef MBEDTLS_SSL_ENCRYPT_THEN_MAC #undef MBEDTLS_SSL_EXTENDED_MASTER_SECRET #undef MBEDTLS_SSL_RENEGOTIATION #undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED #undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED #undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED #endif #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) #undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED #undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED #undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED #undef MBEDTLS_SSL_EARLY_DATA #undef MBEDTLS_SSL_RECORD_SIZE_LIMIT #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)) #define MBEDTLS_SSL_TLS1_2_SOME_ECC #endif #endif /* MBEDTLS_CONFIG_ADJUST_SSL_H */ webfakes/src/mbedtls/include/mbedtls/mbedtls_config.h0000644000176200001440000044465414740737024022520 0ustar liggesusers/** * \file mbedtls_config.h * * \brief Configuration options (set of defines) * * This set of compile-time options may be used to enable * or disable features selectively, and reduce the global * memory footprint. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** * This is an optional version symbol that enables compatibility handling of * config files. * * It is equal to the #MBEDTLS_VERSION_NUMBER of the Mbed TLS version that * introduced the config format we want to be compatible with. */ //#define MBEDTLS_CONFIG_VERSION 0x03000000 /** * \name SECTION: System support * * This section sets system specific settings. * \{ */ /** * \def MBEDTLS_HAVE_ASM * * The compiler has support for asm(). * * Requires support for asm() in compiler. * * Used in: * library/aesni.h * library/aria.c * library/bn_mul.h * library/constant_time.c * library/padlock.h * * Required by: * MBEDTLS_AESCE_C * MBEDTLS_AESNI_C (on some platforms) * MBEDTLS_PADLOCK_C * * Comment to disable the use of assembly code. */ #define MBEDTLS_HAVE_ASM /** * \def MBEDTLS_NO_UDBL_DIVISION * * The platform lacks support for double-width integer division (64-bit * division on a 32-bit platform, 128-bit division on a 64-bit platform). * * Used in: * include/mbedtls/bignum.h * library/bignum.c * * The bignum code uses double-width division to speed up some operations. * Double-width division is often implemented in software that needs to * be linked with the program. The presence of a double-width integer * type is usually detected automatically through preprocessor macros, * but the automatic detection cannot know whether the code needs to * and can be linked with an implementation of division for that type. * By default division is assumed to be usable if the type is present. * Uncomment this option to prevent the use of double-width division. * * Note that division for the native integer type is always required. * Furthermore, a 64-bit type is always required even on a 32-bit * platform, but it need not support multiplication or division. In some * cases it is also desirable to disable some double-width operations. For * example, if double-width division is implemented in software, disabling * it can reduce code size in some embedded targets. */ //#define MBEDTLS_NO_UDBL_DIVISION /** * \def MBEDTLS_NO_64BIT_MULTIPLICATION * * The platform lacks support for 32x32 -> 64-bit multiplication. * * Used in: * library/poly1305.c * * Some parts of the library may use multiplication of two unsigned 32-bit * operands with a 64-bit result in order to speed up computations. On some * platforms, this is not available in hardware and has to be implemented in * software, usually in a library provided by the toolchain. * * Sometimes it is not desirable to have to link to that library. This option * removes the dependency of that library on platforms that lack a hardware * 64-bit multiplier by embedding a software implementation in Mbed TLS. * * Note that depending on the compiler, this may decrease performance compared * to using the library function provided by the toolchain. */ //#define MBEDTLS_NO_64BIT_MULTIPLICATION /** * \def MBEDTLS_HAVE_SSE2 * * CPU supports SSE2 instruction set. * * Uncomment if the CPU supports SSE2 (IA-32 specific). */ //#define MBEDTLS_HAVE_SSE2 /** * \def MBEDTLS_HAVE_TIME * * System has time.h and time(). * The time does not need to be correct, only time differences are used, * by contrast with MBEDTLS_HAVE_TIME_DATE * * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and * MBEDTLS_PLATFORM_STD_TIME. * * Comment if your system does not support time functions. * * \note If MBEDTLS_TIMING_C is set - to enable the semi-portable timing * interface - timing.c will include time.h on suitable platforms * regardless of the setting of MBEDTLS_HAVE_TIME, unless * MBEDTLS_TIMING_ALT is used. See timing.c for more information. */ #define MBEDTLS_HAVE_TIME /** * \def MBEDTLS_HAVE_TIME_DATE * * System has time.h, time(), and an implementation for * mbedtls_platform_gmtime_r() (see below). * The time needs to be correct (not necessarily very accurate, but at least * the date should be correct). This is used to verify the validity period of * X.509 certificates. * * Comment if your system does not have a correct clock. * * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that * behaves similarly to the gmtime_r() function from the C standard. Refer to * the documentation for mbedtls_platform_gmtime_r() for more information. * * \note It is possible to configure an implementation for * mbedtls_platform_gmtime_r() at compile-time by using the macro * MBEDTLS_PLATFORM_GMTIME_R_ALT. */ #define MBEDTLS_HAVE_TIME_DATE /** * \def MBEDTLS_PLATFORM_MEMORY * * Enable the memory allocation layer. * * By default Mbed TLS uses the system-provided calloc() and free(). * This allows different allocators (self-implemented or provided) to be * provided to the platform abstraction layer. * * Enabling #MBEDTLS_PLATFORM_MEMORY without the * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and * free() function pointer at runtime. * * Enabling #MBEDTLS_PLATFORM_MEMORY and specifying * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the * alternate function at compile time. * * An overview of how the value of mbedtls_calloc is determined: * * - if !MBEDTLS_PLATFORM_MEMORY * - mbedtls_calloc = calloc * - if MBEDTLS_PLATFORM_MEMORY * - if (MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO): * - mbedtls_calloc = MBEDTLS_PLATFORM_CALLOC_MACRO * - if !(MBEDTLS_PLATFORM_CALLOC_MACRO && MBEDTLS_PLATFORM_FREE_MACRO): * - Dynamic setup via mbedtls_platform_set_calloc_free is now possible with a default value MBEDTLS_PLATFORM_STD_CALLOC. * - How is MBEDTLS_PLATFORM_STD_CALLOC handled? * - if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS: * - MBEDTLS_PLATFORM_STD_CALLOC is not set to anything; * - MBEDTLS_PLATFORM_STD_MEM_HDR can be included if present; * - if !MBEDTLS_PLATFORM_NO_STD_FUNCTIONS: * - if MBEDTLS_PLATFORM_STD_CALLOC is present: * - User-defined MBEDTLS_PLATFORM_STD_CALLOC is respected; * - if !MBEDTLS_PLATFORM_STD_CALLOC: * - MBEDTLS_PLATFORM_STD_CALLOC = calloc * * - At this point the presence of MBEDTLS_PLATFORM_STD_CALLOC is checked. * - if !MBEDTLS_PLATFORM_STD_CALLOC * - MBEDTLS_PLATFORM_STD_CALLOC = uninitialized_calloc * * - mbedtls_calloc = MBEDTLS_PLATFORM_STD_CALLOC. * * Defining MBEDTLS_PLATFORM_CALLOC_MACRO and #MBEDTLS_PLATFORM_STD_CALLOC at the same time is not possible. * MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO must both be defined or undefined at the same time. * #MBEDTLS_PLATFORM_STD_CALLOC and #MBEDTLS_PLATFORM_STD_FREE do not have to be defined at the same time, as, if they are used, * dynamic setup of these functions is possible. See the tree above to see how are they handled in all cases. * An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer. * An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything. * * Requires: MBEDTLS_PLATFORM_C * * Enable this layer to allow use of alternative memory allocators. */ //#define MBEDTLS_PLATFORM_MEMORY /** * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS * * Do not assign standard functions in the platform layer (e.g. calloc() to * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) * * This makes sure there are no linking errors on platforms that do not support * these functions. You will HAVE to provide alternatives, either at runtime * via the platform_set_xxx() functions or at compile time by setting * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a * MBEDTLS_PLATFORM_XXX_MACRO. * * Requires: MBEDTLS_PLATFORM_C * * Uncomment to prevent default assignment of standard functions in the * platform layer. */ //#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS /** * \def MBEDTLS_PLATFORM_EXIT_ALT * * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let Mbed TLS support the * function in the platform abstraction layer. * * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, Mbed TLS will * provide a function "mbedtls_platform_set_printf()" that allows you to set an * alternative printf function pointer. * * All these define require MBEDTLS_PLATFORM_C to be defined! * * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; * it will be enabled automatically by check_config.h * * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as * MBEDTLS_PLATFORM_XXX_MACRO! * * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME * * Uncomment a macro to enable alternate implementation of specific base * platform function */ //#define MBEDTLS_PLATFORM_SETBUF_ALT //#define MBEDTLS_PLATFORM_EXIT_ALT //#define MBEDTLS_PLATFORM_TIME_ALT //#define MBEDTLS_PLATFORM_FPRINTF_ALT //#define MBEDTLS_PLATFORM_PRINTF_ALT //#define MBEDTLS_PLATFORM_SNPRINTF_ALT //#define MBEDTLS_PLATFORM_VSNPRINTF_ALT //#define MBEDTLS_PLATFORM_NV_SEED_ALT //#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT //#define MBEDTLS_PLATFORM_MS_TIME_ALT /** * Uncomment the macro to let Mbed TLS use your alternate implementation of * mbedtls_platform_gmtime_r(). This replaces the default implementation in * platform_util.c. * * gmtime() is not a thread-safe function as defined in the C standard. The * library will try to use safer implementations of this function, such as * gmtime_r() when available. However, if Mbed TLS cannot identify the target * system, the implementation of mbedtls_platform_gmtime_r() will default to * using the standard gmtime(). In this case, calls from the library to * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the * library are also guarded with this mutex to avoid race conditions. However, * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will * unconditionally use the implementation for mbedtls_platform_gmtime_r() * supplied at compile time. */ //#define MBEDTLS_PLATFORM_GMTIME_R_ALT /** * Uncomment the macro to let Mbed TLS use your alternate implementation of * mbedtls_platform_zeroize(), to wipe sensitive data in memory. This replaces * the default implementation in platform_util.c. * * By default, the library uses a system function such as memset_s() * (optional feature of C11), explicit_bzero() (BSD and compatible), or * SecureZeroMemory (Windows). If no such function is detected, the library * falls back to a plain C implementation. Compilers are technically * permitted to optimize this implementation out, meaning that the memory is * not actually wiped. The library tries to prevent that, but the C language * makes it impossible to guarantee that the memory will always be wiped. * * If your platform provides a guaranteed method to wipe memory which * `platform_util.c` does not detect, define this macro to the name of * a function that takes two arguments, a `void *` pointer and a length, * and wipes that many bytes starting at the specified address. For example, * if your platform has explicit_bzero() but `platform_util.c` does not * detect its presence, define `MBEDTLS_PLATFORM_ZEROIZE_ALT` to be * `explicit_bzero` to use that function as mbedtls_platform_zeroize(). */ //#define MBEDTLS_PLATFORM_ZEROIZE_ALT /** * \def MBEDTLS_DEPRECATED_WARNING * * Mark deprecated functions and features so that they generate a warning if * used. Functionality deprecated in one version will usually be removed in the * next version. You can enable this to help you prepare the transition to a * new major version by making sure your code is not using this functionality. * * This only works with GCC and Clang. With other compilers, you may want to * use MBEDTLS_DEPRECATED_REMOVED * * Uncomment to get warnings on using deprecated functions and features. */ //#define MBEDTLS_DEPRECATED_WARNING /** * \def MBEDTLS_DEPRECATED_REMOVED * * Remove deprecated functions and features so that they generate an error if * used. Functionality deprecated in one version will usually be removed in the * next version. You can enable this to help you prepare the transition to a * new major version by making sure your code is not using this functionality. * * Uncomment to get errors on using deprecated functions and features. */ //#define MBEDTLS_DEPRECATED_REMOVED /** \} name SECTION: System support */ /** * \name SECTION: Mbed TLS feature support * * This section sets support for features that are or are not needed * within the modules that are enabled. * \{ */ /** * \def MBEDTLS_TIMING_ALT * * Uncomment to provide your own alternate implementation for * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() * * Only works if you have MBEDTLS_TIMING_C enabled. * * You will need to provide a header "timing_alt.h" and an implementation at * compile time. */ //#define MBEDTLS_TIMING_ALT /** * \def MBEDTLS_AES_ALT * * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let Mbed TLS use your * alternate core implementation of a symmetric crypto, an arithmetic or hash * module (e.g. platform specific assembly optimized implementations). Keep * in mind that the function prototypes should remain the same. * * This replaces the whole module. If you only want to replace one of the * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. * * Example: In case you uncomment MBEDTLS_AES_ALT, Mbed TLS will no longer * provide the "struct mbedtls_aes_context" definition and omit the base * function declarations and implementations. "aes_alt.h" will be included from * "aes.h" to include the new function definitions. * * Uncomment a macro to enable alternate implementation of the corresponding * module. * * \warning MD5, DES and SHA-1 are considered weak and their * use constitutes a security risk. If possible, we recommend * avoiding dependencies on them, and considering stronger message * digests and ciphers instead. * */ //#define MBEDTLS_AES_ALT //#define MBEDTLS_ARIA_ALT //#define MBEDTLS_CAMELLIA_ALT //#define MBEDTLS_CCM_ALT //#define MBEDTLS_CHACHA20_ALT //#define MBEDTLS_CHACHAPOLY_ALT //#define MBEDTLS_CMAC_ALT //#define MBEDTLS_DES_ALT //#define MBEDTLS_DHM_ALT //#define MBEDTLS_ECJPAKE_ALT //#define MBEDTLS_GCM_ALT //#define MBEDTLS_NIST_KW_ALT //#define MBEDTLS_MD5_ALT //#define MBEDTLS_POLY1305_ALT //#define MBEDTLS_RIPEMD160_ALT //#define MBEDTLS_RSA_ALT //#define MBEDTLS_SHA1_ALT //#define MBEDTLS_SHA256_ALT //#define MBEDTLS_SHA512_ALT /* * When replacing the elliptic curve module, please consider, that it is * implemented with two .c files: * - ecp.c * - ecp_curves.c * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT * macros as described above. The only difference is that you have to make sure * that you provide functionality for both .c files. */ //#define MBEDTLS_ECP_ALT /** * \def MBEDTLS_SHA256_PROCESS_ALT * * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let Mbed TLS use you * alternate core implementation of symmetric crypto or hash function. Keep in * mind that function prototypes should remain the same. * * This replaces only one function. The header file from Mbed TLS is still * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. * * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, Mbed TLS will * no longer provide the mbedtls_sha1_process() function, but it will still provide * the other function (using your mbedtls_sha1_process() function) and the definition * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible * with this definition. * * \note If you use the AES_xxx_ALT macros, then it is recommended to also set * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES * tables. * * Uncomment a macro to enable alternate implementation of the corresponding * function. * * \warning MD5, DES and SHA-1 are considered weak and their use * constitutes a security risk. If possible, we recommend avoiding * dependencies on them, and considering stronger message digests * and ciphers instead. * * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are * enabled, then the deterministic ECDH signature functions pass the * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore * alternative implementations should use the RNG only for generating * the ephemeral key and nothing else. If this is not possible, then * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative * implementation should be provided for mbedtls_ecdsa_sign_det_ext(). * */ //#define MBEDTLS_MD5_PROCESS_ALT //#define MBEDTLS_RIPEMD160_PROCESS_ALT //#define MBEDTLS_SHA1_PROCESS_ALT //#define MBEDTLS_SHA256_PROCESS_ALT //#define MBEDTLS_SHA512_PROCESS_ALT //#define MBEDTLS_DES_SETKEY_ALT //#define MBEDTLS_DES_CRYPT_ECB_ALT //#define MBEDTLS_DES3_CRYPT_ECB_ALT //#define MBEDTLS_AES_SETKEY_ENC_ALT //#define MBEDTLS_AES_SETKEY_DEC_ALT //#define MBEDTLS_AES_ENCRYPT_ALT //#define MBEDTLS_AES_DECRYPT_ALT //#define MBEDTLS_ECDH_GEN_PUBLIC_ALT //#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT //#define MBEDTLS_ECDSA_VERIFY_ALT //#define MBEDTLS_ECDSA_SIGN_ALT //#define MBEDTLS_ECDSA_GENKEY_ALT /** * \def MBEDTLS_ECP_INTERNAL_ALT * * Expose a part of the internal interface of the Elliptic Curve Point module. * * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let Mbed TLS use your * alternative core implementation of elliptic curve arithmetic. Keep in mind * that function prototypes should remain the same. * * This partially replaces one function. The header file from Mbed TLS is still * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation * is still present and it is used for group structures not supported by the * alternative. * * The original implementation can in addition be removed by setting the * MBEDTLS_ECP_NO_FALLBACK option, in which case any function for which the * corresponding MBEDTLS_ECP__FUNCTION_NAME__ALT macro is defined will not be * able to fallback to curves not supported by the alternative implementation. * * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT * and implementing the following functions: * unsigned char mbedtls_internal_ecp_grp_capable( * const mbedtls_ecp_group *grp ) * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) * The mbedtls_internal_ecp_grp_capable function should return 1 if the * replacement functions implement arithmetic for the given group and 0 * otherwise. * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are * called before and after each point operation and provide an opportunity to * implement optimized set up and tear down instructions. * * Example: In case you set MBEDTLS_ECP_INTERNAL_ALT and * MBEDTLS_ECP_DOUBLE_JAC_ALT, Mbed TLS will still provide the ecp_double_jac() * function, but will use your mbedtls_internal_ecp_double_jac() if the group * for the operation is supported by your implementation (i.e. your * mbedtls_internal_ecp_grp_capable() function returns 1 for this group). If the * group is not supported by your implementation, then the original Mbed TLS * implementation of ecp_double_jac() is used instead, unless this fallback * behaviour is disabled by setting MBEDTLS_ECP_NO_FALLBACK (in which case * ecp_double_jac() will return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE). * * The function prototypes and the definition of mbedtls_ecp_group and * mbedtls_ecp_point will not change based on MBEDTLS_ECP_INTERNAL_ALT, so your * implementation of mbedtls_internal_ecp__function_name__ must be compatible * with their definitions. * * Uncomment a macro to enable alternate implementation of the corresponding * function. */ /* Required for all the functions in this section */ //#define MBEDTLS_ECP_INTERNAL_ALT /* Turn off software fallback for curves not supported in hardware */ //#define MBEDTLS_ECP_NO_FALLBACK /* Support for Weierstrass curves with Jacobi representation */ //#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT //#define MBEDTLS_ECP_ADD_MIXED_ALT //#define MBEDTLS_ECP_DOUBLE_JAC_ALT //#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT //#define MBEDTLS_ECP_NORMALIZE_JAC_ALT /* Support for curves with Montgomery arithmetic */ //#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT //#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT //#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT /** * \def MBEDTLS_ENTROPY_HARDWARE_ALT * * Uncomment this macro to let Mbed TLS use your own implementation of a * hardware entropy collector. * * Your function must be called \c mbedtls_hardware_poll(), have the same * prototype as declared in library/entropy_poll.h, and accept NULL as first * argument. * * Uncomment to use your own hardware entropy collector. */ //#define MBEDTLS_ENTROPY_HARDWARE_ALT /** * \def MBEDTLS_AES_ROM_TABLES * * Use precomputed AES tables stored in ROM. * * Uncomment this macro to use precomputed AES tables stored in ROM. * Comment this macro to generate AES tables in RAM at runtime. * * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the * initialization time before the first AES operation can be performed. * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded * performance if ROM access is slower than RAM access. * * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. */ //#define MBEDTLS_AES_ROM_TABLES /** * \def MBEDTLS_AES_FEWER_TABLES * * Use less ROM/RAM for AES tables. * * Uncommenting this macro omits 75% of the AES tables from * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) * by computing their values on the fly during operations * (the tables are entry-wise rotations of one another). * * Tradeoff: Uncommenting this reduces the RAM / ROM footprint * by ~6kb but at the cost of more arithmetic operations during * runtime. Specifically, one has to compare 4 accesses within * different tables to 4 accesses with additional arithmetic * operations within the same table. The performance gain/loss * depends on the system and memory details. * * This option is independent of \c MBEDTLS_AES_ROM_TABLES. */ //#define MBEDTLS_AES_FEWER_TABLES /** * \def MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH * * Use only 128-bit keys in AES operations to save ROM. * * Uncomment this macro to remove support for AES operations that use 192- * or 256-bit keys. * * Uncommenting this macro reduces the size of AES code by ~300 bytes * on v8-M/Thumb2. * * Module: library/aes.c * * Requires: MBEDTLS_AES_C */ //#define MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH /* * Disable plain C implementation for AES. * * When the plain C implementation is enabled, and an implementation using a * special CPU feature (such as MBEDTLS_AESCE_C) is also enabled, runtime * detection will be used to select between them. * * If only one implementation is present, runtime detection will not be used. * This configuration will crash at runtime if running on a CPU without the * necessary features. It will not build unless at least one of MBEDTLS_AESCE_C * and/or MBEDTLS_AESNI_C is enabled & present in the build. */ //#define MBEDTLS_AES_USE_HARDWARE_ONLY /** * \def MBEDTLS_CAMELLIA_SMALL_MEMORY * * Use less ROM for the Camellia implementation (saves about 768 bytes). * * Uncomment this macro to use less memory for Camellia. */ //#define MBEDTLS_CAMELLIA_SMALL_MEMORY /** * \def MBEDTLS_CHECK_RETURN_WARNING * * If this macro is defined, emit a compile-time warning if application code * calls a function without checking its return value, but the return value * should generally be checked in portable applications. * * This is only supported on platforms where #MBEDTLS_CHECK_RETURN is * implemented. Otherwise this option has no effect. * * Uncomment to get warnings on using fallible functions without checking * their return value. * * \note This feature is a work in progress. * Warnings will be added to more functions in the future. * * \note A few functions are considered critical, and ignoring the return * value of these functions will trigger a warning even if this * macro is not defined. To completely disable return value check * warnings, define #MBEDTLS_CHECK_RETURN with an empty expansion. */ //#define MBEDTLS_CHECK_RETURN_WARNING /** * \def MBEDTLS_CIPHER_MODE_CBC * * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. */ #define MBEDTLS_CIPHER_MODE_CBC /** * \def MBEDTLS_CIPHER_MODE_CFB * * Enable Cipher Feedback mode (CFB) for symmetric ciphers. */ #define MBEDTLS_CIPHER_MODE_CFB /** * \def MBEDTLS_CIPHER_MODE_CTR * * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. */ #define MBEDTLS_CIPHER_MODE_CTR /** * \def MBEDTLS_CIPHER_MODE_OFB * * Enable Output Feedback mode (OFB) for symmetric ciphers. */ #define MBEDTLS_CIPHER_MODE_OFB /** * \def MBEDTLS_CIPHER_MODE_XTS * * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. */ #define MBEDTLS_CIPHER_MODE_XTS /** * \def MBEDTLS_CIPHER_NULL_CIPHER * * Enable NULL cipher. * Warning: Only do so when you know what you are doing. This allows for * encryption or channels without any security! * * To enable the following ciphersuites: * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 * MBEDTLS_TLS_RSA_WITH_NULL_SHA * MBEDTLS_TLS_RSA_WITH_NULL_MD5 * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 * MBEDTLS_TLS_PSK_WITH_NULL_SHA * * Uncomment this macro to enable the NULL cipher and ciphersuites */ //#define MBEDTLS_CIPHER_NULL_CIPHER /** * \def MBEDTLS_CIPHER_PADDING_PKCS7 * * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for * specific padding modes in the cipher layer with cipher modes that support * padding (e.g. CBC) * * If you disable all padding modes, only full blocks can be used with CBC. * * Enable padding modes in the cipher layer. */ #define MBEDTLS_CIPHER_PADDING_PKCS7 #define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS #define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN #define MBEDTLS_CIPHER_PADDING_ZEROS /** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY * * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. * Without this, CTR_DRBG uses a 256-bit key * unless \c MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH is set. */ //#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /** * Enable the verified implementations of ECDH primitives from Project Everest * (currently only Curve25519). This feature changes the layout of ECDH * contexts and therefore is a compatibility break for applications that access * fields of a mbedtls_ecdh_context structure directly. See also * MBEDTLS_ECDH_LEGACY_CONTEXT in include/mbedtls/ecdh.h. * * The Everest code is provided under the Apache 2.0 license only; therefore enabling this * option is not compatible with taking the library under the GPL v2.0-or-later license. */ //#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED /** * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED * * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve * module. By default all supported curves are enabled. * * Comment macros to disable the curve and functions for it */ /* Short Weierstrass curves (supporting ECP, ECDH, ECDSA) */ #define MBEDTLS_ECP_DP_SECP192R1_ENABLED #define MBEDTLS_ECP_DP_SECP224R1_ENABLED #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_ECP_DP_SECP384R1_ENABLED #define MBEDTLS_ECP_DP_SECP521R1_ENABLED #define MBEDTLS_ECP_DP_SECP192K1_ENABLED #define MBEDTLS_ECP_DP_SECP224K1_ENABLED #define MBEDTLS_ECP_DP_SECP256K1_ENABLED #define MBEDTLS_ECP_DP_BP256R1_ENABLED #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED /* Montgomery curves (supporting ECP) */ #define MBEDTLS_ECP_DP_CURVE25519_ENABLED #define MBEDTLS_ECP_DP_CURVE448_ENABLED /** * \def MBEDTLS_ECP_NIST_OPTIM * * Enable specific 'modulo p' routines for each NIST prime. * Depending on the prime and architecture, makes operations 4 to 8 times * faster on the corresponding curve. * * Comment this macro to disable NIST curves optimisation. */ #define MBEDTLS_ECP_NIST_OPTIM /** * \def MBEDTLS_ECP_RESTARTABLE * * Enable "non-blocking" ECC operations that can return early and be resumed. * * This allows various functions to pause by returning * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in * order to further progress and eventually complete their operation. This is * controlled through mbedtls_ecp_set_max_ops() which limits the maximum * number of ECC operations a function may perform before pausing; see * mbedtls_ecp_set_max_ops() for more information. * * This is useful in non-threaded environments if you want to avoid blocking * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. * * This option: * - Adds xxx_restartable() variants of existing operations in the * following modules, with corresponding restart context types: * - ECP (for Short Weierstrass curves only): scalar multiplication (mul), * linear combination (muladd); * - ECDSA: signature generation & verification; * - PK: signature generation & verification; * - X509: certificate chain verification. * - Adds mbedtls_ecdh_enable_restart() in the ECDH module. * - Changes the behaviour of TLS 1.2 clients (not servers) when using the * ECDHE-ECDSA key exchange (not other key exchanges) to make all ECC * computations restartable: * - ECDH operations from the key exchange, only for Short Weierstrass * curves, only when MBEDTLS_USE_PSA_CRYPTO is not enabled. * - verification of the server's key exchange signature; * - verification of the server's certificate chain; * - generation of the client's signature if client authentication is used, * with an ECC key/certificate. * * \note In the cases above, the usual SSL/TLS functions, such as * mbedtls_ssl_handshake(), can now return * MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS. * * \note When this option and MBEDTLS_USE_PSA_CRYPTO are both enabled, * restartable operations in PK, X.509 and TLS (see above) are not * using PSA. On the other hand, ECDH computations in TLS are using * PSA, and are not restartable. These are temporary limitations that * should be lifted in the future. * * \note This option only works with the default software implementation of * elliptic curve functionality. It is incompatible with * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT. * * Requires: MBEDTLS_ECP_C * * Uncomment this macro to enable restartable ECC computations. */ //#define MBEDTLS_ECP_RESTARTABLE /** * Uncomment to enable using new bignum code in the ECC modules. * * \warning This is currently experimental, incomplete and therefore should not * be used in production. */ //#define MBEDTLS_ECP_WITH_MPI_UINT /** * \def MBEDTLS_ECDSA_DETERMINISTIC * * Enable deterministic ECDSA (RFC 6979). * Standard ECDSA is "fragile" in the sense that lack of entropy when signing * may result in a compromise of the long-term signing key. This is avoided by * the deterministic variant. * * Requires: MBEDTLS_HMAC_DRBG_C, MBEDTLS_ECDSA_C * * Comment this macro to disable deterministic ECDSA. */ #define MBEDTLS_ECDSA_DETERMINISTIC /** * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED * * Enable the PSK based ciphersuite modes in SSL / TLS. * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 */ #define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED * * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. * * Requires: MBEDTLS_DHM_C * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 * * \warning Using DHE constitutes a security risk as it * is not possible to validate custom DH parameters. * If possible, it is recommended users should consider * preferring other methods of key exchange. * See dhm.h for more details. * */ #define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED * * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. * * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 */ #define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED * * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. * * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 */ #define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED * * Enable the RSA-only based ciphersuite modes in SSL / TLS. * * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA */ #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED * * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. * * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA * * \warning Using DHE constitutes a security risk as it * is not possible to validate custom DH parameters. * If possible, it is recommended users should consider * preferring other methods of key exchange. * See dhm.h for more details. * */ #define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED * * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. * * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) * MBEDTLS_RSA_C * MBEDTLS_PKCS1_V15 * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 */ #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED * * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. * * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) * MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA) * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 */ #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED * * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. * * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) * MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA) * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 */ #define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED * * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. * * Requires: MBEDTLS_ECDH_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDH) * MBEDTLS_RSA_C * MBEDTLS_X509_CRT_PARSE_C * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 */ #define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED /** * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED * * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. * * \warning This is currently experimental. EC J-PAKE support is based on the * Thread v1.0.0 specification; incompatible changes to the specification * might still happen. For this reason, this is disabled by default. * * Requires: MBEDTLS_ECJPAKE_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_JPAKE) * SHA-256 (via MBEDTLS_SHA256_C or a PSA driver) * MBEDTLS_ECP_DP_SECP256R1_ENABLED * * \warning If SHA-256 is provided only by a PSA driver, you must call * psa_crypto_init() before the first handshake (even if * MBEDTLS_USE_PSA_CRYPTO is disabled). * * This enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 */ //#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED /** * \def MBEDTLS_PK_PARSE_EC_EXTENDED * * Enhance support for reading EC keys using variants of SEC1 not allowed by * RFC 5915 and RFC 5480. * * Currently this means parsing the SpecifiedECDomain choice of EC * parameters (only known groups are supported, not arbitrary domains, to * avoid validation issues). * * Disable if you only need to support RFC 5915 + 5480 key formats. */ #define MBEDTLS_PK_PARSE_EC_EXTENDED /** * \def MBEDTLS_PK_PARSE_EC_COMPRESSED * * Enable the support for parsing public keys of type Short Weierstrass * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX) which are using the * compressed point format. This parsing is done through ECP module's functions. * * \note As explained in the description of MBEDTLS_ECP_PF_COMPRESSED (in ecp.h) * the only unsupported curves are MBEDTLS_ECP_DP_SECP224R1 and * MBEDTLS_ECP_DP_SECP224K1. */ #define MBEDTLS_PK_PARSE_EC_COMPRESSED /** * \def MBEDTLS_ERROR_STRERROR_DUMMY * * Enable a dummy error function to make use of mbedtls_strerror() in * third party libraries easier when MBEDTLS_ERROR_C is disabled * (no effect when MBEDTLS_ERROR_C is enabled). * * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're * not using mbedtls_strerror() or error_strerror() in your application. * * Disable if you run into name conflicts and want to really remove the * mbedtls_strerror() */ #define MBEDTLS_ERROR_STRERROR_DUMMY /** * \def MBEDTLS_GENPRIME * * Enable the prime-number generation code. * * Requires: MBEDTLS_BIGNUM_C */ #define MBEDTLS_GENPRIME /** * \def MBEDTLS_FS_IO * * Enable functions that use the filesystem. */ #define MBEDTLS_FS_IO /** * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES * * Do not add default entropy sources in mbedtls_entropy_init(). * * This is useful to have more control over the added entropy sources in an * application. * * Uncomment this macro to prevent loading of default entropy functions. */ //#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES /** * \def MBEDTLS_NO_PLATFORM_ENTROPY * * Do not use built-in platform entropy functions. * This is useful if your platform does not support * standards like the /dev/urandom or Windows CryptoAPI. * * Uncomment this macro to disable the built-in platform entropy functions. */ //#define MBEDTLS_NO_PLATFORM_ENTROPY /** * \def MBEDTLS_ENTROPY_FORCE_SHA256 * * Force the entropy accumulator to use a SHA-256 accumulator instead of the * default SHA-512 based one (if both are available). * * Requires: MBEDTLS_SHA256_C * * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option * if you have performance concerns. * * This option is only useful if both MBEDTLS_SHA256_C and * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. */ //#define MBEDTLS_ENTROPY_FORCE_SHA256 /** * \def MBEDTLS_ENTROPY_NV_SEED * * Enable the non-volatile (NV) seed file-based entropy source. * (Also enables the NV seed read/write functions in the platform layer) * * This is crucial (if not required) on systems that do not have a * cryptographic entropy source (in hardware or kernel) available. * * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C * * \note The read/write functions that are used by the entropy source are * determined in the platform layer, and can be modified at runtime and/or * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. * * \note If you use the default implementation functions that read a seedfile * with regular fopen(), please make sure you make a seedfile with the * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from * and written to or you will get an entropy source error! The default * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE * bytes from the file. * * \note The entropy collector will write to the seed file before entropy is * given to an external source, to update it. */ //#define MBEDTLS_ENTROPY_NV_SEED /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER * * Enable key identifiers that encode a key owner identifier. * * The owner of a key is identified by a value of type ::mbedtls_key_owner_id_t * which is currently hard-coded to be int32_t. * * Note that this option is meant for internal use only and may be removed * without notice. */ //#define MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER /** * \def MBEDTLS_MEMORY_DEBUG * * Enable debugging of buffer allocator memory issues. Automatically prints * (to stderr) all (fatal) messages on memory allocation issues. Enables * function for 'debug output' of allocated memory. * * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C * * Uncomment this macro to let the buffer allocator print out error messages. */ //#define MBEDTLS_MEMORY_DEBUG /** * \def MBEDTLS_MEMORY_BACKTRACE * * Include backtrace information with each allocated block. * * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C * GLIBC-compatible backtrace() and backtrace_symbols() support * * Uncomment this macro to include backtrace information */ //#define MBEDTLS_MEMORY_BACKTRACE /** * \def MBEDTLS_PK_RSA_ALT_SUPPORT * * Support external private RSA keys (eg from a HSM) in the PK layer. * * Comment this macro to disable support for external private RSA keys. */ #define MBEDTLS_PK_RSA_ALT_SUPPORT /** * \def MBEDTLS_PKCS1_V15 * * Enable support for PKCS#1 v1.5 encoding. * * Requires: MBEDTLS_RSA_C * * This enables support for PKCS#1 v1.5 operations. */ #define MBEDTLS_PKCS1_V15 /** * \def MBEDTLS_PKCS1_V21 * * Enable support for PKCS#1 v2.1 encoding. * * Requires: MBEDTLS_RSA_C * * \warning If using a hash that is only provided by PSA drivers, you must * call psa_crypto_init() before doing any PKCS#1 v2.1 operation. * * This enables support for RSAES-OAEP and RSASSA-PSS operations. */ #define MBEDTLS_PKCS1_V21 /** \def MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS * * Enable support for platform built-in keys. If you enable this feature, * you must implement the function mbedtls_psa_platform_get_builtin_key(). * See the documentation of that function for more information. * * Built-in keys are typically derived from a hardware unique key or * stored in a secure element. * * Requires: MBEDTLS_PSA_CRYPTO_C. * * \warning This interface is experimental and may change or be removed * without notice. */ //#define MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS /** \def MBEDTLS_PSA_CRYPTO_CLIENT * * Enable support for PSA crypto client. * * \note This option allows to include the code necessary for a PSA * crypto client when the PSA crypto implementation is not included in * the library (MBEDTLS_PSA_CRYPTO_C disabled). The code included is the * code to set and get PSA key attributes. * The development of PSA drivers partially relying on the library to * fulfill the hardware gaps is another possible usage of this option. * * \warning This interface is experimental and may change or be removed * without notice. */ //#define MBEDTLS_PSA_CRYPTO_CLIENT /** \def MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG * * Make the PSA Crypto module use an external random generator provided * by a driver, instead of Mbed TLS's entropy and DRBG modules. * * \note This random generator must deliver random numbers with cryptographic * quality and high performance. It must supply unpredictable numbers * with a uniform distribution. The implementation of this function * is responsible for ensuring that the random generator is seeded * with sufficient entropy. If you have a hardware TRNG which is slow * or delivers non-uniform output, declare it as an entropy source * with mbedtls_entropy_add_source() instead of enabling this option. * * If you enable this option, you must configure the type * ::mbedtls_psa_external_random_context_t in psa/crypto_platform.h * and define a function called mbedtls_psa_external_get_random() * with the following prototype: * ``` * psa_status_t mbedtls_psa_external_get_random( * mbedtls_psa_external_random_context_t *context, * uint8_t *output, size_t output_size, size_t *output_length); * ); * ``` * The \c context value is initialized to 0 before the first call. * The function must fill the \c output buffer with \c output_size bytes * of random data and set \c *output_length to \c output_size. * * Requires: MBEDTLS_PSA_CRYPTO_C * * \warning If you enable this option, code that uses the PSA cryptography * interface will not use any of the entropy sources set up for * the entropy module, nor the NV seed that MBEDTLS_ENTROPY_NV_SEED * enables. * * \note This option is experimental and may be removed without notice. */ //#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG /** * \def MBEDTLS_PSA_CRYPTO_SPM * * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure * Partition Manager) integration which separates the code into two parts: a * NSPE (Non-Secure Process Environment) and an SPE (Secure Process * Environment). * * If you enable this option, your build environment must include a header * file `"crypto_spe.h"` (either in the `psa` subdirectory of the Mbed TLS * header files, or in another directory on the compiler's include search * path). Alternatively, your platform may customize the header * `psa/crypto_platform.h`, in which case it can skip or replace the * inclusion of `"crypto_spe.h"`. * * Module: library/psa_crypto.c * Requires: MBEDTLS_PSA_CRYPTO_C * */ //#define MBEDTLS_PSA_CRYPTO_SPM /** * \def MBEDTLS_PSA_KEY_STORE_DYNAMIC * * Dynamically resize the PSA key store to accommodate any number of * volatile keys (until the heap memory is exhausted). * * If this option is disabled, the key store has a fixed size * #MBEDTLS_PSA_KEY_SLOT_COUNT for volatile keys and loaded persistent keys * together. * * This option has no effect when #MBEDTLS_PSA_CRYPTO_C is disabled. * * Module: library/psa_crypto.c * Requires: MBEDTLS_PSA_CRYPTO_C */ #define MBEDTLS_PSA_KEY_STORE_DYNAMIC /** * Uncomment to enable p256-m. This is an alternative implementation of * key generation, ECDH and (randomized) ECDSA on the curve SECP256R1. * Compared to the default implementation: * * - p256-m has a much smaller code size and RAM footprint. * - p256-m is only available via the PSA API. This includes the pk module * when #MBEDTLS_USE_PSA_CRYPTO is enabled. * - p256-m does not support deterministic ECDSA, EC-JPAKE, custom protocols * over the core arithmetic, or deterministic derivation of keys. * * We recommend enabling this option if your application uses the PSA API * and the only elliptic curve support it needs is ECDH and ECDSA over * SECP256R1. * * If you enable this option, you do not need to enable any ECC-related * MBEDTLS_xxx option. You do need to separately request support for the * cryptographic mechanisms through the PSA API: * - #MBEDTLS_PSA_CRYPTO_C and #MBEDTLS_PSA_CRYPTO_CONFIG for PSA-based * configuration; * - #MBEDTLS_USE_PSA_CRYPTO if you want to use p256-m from PK, X.509 or TLS; * - #PSA_WANT_ECC_SECP_R1_256; * - #PSA_WANT_ALG_ECDH and/or #PSA_WANT_ALG_ECDSA as needed; * - #PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY, #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC, * #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT, * #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT and/or * #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE as needed. * * \note To benefit from the smaller code size of p256-m, make sure that you * do not enable any ECC-related option not supported by p256-m: this * would cause the built-in ECC implementation to be built as well, in * order to provide the required option. * Make sure #PSA_WANT_ALG_DETERMINISTIC_ECDSA, #PSA_WANT_ALG_JPAKE and * #PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE, and curves other than * SECP256R1 are disabled as they are not supported by this driver. * Also, avoid defining #MBEDTLS_PK_PARSE_EC_COMPRESSED or * #MBEDTLS_PK_PARSE_EC_EXTENDED as those currently require a subset of * the built-in ECC implementation, see docs/driver-only-builds.md. */ //#define MBEDTLS_PSA_P256M_DRIVER_ENABLED /** * \def MBEDTLS_PSA_INJECT_ENTROPY * * Enable support for entropy injection at first boot. This feature is * required on systems that do not have a built-in entropy source (TRNG). * This feature is currently not supported on systems that have a built-in * entropy source. * * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED * */ //#define MBEDTLS_PSA_INJECT_ENTROPY /** * \def MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS * * Assume all buffers passed to PSA functions are owned exclusively by the * PSA function and are not stored in shared memory. * * This option may be enabled if all buffers passed to any PSA function reside * in memory that is accessible only to the PSA function during its execution. * * This option MUST be disabled whenever buffer arguments are in memory shared * with an untrusted party, for example where arguments to PSA calls are passed * across a trust boundary. * * \note Enabling this option reduces memory usage and code size. * * \note Enabling this option causes overlap of input and output buffers * not to be supported by PSA functions. */ //#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS /** * \def MBEDTLS_RSA_NO_CRT * * Do not use the Chinese Remainder Theorem * for the RSA private operation. * * Uncomment this macro to disable the use of CRT in RSA. * */ //#define MBEDTLS_RSA_NO_CRT /** * \def MBEDTLS_SELF_TEST * * Enable the checkup functions (*_self_test). */ #define MBEDTLS_SELF_TEST /** * \def MBEDTLS_SHA256_SMALLER * * Enable an implementation of SHA-256 that has lower ROM footprint but also * lower performance. * * The default implementation is meant to be a reasonable compromise between * performance and size. This version optimizes more aggressively for size at * the expense of performance. Eg on Cortex-M4 it reduces the size of * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about * 30%. * * Uncomment to enable the smaller implementation of SHA256. */ //#define MBEDTLS_SHA256_SMALLER /** * \def MBEDTLS_SHA512_SMALLER * * Enable an implementation of SHA-512 that has lower ROM footprint but also * lower performance. * * Uncomment to enable the smaller implementation of SHA512. */ //#define MBEDTLS_SHA512_SMALLER /** * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES * * Enable sending of alert messages in case of encountered errors as per RFC. * If you choose not to send the alert messages, Mbed TLS can still communicate * with other servers, only debugging of failures is harder. * * The advantage of not sending alert messages, is that no information is given * about reasons for failures thus preventing adversaries of gaining intel. * * Enable sending of all alert messages */ #define MBEDTLS_SSL_ALL_ALERT_MESSAGES /** * \def MBEDTLS_SSL_DTLS_CONNECTION_ID * * Enable support for the DTLS Connection ID (CID) extension, * which allows to identify DTLS connections across changes * in the underlying transport. The CID functionality is described * in RFC 9146. * * Setting this option enables the SSL APIs `mbedtls_ssl_set_cid()`, * mbedtls_ssl_get_own_cid()`, `mbedtls_ssl_get_peer_cid()` and * `mbedtls_ssl_conf_cid()`. See the corresponding documentation for * more information. * * The maximum lengths of outgoing and incoming CIDs can be configured * through the options * - MBEDTLS_SSL_CID_OUT_LEN_MAX * - MBEDTLS_SSL_CID_IN_LEN_MAX. * * Requires: MBEDTLS_SSL_PROTO_DTLS * * Uncomment to enable the Connection ID extension. */ #define MBEDTLS_SSL_DTLS_CONNECTION_ID /** * \def MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT * * Defines whether RFC 9146 (default) or the legacy version * (version draft-ietf-tls-dtls-connection-id-05, * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) * is used. * * Set the value to 0 for the standard version, and * 1 for the legacy draft version. * * \deprecated Support for the legacy version of the DTLS * Connection ID feature is deprecated. Please * switch to the standardized version defined * in RFC 9146 enabled by utilizing * MBEDTLS_SSL_DTLS_CONNECTION_ID without use * of MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT. * * Requires: MBEDTLS_SSL_DTLS_CONNECTION_ID */ #define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0 /** * \def MBEDTLS_SSL_ASYNC_PRIVATE * * Enable asynchronous external private key operations in SSL. This allows * you to configure an SSL connection to call an external cryptographic * module to perform private key operations instead of performing the * operation inside the library. * * Requires: MBEDTLS_X509_CRT_PARSE_C */ //#define MBEDTLS_SSL_ASYNC_PRIVATE /** * \def MBEDTLS_SSL_CONTEXT_SERIALIZATION * * Enable serialization of the TLS context structures, through use of the * functions mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). * * This pair of functions allows one side of a connection to serialize the * context associated with the connection, then free or re-use that context * while the serialized state is persisted elsewhere, and finally deserialize * that state to a live context for resuming read/write operations on the * connection. From a protocol perspective, the state of the connection is * unaffected, in particular this is entirely transparent to the peer. * * Note: this is distinct from TLS session resumption, which is part of the * protocol and fully visible by the peer. TLS session resumption enables * establishing new connections associated to a saved session with shorter, * lighter handshakes, while context serialization is a local optimization in * handling a single, potentially long-lived connection. * * Enabling these APIs makes some SSL structures larger, as 64 extra bytes are * saved after the handshake to allow for more efficient serialization, so if * you don't need this feature you'll save RAM by disabling it. * * Requires: MBEDTLS_GCM_C or MBEDTLS_CCM_C or MBEDTLS_CHACHAPOLY_C * * Comment to disable the context serialization APIs. */ #define MBEDTLS_SSL_CONTEXT_SERIALIZATION /** * \def MBEDTLS_SSL_DEBUG_ALL * * Enable the debug messages in SSL module for all issues. * Debug messages have been disabled in some places to prevent timing * attacks due to (unbalanced) debugging function calls. * * If you need all error reporting you should enable this during debugging, * but remove this for production servers that should log as well. * * Uncomment this macro to report all debug messages on errors introducing * a timing side-channel. * */ //#define MBEDTLS_SSL_DEBUG_ALL /** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC * * Enable support for Encrypt-then-MAC, RFC 7366. * * This allows peers that both support it to use a more robust protection for * ciphersuites using CBC, providing deep resistance against timing attacks * on the padding or underlying cipher. * * This only affects CBC ciphersuites, and is useless if none is defined. * * Requires: MBEDTLS_SSL_PROTO_TLS1_2 * * Comment this macro to disable support for Encrypt-then-MAC */ #define MBEDTLS_SSL_ENCRYPT_THEN_MAC /** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET * * Enable support for RFC 7627: Session Hash and Extended Master Secret * Extension. * * This was introduced as "the proper fix" to the Triple Handshake family of * attacks, but it is recommended to always use it (even if you disable * renegotiation), since it actually fixes a more fundamental issue in the * original SSL/TLS design, and has implications beyond Triple Handshake. * * Requires: MBEDTLS_SSL_PROTO_TLS1_2 * * Comment this macro to disable support for Extended Master Secret. */ #define MBEDTLS_SSL_EXTENDED_MASTER_SECRET /** * \def MBEDTLS_SSL_KEEP_PEER_CERTIFICATE * * This option controls the availability of the API mbedtls_ssl_get_peer_cert() * giving access to the peer's certificate after completion of the handshake. * * Unless you need mbedtls_ssl_peer_cert() in your application, it is * recommended to disable this option for reduced RAM usage. * * \note If this option is disabled, mbedtls_ssl_get_peer_cert() is still * defined, but always returns \c NULL. * * \note This option has no influence on the protection against the * triple handshake attack. Even if it is disabled, Mbed TLS will * still ensure that certificates do not change during renegotiation, * for example by keeping a hash of the peer's certificate. * * \note This option is required if MBEDTLS_SSL_PROTO_TLS1_3 is set. * * Comment this macro to disable storing the peer's certificate * after the handshake. */ #define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE /** * \def MBEDTLS_SSL_RENEGOTIATION * * Enable support for TLS renegotiation. * * The two main uses of renegotiation are (1) refresh keys on long-lived * connections and (2) client authentication after the initial handshake. * If you don't need renegotiation, it's probably better to disable it, since * it has been associated with security issues in the past and is easy to * misuse/misunderstand. * * Requires: MBEDTLS_SSL_PROTO_TLS1_2 * * Comment this to disable support for renegotiation. * * \note Even if this option is disabled, both client and server are aware * of the Renegotiation Indication Extension (RFC 5746) used to * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). * (See \c mbedtls_ssl_conf_legacy_renegotiation for the * configuration of this extension). * */ #define MBEDTLS_SSL_RENEGOTIATION /** * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH * * Enable support for RFC 6066 max_fragment_length extension in SSL. * * Comment this macro to disable support for the max_fragment_length extension */ #define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH /** * \def MBEDTLS_SSL_RECORD_SIZE_LIMIT * * Enable support for RFC 8449 record_size_limit extension in SSL (TLS 1.3 only). * * Requires: MBEDTLS_SSL_PROTO_TLS1_3 * * Uncomment this macro to enable support for the record_size_limit extension */ //#define MBEDTLS_SSL_RECORD_SIZE_LIMIT /** * \def MBEDTLS_SSL_PROTO_TLS1_2 * * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). * * Requires: Without MBEDTLS_USE_PSA_CRYPTO: MBEDTLS_MD_C and * (MBEDTLS_SHA256_C or MBEDTLS_SHA384_C or * SHA-256 or SHA-512 provided by a PSA driver) * With MBEDTLS_USE_PSA_CRYPTO: * PSA_WANT_ALG_SHA_256 or PSA_WANT_ALG_SHA_384 * * \warning If building with MBEDTLS_USE_PSA_CRYPTO, or if the hash(es) used * are only provided by PSA drivers, you must call psa_crypto_init() before * doing any TLS operations. * * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 */ #define MBEDTLS_SSL_PROTO_TLS1_2 /** * \def MBEDTLS_SSL_PROTO_TLS1_3 * * Enable support for TLS 1.3. * * \note See docs/architecture/tls13-support.md for a description of the TLS * 1.3 support that this option enables. * * Requires: MBEDTLS_SSL_KEEP_PEER_CERTIFICATE * Requires: MBEDTLS_PSA_CRYPTO_C * * \note TLS 1.3 uses PSA crypto for cryptographic operations that are * directly performed by TLS 1.3 code. As a consequence, when TLS 1.3 * is enabled, a TLS handshake may call psa_crypto_init(), even * if it ends up negotiating a different TLS version. * * \note Cryptographic operations performed indirectly via another module * (X.509, PK) or by code shared with TLS 1.2 (record protection, * running handshake hash) only use PSA crypto if * #MBEDTLS_USE_PSA_CRYPTO is enabled. * * Uncomment this macro to enable the support for TLS 1.3. */ #define MBEDTLS_SSL_PROTO_TLS1_3 /** * \def MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE * * Enable TLS 1.3 middlebox compatibility mode. * * As specified in Section D.4 of RFC 8446, TLS 1.3 offers a compatibility * mode to make a TLS 1.3 connection more likely to pass through middle boxes * expecting TLS 1.2 traffic. * * Turning on the compatibility mode comes at the cost of a few added bytes * on the wire, but it doesn't affect compatibility with TLS 1.3 implementations * that don't use it. Therefore, unless transmission bandwidth is critical and * you know that middlebox compatibility issues won't occur, it is therefore * recommended to set this option. * * Comment to disable compatibility mode for TLS 1.3. If * MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any * effect on the build. * */ #define MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE /** * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED * * Enable TLS 1.3 PSK key exchange mode. * * Comment to disable support for the PSK key exchange mode in TLS 1.3. If * MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any * effect on the build. * */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED /** * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED * * Enable TLS 1.3 ephemeral key exchange mode. * * Requires: PSA_WANT_ALG_ECDH or PSA_WANT_ALG_FFDH * MBEDTLS_X509_CRT_PARSE_C * and at least one of: * MBEDTLS_ECDSA_C or (MBEDTLS_USE_PSA_CRYPTO and PSA_WANT_ALG_ECDSA) * MBEDTLS_PKCS1_V21 * * Comment to disable support for the ephemeral key exchange mode in TLS 1.3. * If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any * effect on the build. * */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED /** * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED * * Enable TLS 1.3 PSK ephemeral key exchange mode. * * Requires: PSA_WANT_ALG_ECDH or PSA_WANT_ALG_FFDH * * Comment to disable support for the PSK ephemeral key exchange mode in * TLS 1.3. If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not * have any effect on the build. * */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED /** * \def MBEDTLS_SSL_EARLY_DATA * * Enable support for RFC 8446 TLS 1.3 early data. * * Requires: MBEDTLS_SSL_SESSION_TICKETS and either * MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED or * MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED * * Comment this to disable support for early data. If MBEDTLS_SSL_PROTO_TLS1_3 * is not enabled, this option does not have any effect on the build. * * \note The maximum amount of early data can be set with * MBEDTLS_SSL_MAX_EARLY_DATA_SIZE. * */ //#define MBEDTLS_SSL_EARLY_DATA /** * \def MBEDTLS_SSL_PROTO_DTLS * * Enable support for DTLS (all available versions). * * Enable this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. * * Requires: MBEDTLS_SSL_PROTO_TLS1_2 * * Comment this macro to disable support for DTLS */ #define MBEDTLS_SSL_PROTO_DTLS /** * \def MBEDTLS_SSL_ALPN * * Enable support for RFC 7301 Application Layer Protocol Negotiation. * * Comment this macro to disable support for ALPN. */ #define MBEDTLS_SSL_ALPN /** * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY * * Enable support for the anti-replay mechanism in DTLS. * * Requires: MBEDTLS_SSL_TLS_C * MBEDTLS_SSL_PROTO_DTLS * * \warning Disabling this is often a security risk! * See mbedtls_ssl_conf_dtls_anti_replay() for details. * * Comment this to disable anti-replay in DTLS. */ #define MBEDTLS_SSL_DTLS_ANTI_REPLAY /** * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY * * Enable support for HelloVerifyRequest on DTLS servers. * * This feature is highly recommended to prevent DTLS servers being used as * amplifiers in DoS attacks against other hosts. It should always be enabled * unless you know for sure amplification cannot be a problem in the * environment in which your server operates. * * \warning Disabling this can be a security risk! (see above) * * Requires: MBEDTLS_SSL_PROTO_DTLS * * Comment this to disable support for HelloVerifyRequest. */ #define MBEDTLS_SSL_DTLS_HELLO_VERIFY /** * \def MBEDTLS_SSL_DTLS_SRTP * * Enable support for negotiation of DTLS-SRTP (RFC 5764) * through the use_srtp extension. * * \note This feature provides the minimum functionality required * to negotiate the use of DTLS-SRTP and to allow the derivation of * the associated SRTP packet protection key material. * In particular, the SRTP packet protection itself, as well as the * demultiplexing of RTP and DTLS packets at the datagram layer * (see Section 5 of RFC 5764), are not handled by this feature. * Instead, after successful completion of a handshake negotiating * the use of DTLS-SRTP, the extended key exporter API * mbedtls_ssl_conf_export_keys_cb() should be used to implement * the key exporter described in Section 4.2 of RFC 5764 and RFC 5705 * (this is implemented in the SSL example programs). * The resulting key should then be passed to an SRTP stack. * * Setting this option enables the runtime API * mbedtls_ssl_conf_dtls_srtp_protection_profiles() * through which the supported DTLS-SRTP protection * profiles can be configured. You must call this API at * runtime if you wish to negotiate the use of DTLS-SRTP. * * Requires: MBEDTLS_SSL_PROTO_DTLS * * Uncomment this to enable support for use_srtp extension. */ //#define MBEDTLS_SSL_DTLS_SRTP /** * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE * * Enable server-side support for clients that reconnect from the same port. * * Some clients unexpectedly close the connection and try to reconnect using the * same source port. This needs special support from the server to handle the * new connection securely, as described in section 4.2.8 of RFC 6347. This * flag enables that support. * * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY * * Comment this to disable support for clients reusing the source port. */ #define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE /** * \def MBEDTLS_SSL_SESSION_TICKETS * * Enable support for RFC 5077 session tickets in SSL. * Client-side, provides full support for session tickets (maintenance of a * session store remains the responsibility of the application, though). * Server-side, you also need to provide callbacks for writing and parsing * tickets, including authenticated encryption and key management. Example * callbacks are provided by MBEDTLS_SSL_TICKET_C. * * Comment this macro to disable support for SSL session tickets */ #define MBEDTLS_SSL_SESSION_TICKETS /** * \def MBEDTLS_SSL_SERVER_NAME_INDICATION * * Enable support for RFC 6066 server name indication (SNI) in SSL. * * Requires: MBEDTLS_X509_CRT_PARSE_C * * Comment this macro to disable support for server name indication in SSL */ #define MBEDTLS_SSL_SERVER_NAME_INDICATION /** * \def MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH * * When this option is enabled, the SSL buffer will be resized automatically * based on the negotiated maximum fragment length in each direction. * * Requires: MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ //#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH /** * \def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN * * Enable testing of the constant-flow nature of some sensitive functions with * clang's MemorySanitizer. This causes some existing tests to also test * this non-functional property of the code under test. * * This setting requires compiling with clang -fsanitize=memory. The test * suites can then be run normally. * * \warning This macro is only used for extended testing; it is not considered * part of the library's API, so it may change or disappear at any time. * * Uncomment to enable testing of the constant-flow nature of selected code. */ //#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN /** * \def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND * * Enable testing of the constant-flow nature of some sensitive functions with * valgrind's memcheck tool. This causes some existing tests to also test * this non-functional property of the code under test. * * This setting requires valgrind headers for building, and is only useful for * testing if the tests suites are run with valgrind's memcheck. This can be * done for an individual test suite with 'valgrind ./test_suite_xxx', or when * using CMake, this can be done for all test suites with 'make memcheck'. * * \warning This macro is only used for extended testing; it is not considered * part of the library's API, so it may change or disappear at any time. * * Uncomment to enable testing of the constant-flow nature of selected code. */ //#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND /** * \def MBEDTLS_TEST_HOOKS * * Enable features for invasive testing such as introspection functions and * hooks for fault injection. This enables additional unit tests. * * Merely enabling this feature should not change the behavior of the product. * It only adds new code, and new branching points where the default behavior * is the same as when this feature is disabled. * However, this feature increases the attack surface: there is an added * risk of vulnerabilities, and more gadgets that can make exploits easier. * Therefore this feature must never be enabled in production. * * See `docs/architecture/testing/mbed-crypto-invasive-testing.md` for more * information. * * Uncomment to enable invasive tests. */ //#define MBEDTLS_TEST_HOOKS /** * \def MBEDTLS_THREADING_ALT * * Provide your own alternate threading implementation. * * Requires: MBEDTLS_THREADING_C * * Uncomment this to allow your own alternate threading implementation. */ //#define MBEDTLS_THREADING_ALT /** * \def MBEDTLS_THREADING_PTHREAD * * Enable the pthread wrapper layer for the threading layer. * * Requires: MBEDTLS_THREADING_C * * Uncomment this to enable pthread mutexes. */ //#define MBEDTLS_THREADING_PTHREAD /** * \def MBEDTLS_USE_PSA_CRYPTO * * Make the X.509 and TLS libraries use PSA for cryptographic operations as * much as possible, and enable new APIs for using keys handled by PSA Crypto. * * \note Development of this option is currently in progress, and parts of Mbed * TLS's X.509 and TLS modules are not ported to PSA yet. However, these parts * will still continue to work as usual, so enabling this option should not * break backwards compatibility. * * \warning If you enable this option, you need to call `psa_crypto_init()` * before calling any function from the SSL/TLS, X.509 or PK modules, except * for the various mbedtls_xxx_init() functions which can be called at any time. * * \note An important and desirable effect of this option is that it allows * PK, X.509 and TLS to take advantage of PSA drivers. For example, enabling * this option is what allows use of drivers for ECDSA, ECDH and EC J-PAKE in * those modules. However, note that even with this option disabled, some code * in PK, X.509, TLS or the crypto library might still use PSA drivers, if it * can determine it's safe to do so; currently that's the case for hashes. * * \note See docs/use-psa-crypto.md for a complete description this option. * * Requires: MBEDTLS_PSA_CRYPTO_C. * * Uncomment this to enable internal use of PSA Crypto and new associated APIs. */ //#define MBEDTLS_USE_PSA_CRYPTO /** * \def MBEDTLS_PSA_CRYPTO_CONFIG * * This setting allows support for cryptographic mechanisms through the PSA * API to be configured separately from support through the mbedtls API. * * When this option is disabled, the PSA API exposes the cryptographic * mechanisms that can be implemented on top of the `mbedtls_xxx` API * configured with `MBEDTLS_XXX` symbols. * * When this option is enabled, the PSA API exposes the cryptographic * mechanisms requested by the `PSA_WANT_XXX` symbols defined in * include/psa/crypto_config.h. The corresponding `MBEDTLS_XXX` settings are * automatically enabled if required (i.e. if no PSA driver provides the * mechanism). You may still freely enable additional `MBEDTLS_XXX` symbols * in mbedtls_config.h. * * If the symbol #MBEDTLS_PSA_CRYPTO_CONFIG_FILE is defined, it specifies * an alternative header to include instead of include/psa/crypto_config.h. * * \warning This option is experimental, in that the set of `PSA_WANT_XXX` * symbols is not completely finalized yet, and the configuration * tooling is not ideally adapted to having two separate configuration * files. * Future minor releases of Mbed TLS may make minor changes to those * symbols, but we will endeavor to provide a transition path. * Nonetheless, this option is considered mature enough to use in * production, as long as you accept that you may need to make * minor changes to psa/crypto_config.h when upgrading Mbed TLS. */ //#define MBEDTLS_PSA_CRYPTO_CONFIG /** * \def MBEDTLS_VERSION_FEATURES * * Allow run-time checking of compile-time enabled features. Thus allowing users * to check at run-time if the library is for instance compiled with threading * support via mbedtls_version_check_feature(). * * Requires: MBEDTLS_VERSION_C * * Comment this to disable run-time checking and save ROM space */ #define MBEDTLS_VERSION_FEATURES /** * \def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK * * If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_ca_cb()` * and the SSL API `mbedtls_ssl_conf_ca_cb()` which allow users to configure * the set of trusted certificates through a callback instead of a linked * list. * * This is useful for example in environments where a large number of trusted * certificates is present and storing them in a linked list isn't efficient * enough, or when the set of trusted certificates changes frequently. * * See the documentation of `mbedtls_x509_crt_verify_with_ca_cb()` and * `mbedtls_ssl_conf_ca_cb()` for more information. * * Requires: MBEDTLS_X509_CRT_PARSE_C * * Uncomment to enable trusted certificate callbacks. */ //#define MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK /** * \def MBEDTLS_X509_REMOVE_INFO * * Disable mbedtls_x509_*_info() and related APIs. * * Uncomment to omit mbedtls_x509_*_info(), as well as mbedtls_debug_print_crt() * and other functions/constants only used by these functions, thus reducing * the code footprint by several KB. */ //#define MBEDTLS_X509_REMOVE_INFO /** * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT * * Enable parsing and verification of X.509 certificates, CRLs and CSRS * signed with RSASSA-PSS (aka PKCS#1 v2.1). * * Requires: MBEDTLS_PKCS1_V21 * * Comment this macro to disallow using RSASSA-PSS in certificates. */ #define MBEDTLS_X509_RSASSA_PSS_SUPPORT /** \} name SECTION: Mbed TLS feature support */ /** * \name SECTION: Mbed TLS modules * * This section enables or disables entire modules in Mbed TLS * \{ */ /** * \def MBEDTLS_AESNI_C * * Enable AES-NI support on x86-64 or x86-32. * * \note AESNI is only supported with certain compilers and target options: * - Visual Studio: supported * - GCC, x86-64, target not explicitly supporting AESNI: * requires MBEDTLS_HAVE_ASM. * - GCC, x86-32, target not explicitly supporting AESNI: * not supported. * - GCC, x86-64 or x86-32, target supporting AESNI: supported. * For this assembly-less implementation, you must currently compile * `library/aesni.c` and `library/aes.c` with machine options to enable * SSE2 and AESNI instructions: `gcc -msse2 -maes -mpclmul` or * `clang -maes -mpclmul`. * - Non-x86 targets: this option is silently ignored. * - Other compilers: this option is silently ignored. * * \note * Above, "GCC" includes compatible compilers such as Clang. * The limitations on target support are likely to be relaxed in the future. * * Module: library/aesni.c * Caller: library/aes.c * * Requires: MBEDTLS_HAVE_ASM (on some platforms, see note) * * This modules adds support for the AES-NI instructions on x86. */ #define MBEDTLS_AESNI_C /** * \def MBEDTLS_AESCE_C * * Enable AES cryptographic extension support on Armv8. * * Module: library/aesce.c * Caller: library/aes.c * * Requires: MBEDTLS_AES_C * * \warning Runtime detection only works on Linux. For non-Linux operating * system, Armv8-A Cryptographic Extensions must be supported by * the CPU when this option is enabled. * * \note Minimum compiler versions for this feature when targeting aarch64 * are Clang 4.0; armclang 6.6; GCC 6.0; or MSVC 2019 version 16.11.2. * Minimum compiler versions for this feature when targeting 32-bit * Arm or Thumb are Clang 11.0; armclang 6.20; or GCC 6.0. * * \note \c CFLAGS must be set to a minimum of \c -march=armv8-a+crypto for * armclang <= 6.9 * * This module adds support for the AES Armv8-A Cryptographic Extensions on Armv8 systems. */ #define MBEDTLS_AESCE_C /** * \def MBEDTLS_AES_C * * Enable the AES block cipher. * * Module: library/aes.c * Caller: library/cipher.c * library/pem.c * library/ctr_drbg.c * * This module enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA * * PEM_PARSE uses AES for decrypting encrypted keys. */ #define MBEDTLS_AES_C /** * \def MBEDTLS_ASN1_PARSE_C * * Enable the generic ASN1 parser. * * Module: library/asn1.c * Caller: library/x509.c * library/dhm.c * library/pkcs12.c * library/pkcs5.c * library/pkparse.c */ #define MBEDTLS_ASN1_PARSE_C /** * \def MBEDTLS_ASN1_WRITE_C * * Enable the generic ASN1 writer. * * Module: library/asn1write.c * Caller: library/ecdsa.c * library/pkwrite.c * library/x509_create.c * library/x509write_crt.c * library/x509write_csr.c */ #define MBEDTLS_ASN1_WRITE_C /** * \def MBEDTLS_BASE64_C * * Enable the Base64 module. * * Module: library/base64.c * Caller: library/pem.c * * This module is required for PEM support (required by X.509). */ #define MBEDTLS_BASE64_C /** * \def MBEDTLS_BLOCK_CIPHER_NO_DECRYPT * * Remove decryption operation for AES, ARIA and Camellia block cipher. * * \note This feature is incompatible with insecure block cipher, * MBEDTLS_DES_C, and cipher modes which always require decryption * operation, MBEDTLS_CIPHER_MODE_CBC, MBEDTLS_CIPHER_MODE_XTS and * MBEDTLS_NIST_KW_C. When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled, * this feature is incompatible with following supported PSA equivalence, * PSA_WANT_ALG_ECB_NO_PADDING, PSA_WANT_ALG_CBC_NO_PADDING, * PSA_WANT_ALG_CBC_PKCS7 and PSA_WANT_KEY_TYPE_DES. * * Module: library/aes.c * library/aesce.c * library/aesni.c * library/aria.c * library/camellia.c * library/cipher.c */ //#define MBEDTLS_BLOCK_CIPHER_NO_DECRYPT /** * \def MBEDTLS_BIGNUM_C * * Enable the multi-precision integer library. * * Module: library/bignum.c * library/bignum_core.c * library/bignum_mod.c * library/bignum_mod_raw.c * Caller: library/dhm.c * library/ecp.c * library/ecdsa.c * library/rsa.c * library/rsa_alt_helpers.c * library/ssl_tls.c * * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. */ #define MBEDTLS_BIGNUM_C /** * \def MBEDTLS_CAMELLIA_C * * Enable the Camellia block cipher. * * Module: library/camellia.c * Caller: library/cipher.c * * This module enables the following ciphersuites (if other requisites are * enabled as well): * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 */ #define MBEDTLS_CAMELLIA_C /** * \def MBEDTLS_ARIA_C * * Enable the ARIA block cipher. * * Module: library/aria.c * Caller: library/cipher.c * * This module enables the following ciphersuites (if other requisites are * enabled as well): * * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 */ #define MBEDTLS_ARIA_C /** * \def MBEDTLS_CCM_C * * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. * * Module: library/ccm.c * * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or * MBEDTLS_ARIA_C * * This module enables the AES-CCM ciphersuites, if other requisites are * enabled as well. */ #define MBEDTLS_CCM_C /** * \def MBEDTLS_CHACHA20_C * * Enable the ChaCha20 stream cipher. * * Module: library/chacha20.c */ #define MBEDTLS_CHACHA20_C /** * \def MBEDTLS_CHACHAPOLY_C * * Enable the ChaCha20-Poly1305 AEAD algorithm. * * Module: library/chachapoly.c * * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C */ #define MBEDTLS_CHACHAPOLY_C /** * \def MBEDTLS_CIPHER_C * * Enable the generic cipher layer. * * Module: library/cipher.c * Caller: library/ccm.c * library/cmac.c * library/gcm.c * library/nist_kw.c * library/pkcs12.c * library/pkcs5.c * library/psa_crypto_aead.c * library/psa_crypto_mac.c * library/ssl_ciphersuites.c * library/ssl_msg.c * library/ssl_ticket.c (unless MBEDTLS_USE_PSA_CRYPTO is enabled) * Auto-enabled by: MBEDTLS_PSA_CRYPTO_C depending on which ciphers are enabled * (see the documentation of that option for details). * * Uncomment to enable generic cipher wrappers. */ #define MBEDTLS_CIPHER_C /** * \def MBEDTLS_CMAC_C * * Enable the CMAC (Cipher-based Message Authentication Code) mode for block * ciphers. * * \note When #MBEDTLS_CMAC_ALT is active, meaning that the underlying * implementation of the CMAC algorithm is provided by an alternate * implementation, that alternate implementation may opt to not support * AES-192 or 3DES as underlying block ciphers for the CMAC operation. * * Module: library/cmac.c * * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_DES_C * */ #define MBEDTLS_CMAC_C /** * \def MBEDTLS_CTR_DRBG_C * * Enable the CTR_DRBG AES-based random generator. * The CTR_DRBG generator uses AES-256 by default. * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. * * AES support can either be achieved through builtin (MBEDTLS_AES_C) or PSA. * Builtin is the default option when MBEDTLS_AES_C is defined otherwise PSA * is used. * * \warning When using PSA, the user should call `psa_crypto_init()` before * using any CTR_DRBG operation (except `mbedtls_ctr_drbg_init()`). * * \note AES-128 will be used if \c MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH is set. * * \note To achieve a 256-bit security strength with CTR_DRBG, * you must use AES-256 *and* use sufficient entropy. * See ctr_drbg.h for more details. * * Module: library/ctr_drbg.c * Caller: * * Requires: MBEDTLS_AES_C or * (PSA_WANT_KEY_TYPE_AES and PSA_WANT_ALG_ECB_NO_PADDING and * MBEDTLS_PSA_CRYPTO_C) * * This module provides the CTR_DRBG AES random number generator. */ #define MBEDTLS_CTR_DRBG_C /** * \def MBEDTLS_DEBUG_C * * Enable the debug functions. * * Module: library/debug.c * Caller: library/ssl_msg.c * library/ssl_tls.c * library/ssl_tls12_*.c * library/ssl_tls13_*.c * * This module provides debugging functions. */ #define MBEDTLS_DEBUG_C /** * \def MBEDTLS_DES_C * * Enable the DES block cipher. * * Module: library/des.c * Caller: library/pem.c * library/cipher.c * * PEM_PARSE uses DES/3DES for decrypting encrypted keys. * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers instead. */ #define MBEDTLS_DES_C /** * \def MBEDTLS_DHM_C * * Enable the Diffie-Hellman-Merkle module. * * Module: library/dhm.c * Caller: library/ssl_tls.c * library/ssl*_client.c * library/ssl*_server.c * * This module is used by the following key exchanges: * DHE-RSA, DHE-PSK * * \warning Using DHE constitutes a security risk as it * is not possible to validate custom DH parameters. * If possible, it is recommended users should consider * preferring other methods of key exchange. * See dhm.h for more details. * */ #define MBEDTLS_DHM_C /** * \def MBEDTLS_ECDH_C * * Enable the elliptic curve Diffie-Hellman library. * * Module: library/ecdh.c * Caller: library/psa_crypto.c * library/ssl_tls.c * library/ssl*_client.c * library/ssl*_server.c * * This module is used by the following key exchanges: * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK * * Requires: MBEDTLS_ECP_C */ #define MBEDTLS_ECDH_C /** * \def MBEDTLS_ECDSA_C * * Enable the elliptic curve DSA library. * * Module: library/ecdsa.c * Caller: * * This module is used by the following key exchanges: * ECDHE-ECDSA * * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C, * and at least one MBEDTLS_ECP_DP_XXX_ENABLED for a * short Weierstrass curve. */ #define MBEDTLS_ECDSA_C /** * \def MBEDTLS_ECJPAKE_C * * Enable the elliptic curve J-PAKE library. * * \note EC J-PAKE support is based on the Thread v1.0.0 specification. * It has not been reviewed for compliance with newer standards such as * Thread v1.1 or RFC 8236. * * Module: library/ecjpake.c * Caller: * * This module is used by the following key exchanges: * ECJPAKE * * Requires: MBEDTLS_ECP_C and either MBEDTLS_MD_C or MBEDTLS_PSA_CRYPTO_C * * \warning If using a hash that is only provided by PSA drivers, you must * call psa_crypto_init() before doing any EC J-PAKE operations. */ #define MBEDTLS_ECJPAKE_C /** * \def MBEDTLS_ECP_C * * Enable the elliptic curve over GF(p) library. * * Module: library/ecp.c * Caller: library/ecdh.c * library/ecdsa.c * library/ecjpake.c * * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED */ #define MBEDTLS_ECP_C /** * \def MBEDTLS_ENTROPY_C * * Enable the platform-specific entropy code. * * Module: library/entropy.c * Caller: * * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C * * This module provides a generic entropy pool */ #define MBEDTLS_ENTROPY_C /** * \def MBEDTLS_ERROR_C * * Enable error code to error string conversion. * * Module: library/error.c * Caller: * * This module enables mbedtls_strerror(). */ #define MBEDTLS_ERROR_C /** * \def MBEDTLS_GCM_C * * Enable the Galois/Counter Mode (GCM). * * Module: library/gcm.c * * Requires: MBEDTLS_CIPHER_C, MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or * MBEDTLS_ARIA_C * * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other * requisites are enabled as well. */ #define MBEDTLS_GCM_C /** * \def MBEDTLS_GCM_LARGE_TABLE * * Enable large pre-computed tables for Galois/Counter Mode (GCM). * Can significantly increase throughput on systems without GCM hardware * acceleration (e.g., AESNI, AESCE). * * The mbedtls_gcm_context size will increase by 3840 bytes. * The code size will increase by roughly 344 bytes. * * Module: library/gcm.c * * Requires: MBEDTLS_GCM_C */ //#define MBEDTLS_GCM_LARGE_TABLE /** * \def MBEDTLS_HKDF_C * * Enable the HKDF algorithm (RFC 5869). * * Module: library/hkdf.c * Caller: * * Requires: MBEDTLS_MD_C * * This module adds support for the Hashed Message Authentication Code * (HMAC)-based key derivation function (HKDF). */ #define MBEDTLS_HKDF_C /** * \def MBEDTLS_HMAC_DRBG_C * * Enable the HMAC_DRBG random generator. * * Module: library/hmac_drbg.c * Caller: * * Requires: MBEDTLS_MD_C * * Uncomment to enable the HMAC_DRBG random number generator. */ #define MBEDTLS_HMAC_DRBG_C /** * \def MBEDTLS_LMS_C * * Enable the LMS stateful-hash asymmetric signature algorithm. * * Module: library/lms.c * Caller: * * Requires: MBEDTLS_PSA_CRYPTO_C * * Uncomment to enable the LMS verification algorithm and public key operations. */ #define MBEDTLS_LMS_C /** * \def MBEDTLS_LMS_PRIVATE * * Enable LMS private-key operations and signing code. Functions enabled by this * option are experimental, and should not be used in production. * * Requires: MBEDTLS_LMS_C * * Uncomment to enable the LMS signature algorithm and private key operations. */ //#define MBEDTLS_LMS_PRIVATE /** * \def MBEDTLS_NIST_KW_C * * Enable the Key Wrapping mode for 128-bit block ciphers, * as defined in NIST SP 800-38F. Only KW and KWP modes * are supported. At the moment, only AES is approved by NIST. * * Module: library/nist_kw.c * * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C */ #define MBEDTLS_NIST_KW_C /** * \def MBEDTLS_MD_C * * Enable the generic layer for message digest (hashing) and HMAC. * * Requires: one of: MBEDTLS_MD5_C, MBEDTLS_RIPEMD160_C, MBEDTLS_SHA1_C, * MBEDTLS_SHA224_C, MBEDTLS_SHA256_C, MBEDTLS_SHA384_C, * MBEDTLS_SHA512_C, or MBEDTLS_PSA_CRYPTO_C with at least * one hash. * Module: library/md.c * Caller: library/constant_time.c * library/ecdsa.c * library/ecjpake.c * library/hkdf.c * library/hmac_drbg.c * library/pk.c * library/pkcs5.c * library/pkcs12.c * library/psa_crypto_ecp.c * library/psa_crypto_rsa.c * library/rsa.c * library/ssl_cookie.c * library/ssl_msg.c * library/ssl_tls.c * library/x509.c * library/x509_crt.c * library/x509write_crt.c * library/x509write_csr.c * * Uncomment to enable generic message digest wrappers. */ #define MBEDTLS_MD_C /** * \def MBEDTLS_MD5_C * * Enable the MD5 hash algorithm. * * Module: library/md5.c * Caller: library/md.c * library/pem.c * library/ssl_tls.c * * This module is required for TLS 1.2 depending on the handshake parameters. * Further, it is used for checking MD5-signed certificates, and for PBKDF1 * when decrypting PEM-encoded encrypted keys. * * \warning MD5 is considered a weak message digest and its use constitutes a * security risk. If possible, we recommend avoiding dependencies on * it, and considering stronger message digests instead. * */ #define MBEDTLS_MD5_C /** * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C * * Enable the buffer allocator implementation that makes use of a (stack) * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() * calls) * * Module: library/memory_buffer_alloc.c * * Requires: MBEDTLS_PLATFORM_C * MBEDTLS_PLATFORM_MEMORY (to use it within Mbed TLS) * * Enable this module to enable the buffer memory allocator. */ //#define MBEDTLS_MEMORY_BUFFER_ALLOC_C /** * \def MBEDTLS_NET_C * * Enable the TCP and UDP over IPv6/IPv4 networking routines. * * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) * and Windows. For other platforms, you'll want to disable it, and write your * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). * * \note See also our Knowledge Base article about porting to a new * environment: * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS * * Module: library/net_sockets.c * * This module provides networking routines. */ #define MBEDTLS_NET_C /** * \def MBEDTLS_OID_C * * Enable the OID database. * * Module: library/oid.c * Caller: library/asn1write.c * library/pkcs5.c * library/pkparse.c * library/pkwrite.c * library/rsa.c * library/x509.c * library/x509_create.c * library/x509_crl.c * library/x509_crt.c * library/x509_csr.c * library/x509write_crt.c * library/x509write_csr.c * * This modules translates between OIDs and internal values. */ #define MBEDTLS_OID_C /** * \def MBEDTLS_PADLOCK_C * * Enable VIA Padlock support on x86. * * Module: library/padlock.c * Caller: library/aes.c * * Requires: MBEDTLS_HAVE_ASM * * This modules adds support for the VIA PadLock on x86. */ #define MBEDTLS_PADLOCK_C /** * \def MBEDTLS_PEM_PARSE_C * * Enable PEM decoding / parsing. * * Module: library/pem.c * Caller: library/dhm.c * library/pkparse.c * library/x509_crl.c * library/x509_crt.c * library/x509_csr.c * * Requires: MBEDTLS_BASE64_C * optionally MBEDTLS_MD5_C, or PSA Crypto with MD5 (see below) * * \warning When parsing password-protected files, if MD5 is provided only by * a PSA driver, you must call psa_crypto_init() before the first file. * * This modules adds support for decoding / parsing PEM files. */ #define MBEDTLS_PEM_PARSE_C /** * \def MBEDTLS_PEM_WRITE_C * * Enable PEM encoding / writing. * * Module: library/pem.c * Caller: library/pkwrite.c * library/x509write_crt.c * library/x509write_csr.c * * Requires: MBEDTLS_BASE64_C * * This modules adds support for encoding / writing PEM files. */ #define MBEDTLS_PEM_WRITE_C /** * \def MBEDTLS_PK_C * * Enable the generic public (asymmetric) key layer. * * Module: library/pk.c * Caller: library/psa_crypto_rsa.c * library/ssl_tls.c * library/ssl*_client.c * library/ssl*_server.c * library/x509.c * * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C or MBEDTLS_ECP_C * * Uncomment to enable generic public key wrappers. */ #define MBEDTLS_PK_C /** * \def MBEDTLS_PK_PARSE_C * * Enable the generic public (asymmetric) key parser. * * Module: library/pkparse.c * Caller: library/x509_crt.c * library/x509_csr.c * * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_OID_C, MBEDTLS_PK_C * * Uncomment to enable generic public key parse functions. */ #define MBEDTLS_PK_PARSE_C /** * \def MBEDTLS_PK_WRITE_C * * Enable the generic public (asymmetric) key writer. * * Module: library/pkwrite.c * Caller: library/x509write.c * * Requires: MBEDTLS_ASN1_WRITE_C, MBEDTLS_OID_C, MBEDTLS_PK_C * * Uncomment to enable generic public key write functions. */ #define MBEDTLS_PK_WRITE_C /** * \def MBEDTLS_PKCS5_C * * Enable PKCS#5 functions. * * Module: library/pkcs5.c * * Auto-enables: MBEDTLS_MD_C * * \warning If using a hash that is only provided by PSA drivers, you must * call psa_crypto_init() before doing any PKCS5 operations. * * This module adds support for the PKCS#5 functions. */ #define MBEDTLS_PKCS5_C /** * \def MBEDTLS_PKCS7_C * * Enable PKCS #7 core for using PKCS #7-formatted signatures. * RFC Link - https://tools.ietf.org/html/rfc2315 * * Module: library/pkcs7.c * * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C, * MBEDTLS_X509_CRT_PARSE_C MBEDTLS_X509_CRL_PARSE_C, * MBEDTLS_BIGNUM_C, MBEDTLS_MD_C * * This module is required for the PKCS #7 parsing modules. */ #define MBEDTLS_PKCS7_C /** * \def MBEDTLS_PKCS12_C * * Enable PKCS#12 PBE functions. * Adds algorithms for parsing PKCS#8 encrypted private keys * * Module: library/pkcs12.c * Caller: library/pkparse.c * * Requires: MBEDTLS_ASN1_PARSE_C and either MBEDTLS_MD_C or * MBEDTLS_PSA_CRYPTO_C. * * \warning If using a hash that is only provided by PSA drivers, you must * call psa_crypto_init() before doing any PKCS12 operations. * * This module enables PKCS#12 functions. */ #define MBEDTLS_PKCS12_C /** * \def MBEDTLS_PLATFORM_C * * Enable the platform abstraction layer that allows you to re-assign * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). * * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned * above to be specified at runtime or compile time respectively. * * \note This abstraction layer must be enabled on Windows (including MSYS2) * as other modules rely on it for a fixed snprintf implementation. * * Module: library/platform.c * Caller: Most other .c files * * This module enables abstraction of common (libc) functions. */ #define MBEDTLS_PLATFORM_C /** * \def MBEDTLS_POLY1305_C * * Enable the Poly1305 MAC algorithm. * * Module: library/poly1305.c * Caller: library/chachapoly.c */ #define MBEDTLS_POLY1305_C /** * \def MBEDTLS_PSA_CRYPTO_C * * Enable the Platform Security Architecture cryptography API. * * Module: library/psa_crypto.c * * Requires: either MBEDTLS_CTR_DRBG_C and MBEDTLS_ENTROPY_C, * or MBEDTLS_HMAC_DRBG_C and MBEDTLS_ENTROPY_C, * or MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. * Auto-enables: MBEDTLS_CIPHER_C if any unauthenticated (ie, non-AEAD) cipher * is enabled in PSA (unless it's fully accelerated, see * docs/driver-only-builds.md about that). */ #define MBEDTLS_PSA_CRYPTO_C /** * \def MBEDTLS_PSA_CRYPTO_SE_C * * Enable dynamic secure element support in the Platform Security Architecture * cryptography API. * * \deprecated This feature is deprecated. Please switch to the PSA driver * interface. * * \warning This feature is not thread-safe, and should not be used in a * multi-threaded environment. * * Module: library/psa_crypto_se.c * * Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C * */ //#define MBEDTLS_PSA_CRYPTO_SE_C /** * \def MBEDTLS_PSA_CRYPTO_STORAGE_C * * Enable the Platform Security Architecture persistent key storage. * * Module: library/psa_crypto_storage.c * * Requires: MBEDTLS_PSA_CRYPTO_C, * either MBEDTLS_PSA_ITS_FILE_C or a native implementation of * the PSA ITS interface */ #define MBEDTLS_PSA_CRYPTO_STORAGE_C /** * \def MBEDTLS_PSA_ITS_FILE_C * * Enable the emulation of the Platform Security Architecture * Internal Trusted Storage (PSA ITS) over files. * * Module: library/psa_its_file.c * * Requires: MBEDTLS_FS_IO */ #define MBEDTLS_PSA_ITS_FILE_C /** * \def MBEDTLS_RIPEMD160_C * * Enable the RIPEMD-160 hash algorithm. * * Module: library/ripemd160.c * Caller: library/md.c * */ #define MBEDTLS_RIPEMD160_C /** * \def MBEDTLS_RSA_C * * Enable the RSA public-key cryptosystem. * * Module: library/rsa.c * library/rsa_alt_helpers.c * Caller: library/pk.c * library/psa_crypto.c * library/ssl_tls.c * library/ssl*_client.c * library/ssl*_server.c * * This module is used by the following key exchanges: * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK * * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C */ #define MBEDTLS_RSA_C /** * \def MBEDTLS_SHA1_C * * Enable the SHA1 cryptographic hash algorithm. * * Module: library/sha1.c * Caller: library/md.c * library/psa_crypto_hash.c * * This module is required for TLS 1.2 depending on the handshake parameters, * and for SHA1-signed certificates. * * \warning SHA-1 is considered a weak message digest and its use constitutes * a security risk. If possible, we recommend avoiding dependencies * on it, and considering stronger message digests instead. * */ #define MBEDTLS_SHA1_C /** * \def MBEDTLS_SHA224_C * * Enable the SHA-224 cryptographic hash algorithm. * * Module: library/sha256.c * Caller: library/md.c * library/ssl_cookie.c * * This module adds support for SHA-224. */ #define MBEDTLS_SHA224_C /** * \def MBEDTLS_SHA256_C * * Enable the SHA-256 cryptographic hash algorithm. * * Module: library/sha256.c * Caller: library/entropy.c * library/md.c * library/ssl_tls.c * library/ssl*_client.c * library/ssl*_server.c * * This module adds support for SHA-256. * This module is required for the SSL/TLS 1.2 PRF function. */ #define MBEDTLS_SHA256_C /** * \def MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT * * Enable acceleration of the SHA-256 and SHA-224 cryptographic hash algorithms * with the ARMv8 cryptographic extensions if they are available at runtime. * If not, the library will fall back to the C implementation. * * \note If MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT is defined when building * for a non-Armv8-A build it will be silently ignored. * * \note Minimum compiler versions for this feature are Clang 4.0, * armclang 6.6 or GCC 6.0. * * \note \c CFLAGS must be set to a minimum of \c -march=armv8-a+crypto for * armclang <= 6.9 * * \note This was previously known as MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT. * That name is deprecated, but may still be used as an alternative form for this * option. * * \warning MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT cannot be defined at the * same time as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY. * * Requires: MBEDTLS_SHA256_C. * * Module: library/sha256.c * * Uncomment to have the library check for the Armv8-A SHA-256 crypto extensions * and use them if available. */ //#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT /** * \def MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT * * \deprecated This is now known as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT. * This name is now deprecated, but may still be used as an alternative form for * this option. */ //#define MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT /** * \def MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY * * Enable acceleration of the SHA-256 and SHA-224 cryptographic hash algorithms * with the ARMv8 cryptographic extensions, which must be available at runtime * or else an illegal instruction fault will occur. * * \note This allows builds with a smaller code size than with * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT * * \note Minimum compiler versions for this feature are Clang 4.0, * armclang 6.6 or GCC 6.0. * * \note \c CFLAGS must be set to a minimum of \c -march=armv8-a+crypto for * armclang <= 6.9 * * \note This was previously known as MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY. * That name is deprecated, but may still be used as an alternative form for this * option. * * \warning MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY cannot be defined at the same * time as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT. * * Requires: MBEDTLS_SHA256_C. * * Module: library/sha256.c * * Uncomment to have the library use the Armv8-A SHA-256 crypto extensions * unconditionally. */ //#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY /** * \def MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY * * \deprecated This is now known as MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY. * This name is now deprecated, but may still be used as an alternative form for * this option. */ //#define MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY /** * \def MBEDTLS_SHA384_C * * Enable the SHA-384 cryptographic hash algorithm. * * Module: library/sha512.c * Caller: library/md.c * library/psa_crypto_hash.c * library/ssl_tls.c * library/ssl*_client.c * library/ssl*_server.c * * Comment to disable SHA-384 */ #define MBEDTLS_SHA384_C /** * \def MBEDTLS_SHA512_C * * Enable SHA-512 cryptographic hash algorithms. * * Module: library/sha512.c * Caller: library/entropy.c * library/md.c * library/ssl_tls.c * library/ssl_cookie.c * * This module adds support for SHA-512. */ #define MBEDTLS_SHA512_C /** * \def MBEDTLS_SHA3_C * * Enable the SHA3 cryptographic hash algorithm. * * Module: library/sha3.c * * This module adds support for SHA3. */ #define MBEDTLS_SHA3_C /** * \def MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT * * Enable acceleration of the SHA-512 and SHA-384 cryptographic hash algorithms * with the ARMv8 cryptographic extensions if they are available at runtime. * If not, the library will fall back to the C implementation. * * \note If MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT is defined when building * for a non-Aarch64 build it will be silently ignored. * * \note Minimum compiler versions for this feature are Clang 7.0, * armclang 6.9 or GCC 8.0. * * \note \c CFLAGS must be set to a minimum of \c -march=armv8.2-a+sha3 for * armclang 6.9 * * \warning MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT cannot be defined at the * same time as MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY. * * Requires: MBEDTLS_SHA512_C. * * Module: library/sha512.c * * Uncomment to have the library check for the A64 SHA-512 crypto extensions * and use them if available. */ //#define MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT /** * \def MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY * * Enable acceleration of the SHA-512 and SHA-384 cryptographic hash algorithms * with the ARMv8 cryptographic extensions, which must be available at runtime * or else an illegal instruction fault will occur. * * \note This allows builds with a smaller code size than with * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT * * \note Minimum compiler versions for this feature are Clang 7.0, * armclang 6.9 or GCC 8.0. * * \note \c CFLAGS must be set to a minimum of \c -march=armv8.2-a+sha3 for * armclang 6.9 * * \warning MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY cannot be defined at the same * time as MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT. * * Requires: MBEDTLS_SHA512_C. * * Module: library/sha512.c * * Uncomment to have the library use the A64 SHA-512 crypto extensions * unconditionally. */ //#define MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY /** * \def MBEDTLS_SSL_CACHE_C * * Enable simple SSL cache implementation. * * Module: library/ssl_cache.c * Caller: * * Requires: MBEDTLS_SSL_CACHE_C */ #define MBEDTLS_SSL_CACHE_C /** * \def MBEDTLS_SSL_COOKIE_C * * Enable basic implementation of DTLS cookies for hello verification. * * Module: library/ssl_cookie.c * Caller: */ #define MBEDTLS_SSL_COOKIE_C /** * \def MBEDTLS_SSL_TICKET_C * * Enable an implementation of TLS server-side callbacks for session tickets. * * Module: library/ssl_ticket.c * Caller: * * Requires: (MBEDTLS_CIPHER_C || MBEDTLS_USE_PSA_CRYPTO) && * (MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C) */ #define MBEDTLS_SSL_TICKET_C /** * \def MBEDTLS_SSL_CLI_C * * Enable the SSL/TLS client code. * * Module: library/ssl*_client.c * Caller: * * Requires: MBEDTLS_SSL_TLS_C * * This module is required for SSL/TLS client support. */ #define MBEDTLS_SSL_CLI_C /** * \def MBEDTLS_SSL_SRV_C * * Enable the SSL/TLS server code. * * Module: library/ssl*_server.c * Caller: * * Requires: MBEDTLS_SSL_TLS_C * * This module is required for SSL/TLS server support. */ #define MBEDTLS_SSL_SRV_C /** * \def MBEDTLS_SSL_TLS_C * * Enable the generic SSL/TLS code. * * Module: library/ssl_tls.c * Caller: library/ssl*_client.c * library/ssl*_server.c * * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C * and at least one of the MBEDTLS_SSL_PROTO_XXX defines * * This module is required for SSL/TLS. */ #define MBEDTLS_SSL_TLS_C /** * \def MBEDTLS_THREADING_C * * Enable the threading abstraction layer. * By default Mbed TLS assumes it is used in a non-threaded environment or that * contexts are not shared between threads. If you do intend to use contexts * between threads, you will need to enable this layer to prevent race * conditions. See also our Knowledge Base article about threading: * https://mbed-tls.readthedocs.io/en/latest/kb/development/thread-safety-and-multi-threading * * Module: library/threading.c * * This allows different threading implementations (self-implemented or * provided). * * You will have to enable either MBEDTLS_THREADING_ALT or * MBEDTLS_THREADING_PTHREAD. * * Enable this layer to allow use of mutexes within Mbed TLS */ //#define MBEDTLS_THREADING_C /** * \def MBEDTLS_TIMING_C * * Enable the semi-portable timing interface. * * \note The provided implementation only works on POSIX/Unix (including Linux, * BSD and OS X) and Windows. On other platforms, you can either disable that * module and provide your own implementations of the callbacks needed by * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide * your own implementation of the whole module by setting * \c MBEDTLS_TIMING_ALT in the current file. * * \note The timing module will include time.h on suitable platforms * regardless of the setting of MBEDTLS_HAVE_TIME, unless * MBEDTLS_TIMING_ALT is used. See timing.c for more information. * * \note See also our Knowledge Base article about porting to a new * environment: * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS * * Module: library/timing.c */ #define MBEDTLS_TIMING_C /** * \def MBEDTLS_VERSION_C * * Enable run-time version information. * * Module: library/version.c * * This module provides run-time version information. */ #define MBEDTLS_VERSION_C /** * \def MBEDTLS_X509_USE_C * * Enable X.509 core for using certificates. * * Module: library/x509.c * Caller: library/x509_crl.c * library/x509_crt.c * library/x509_csr.c * * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C, * (MBEDTLS_MD_C or MBEDTLS_USE_PSA_CRYPTO) * * \warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call * psa_crypto_init() before doing any X.509 operation. * * This module is required for the X.509 parsing modules. */ #define MBEDTLS_X509_USE_C /** * \def MBEDTLS_X509_CRT_PARSE_C * * Enable X.509 certificate parsing. * * Module: library/x509_crt.c * Caller: library/ssl_tls.c * library/ssl*_client.c * library/ssl*_server.c * * Requires: MBEDTLS_X509_USE_C * * This module is required for X.509 certificate parsing. */ #define MBEDTLS_X509_CRT_PARSE_C /** * \def MBEDTLS_X509_CRL_PARSE_C * * Enable X.509 CRL parsing. * * Module: library/x509_crl.c * Caller: library/x509_crt.c * * Requires: MBEDTLS_X509_USE_C * * This module is required for X.509 CRL parsing. */ #define MBEDTLS_X509_CRL_PARSE_C /** * \def MBEDTLS_X509_CSR_PARSE_C * * Enable X.509 Certificate Signing Request (CSR) parsing. * * Module: library/x509_csr.c * Caller: library/x509_crt_write.c * * Requires: MBEDTLS_X509_USE_C * * This module is used for reading X.509 certificate request. */ #define MBEDTLS_X509_CSR_PARSE_C /** * \def MBEDTLS_X509_CREATE_C * * Enable X.509 core for creating certificates. * * Module: library/x509_create.c * * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C, * (MBEDTLS_MD_C or MBEDTLS_USE_PSA_CRYPTO) * * \warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call * psa_crypto_init() before doing any X.509 create operation. * * This module is the basis for creating X.509 certificates and CSRs. */ #define MBEDTLS_X509_CREATE_C /** * \def MBEDTLS_X509_CRT_WRITE_C * * Enable creating X.509 certificates. * * Module: library/x509_crt_write.c * * Requires: MBEDTLS_X509_CREATE_C * * This module is required for X.509 certificate creation. */ #define MBEDTLS_X509_CRT_WRITE_C /** * \def MBEDTLS_X509_CSR_WRITE_C * * Enable creating X.509 Certificate Signing Requests (CSR). * * Module: library/x509_csr_write.c * * Requires: MBEDTLS_X509_CREATE_C * * This module is required for X.509 certificate request writing. */ #define MBEDTLS_X509_CSR_WRITE_C /** \} name SECTION: Mbed TLS modules */ /** * \name SECTION: General configuration options * * This section contains Mbed TLS build settings that are not associated * with a particular module. * * \{ */ /** * \def MBEDTLS_CONFIG_FILE * * If defined, this is a header which will be included instead of * `"mbedtls/mbedtls_config.h"`. * This header file specifies the compile-time configuration of Mbed TLS. * Unlike other configuration options, this one must be defined on the * compiler command line: a definition in `mbedtls_config.h` would have * no effect. * * This macro is expanded after an \#include directive. This is a popular but * non-standard feature of the C language, so this feature is only available * with compilers that perform macro expansion on an \#include line. * * The value of this symbol is typically a path in double quotes, either * absolute or relative to a directory on the include search path. */ //#define MBEDTLS_CONFIG_FILE "mbedtls/mbedtls_config.h" /** * \def MBEDTLS_USER_CONFIG_FILE * * If defined, this is a header which will be included after * `"mbedtls/mbedtls_config.h"` or #MBEDTLS_CONFIG_FILE. * This allows you to modify the default configuration, including the ability * to undefine options that are enabled by default. * * This macro is expanded after an \#include directive. This is a popular but * non-standard feature of the C language, so this feature is only available * with compilers that perform macro expansion on an \#include line. * * The value of this symbol is typically a path in double quotes, either * absolute or relative to a directory on the include search path. */ //#define MBEDTLS_USER_CONFIG_FILE "/dev/null" /** * \def MBEDTLS_PSA_CRYPTO_CONFIG_FILE * * If defined, this is a header which will be included instead of * `"psa/crypto_config.h"`. * This header file specifies which cryptographic mechanisms are available * through the PSA API when #MBEDTLS_PSA_CRYPTO_CONFIG is enabled, and * is not used when #MBEDTLS_PSA_CRYPTO_CONFIG is disabled. * * This macro is expanded after an \#include directive. This is a popular but * non-standard feature of the C language, so this feature is only available * with compilers that perform macro expansion on an \#include line. * * The value of this symbol is typically a path in double quotes, either * absolute or relative to a directory on the include search path. */ //#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "psa/crypto_config.h" /** * \def MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE * * If defined, this is a header which will be included after * `"psa/crypto_config.h"` or #MBEDTLS_PSA_CRYPTO_CONFIG_FILE. * This allows you to modify the default configuration, including the ability * to undefine options that are enabled by default. * * This macro is expanded after an \#include directive. This is a popular but * non-standard feature of the C language, so this feature is only available * with compilers that perform macro expansion on an \#include line. * * The value of this symbol is typically a path in double quotes, either * absolute or relative to a directory on the include search path. */ //#define MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE "/dev/null" /** * \def MBEDTLS_PSA_CRYPTO_PLATFORM_FILE * * If defined, this is a header which will be included instead of * `"psa/crypto_platform.h"`. This file should declare the same identifiers * as the one in Mbed TLS, but with definitions adapted to the platform on * which the library code will run. * * \note The required content of this header can vary from one version of * Mbed TLS to the next. Integrators who provide an alternative file * should review the changes in the original file whenever they * upgrade Mbed TLS. * * This macro is expanded after an \#include directive. This is a popular but * non-standard feature of the C language, so this feature is only available * with compilers that perform macro expansion on an \#include line. * * The value of this symbol is typically a path in double quotes, either * absolute or relative to a directory on the include search path. */ //#define MBEDTLS_PSA_CRYPTO_PLATFORM_FILE "psa/crypto_platform_alt.h" /** * \def MBEDTLS_PSA_CRYPTO_STRUCT_FILE * * If defined, this is a header which will be included instead of * `"psa/crypto_struct.h"`. This file should declare the same identifiers * as the one in Mbed TLS, but with definitions adapted to the environment * in which the library code will run. The typical use for this feature * is to provide alternative type definitions on the client side in * client-server integrations of PSA crypto, where operation structures * contain handles instead of cryptographic data. * * \note The required content of this header can vary from one version of * Mbed TLS to the next. Integrators who provide an alternative file * should review the changes in the original file whenever they * upgrade Mbed TLS. * * This macro is expanded after an \#include directive. This is a popular but * non-standard feature of the C language, so this feature is only available * with compilers that perform macro expansion on an \#include line. * * The value of this symbol is typically a path in double quotes, either * absolute or relative to a directory on the include search path. */ //#define MBEDTLS_PSA_CRYPTO_STRUCT_FILE "psa/crypto_struct_alt.h" /** \} name SECTION: General configuration options */ /** * \name SECTION: Module configuration options * * This section allows for the setting of module specific sizes and * configuration options. The default values are already present in the * relevant header files and should suffice for the regular use cases. * * Our advice is to enable options and change their values here * only if you have a good reason and know the consequences. * \{ */ /* The Doxygen documentation here is used when a user comments out a * setting and runs doxygen themselves. On the other hand, when we typeset * the full documentation including disabled settings, the documentation * in specific modules' header files is used if present. When editing this * file, make sure that each option is documented in exactly one place, * plus optionally a same-line Doxygen comment here if there is a Doxygen * comment in the specific module. */ /* MPI / BIGNUM options */ //#define MBEDTLS_MPI_WINDOW_SIZE 2 /**< Maximum window size used. */ //#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ /* CTR_DRBG options */ //#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ //#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ //#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ //#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ //#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ /* HMAC_DRBG options */ //#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ //#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ //#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ //#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ /* ECP options */ //#define MBEDTLS_ECP_WINDOW_SIZE 4 /**< Maximum window size used */ //#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ /* Entropy options */ //#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ //#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ //#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ /* Memory buffer allocator options */ //#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ /* Platform options */ //#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ /** \def MBEDTLS_PLATFORM_STD_CALLOC * * Default allocator to use, can be undefined. * It must initialize the allocated buffer memory to zeroes. * The size of the buffer is the product of the two parameters. * The calloc function returns either a null pointer or a pointer to the allocated space. * If the product is 0, the function may either return NULL or a valid pointer to an array of size 0 which is a valid input to the deallocation function. * An uninitialized #MBEDTLS_PLATFORM_STD_CALLOC always fails, returning a null pointer. * See the description of #MBEDTLS_PLATFORM_MEMORY for more details. * The corresponding deallocation function is #MBEDTLS_PLATFORM_STD_FREE. */ //#define MBEDTLS_PLATFORM_STD_CALLOC calloc /** \def MBEDTLS_PLATFORM_STD_FREE * * Default free to use, can be undefined. * NULL is a valid parameter, and the function must do nothing. * A non-null parameter will always be a pointer previously returned by #MBEDTLS_PLATFORM_STD_CALLOC and not yet freed. * An uninitialized #MBEDTLS_PLATFORM_STD_FREE does not do anything. * See the description of #MBEDTLS_PLATFORM_MEMORY for more details (same principles as for MBEDTLS_PLATFORM_STD_CALLOC apply). */ //#define MBEDTLS_PLATFORM_STD_FREE free //#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< Default setbuf to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ //#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ /* Note: your snprintf must correctly zero-terminate the buffer! */ //#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ //#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ /* To use the following function macros, MBEDTLS_PLATFORM_C must be enabled. */ /* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ //#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_CALLOC for requirements. */ //#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined. See MBEDTLS_PLATFORM_STD_FREE for requirements. */ //#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_SETBUF_MACRO setbuf /**< Default setbuf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ //#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ //#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ /* Note: your snprintf must correctly zero-terminate the buffer! */ //#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ //#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO int64_t //#define MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO int64_t /**< Default milliseconds time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled. It must be signed, and at least 64 bits. If it is changed from the default, MBEDTLS_PRINTF_MS_TIME must be updated to match.*/ //#define MBEDTLS_PRINTF_MS_TIME PRId64 /**< Default fmt for printf. That's avoid compiler warning if mbedtls_ms_time_t is redefined */ /** \def MBEDTLS_CHECK_RETURN * * This macro is used at the beginning of the declaration of a function * to indicate that its return value should be checked. It should * instruct the compiler to emit a warning or an error if the function * is called without checking its return value. * * There is a default implementation for popular compilers in platform_util.h. * You can override the default implementation by defining your own here. * * If the implementation here is empty, this will effectively disable the * checking of functions' return values. */ //#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__)) /** \def MBEDTLS_IGNORE_RETURN * * This macro requires one argument, which should be a C function call. * If that function call would cause a #MBEDTLS_CHECK_RETURN warning, this * warning is suppressed. */ //#define MBEDTLS_IGNORE_RETURN( result ) ((void) !(result)) /* PSA options */ /** * Use HMAC_DRBG with the specified hash algorithm for HMAC_DRBG for the * PSA crypto subsystem. * * If this option is unset, the library chooses a hash (currently between * #MBEDTLS_MD_SHA512 and #MBEDTLS_MD_SHA256) based on availability and * unspecified heuristics. * * \note The PSA crypto subsystem uses the first available mechanism amongst * the following: * - #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG if enabled; * - Entropy from #MBEDTLS_ENTROPY_C plus CTR_DRBG with AES * if #MBEDTLS_CTR_DRBG_C is enabled; * - Entropy from #MBEDTLS_ENTROPY_C plus HMAC_DRBG. * * A future version may reevaluate the prioritization of DRBG mechanisms. */ //#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 /** \def MBEDTLS_PSA_KEY_SLOT_COUNT * * When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is disabled, * the maximum amount of PSA keys simultaneously in memory. This counts all * volatile keys, plus loaded persistent keys. * * When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, * the maximum number of loaded persistent keys. * * Currently, persistent keys do not need to be loaded all the time while * a multipart operation is in progress, only while the operation is being * set up. This may change in future versions of the library. * * Currently, the library traverses of the whole table on each access to a * persistent key. Therefore large values may cause poor performance. * * This option has no effect when #MBEDTLS_PSA_CRYPTO_C is disabled. */ //#define MBEDTLS_PSA_KEY_SLOT_COUNT 32 /* RSA OPTIONS */ //#define MBEDTLS_RSA_GEN_KEY_MIN_BITS 1024 /**< Minimum RSA key size that can be generated in bits (Minimum possible value is 128 bits) */ /* SSL Cache options */ //#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ /* SSL options */ /** \def MBEDTLS_SSL_IN_CONTENT_LEN * * Maximum length (in bytes) of incoming plaintext fragments. * * This determines the size of the incoming TLS I/O buffer in such a way * that it is capable of holding the specified amount of plaintext data, * regardless of the protection mechanism used. * * \note When using a value less than the default of 16KB on the client, it is * recommended to use the Maximum Fragment Length (MFL) extension to * inform the server about this limitation. On the server, there * is no supported, standardized way of informing the client about * restriction on the maximum size of incoming messages, and unless * the limitation has been communicated by other means, it is recommended * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN * while keeping the default value of 16KB for the incoming buffer. * * Uncomment to set the maximum plaintext size of the incoming I/O buffer. */ //#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 /** \def MBEDTLS_SSL_CID_IN_LEN_MAX * * The maximum length of CIDs used for incoming DTLS messages. * */ //#define MBEDTLS_SSL_CID_IN_LEN_MAX 32 /** \def MBEDTLS_SSL_CID_OUT_LEN_MAX * * The maximum length of CIDs used for outgoing DTLS messages. * */ //#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 /** \def MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY * * This option controls the use of record plaintext padding * in TLS 1.3 and when using the Connection ID extension in DTLS 1.2. * * The padding will always be chosen so that the length of the * padded plaintext is a multiple of the value of this option. * * Note: A value of \c 1 means that no padding will be used * for outgoing records. * * Note: On systems lacking division instructions, * a power of two should be preferred. */ //#define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16 /** \def MBEDTLS_SSL_OUT_CONTENT_LEN * * Maximum length (in bytes) of outgoing plaintext fragments. * * This determines the size of the outgoing TLS I/O buffer in such a way * that it is capable of holding the specified amount of plaintext data, * regardless of the protection mechanism used. * * It is possible to save RAM by setting a smaller outward buffer, while keeping * the default inward 16384 byte buffer to conform to the TLS specification. * * The minimum required outward buffer size is determined by the handshake * protocol's usage. Handshaking will fail if the outward buffer is too small. * The specific size requirement depends on the configured ciphers and any * certificate data which is sent during the handshake. * * Uncomment to set the maximum plaintext size of the outgoing I/O buffer. */ //#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 /** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING * * Maximum number of heap-allocated bytes for the purpose of * DTLS handshake message reassembly and future message buffering. * * This should be at least 9/8 * MBEDTLS_SSL_IN_CONTENT_LEN * to account for a reassembled handshake message of maximum size, * together with its reassembly bitmap. * * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) * should be sufficient for all practical situations as it allows * to reassembly a large handshake message (such as a certificate) * while buffering multiple smaller handshake messages. * */ //#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 //#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 or 384 bits) */ //#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ /** * Complete list of ciphersuites to use, in order of preference. * * \warning No dependency checking is done on that field! This option can only * be used to restrict the set of available ciphersuites. It is your * responsibility to make sure the needed modules are active. * * Use this to save a few hundred bytes of ROM (default ordering of all * available ciphersuites) and a few to a few hundred bytes of RAM. * * The value below is only an example, not the default. */ //#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 /** * \def MBEDTLS_SSL_MAX_EARLY_DATA_SIZE * * The default maximum amount of 0-RTT data. See the documentation of * \c mbedtls_ssl_conf_max_early_data_size() for more information. * * It must be positive and smaller than UINT32_MAX. * * If MBEDTLS_SSL_EARLY_DATA is not defined, this default value does not * have any impact on the build. */ //#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE 1024 /** * \def MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE * * Maximum allowed ticket age difference in milliseconds tolerated between * server and client. Default value is 6000. This is not used in TLS 1.2. * * - The client ticket age is the time difference between the time when the * client proposes to the server to use the ticket and the time the client * received the ticket from the server. * - The server ticket age is the time difference between the time when the * server receives a proposition from the client to use the ticket and the * time when the ticket was created by the server. * * The ages might be different due to the client and server clocks not running * at the same pace. The typical accuracy of an RTC crystal is ±100 to ±20 parts * per million (360 to 72 milliseconds per hour). Default tolerance window is * 6s, thus in the worst case clients and servers must sync up their system time * every 6000/360/2~=8 hours. * * See section 8.3 of the TLS 1.3 specification(RFC 8446) for more information. */ //#define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000 /** * \def MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH * * Size in bytes of a ticket nonce. This is not used in TLS 1.2. * * This must be less than 256. */ //#define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32 /** * \def MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS * * Default number of NewSessionTicket messages to be sent by a TLS 1.3 server * after handshake completion. This is not used in TLS 1.2 and relevant only if * the MBEDTLS_SSL_SESSION_TICKETS option is enabled. * */ //#define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1 /* X509 options */ //#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ //#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ /** \} name SECTION: Module configuration options */ webfakes/src/mbedtls/include/mbedtls/ecdsa.h0000644000176200001440000007607114740737024020612 0ustar liggesusers/** * \file ecdsa.h * * \brief This file contains ECDSA definitions and functions. * * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in * Standards for Efficient Cryptography Group (SECG): * SEC1 Elliptic Curve Cryptography. * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECDSA_H #define MBEDTLS_ECDSA_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ecp.h" #include "mbedtls/md.h" /** * \brief Maximum ECDSA signature size for a given curve bit size * * \param bits Curve size in bits * \return Maximum signature size in bytes * * \note This macro returns a compile-time constant if its argument * is one. It may evaluate its argument multiple times. */ /* * Ecdsa-Sig-Value ::= SEQUENCE { * r INTEGER, * s INTEGER * } * * For each of r and s, the value (V) may include an extra initial "0" bit. */ #define MBEDTLS_ECDSA_MAX_SIG_LEN(bits) \ (/*T,L of SEQUENCE*/ ((bits) >= 61 * 8 ? 3 : 2) + \ /*T,L of r,s*/ 2 * (((bits) >= 127 * 8 ? 3 : 2) + \ /*V of r,s*/ ((bits) + 8) / 8)) /** The maximal size of an ECDSA signature in Bytes. */ #define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN(MBEDTLS_ECP_MAX_BITS) #ifdef __cplusplus extern "C" { #endif /** * \brief The ECDSA context structure. * * \warning Performing multiple operations concurrently on the same * ECDSA context is not supported; objects of this type * should not be shared between multiple threads. * * \note pk_wrap module assumes that "ecdsa_context" is identical * to "ecp_keypair" (see for example structure * "mbedtls_eckey_info" where ECDSA sign/verify functions * are used also for EC key) */ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Internal restart context for ecdsa_verify() * * \note Opaque struct, defined in ecdsa.c */ typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; /** * \brief Internal restart context for ecdsa_sign() * * \note Opaque struct, defined in ecdsa.c */ typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /** * \brief Internal restart context for ecdsa_sign_det() * * \note Opaque struct, defined in ecdsa.c */ typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; #endif /** * \brief General context for resuming ECDSA operations */ typedef struct { mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(ecp); /*!< base context for ECP restart and shared administrative info */ mbedtls_ecdsa_restart_ver_ctx *MBEDTLS_PRIVATE(ver); /*!< ecdsa_verify() sub-context */ mbedtls_ecdsa_restart_sig_ctx *MBEDTLS_PRIVATE(sig); /*!< ecdsa_sign() sub-context */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) mbedtls_ecdsa_restart_det_ctx *MBEDTLS_PRIVATE(det); /*!< ecdsa_sign_det() sub-context */ #endif } mbedtls_ecdsa_restart_ctx; #else /* MBEDTLS_ECP_RESTARTABLE */ /* Now we can declare functions that take a pointer to that */ typedef void mbedtls_ecdsa_restart_ctx; #endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief This function checks whether a given group can be used * for ECDSA. * * \param gid The ECP group ID to check. * * \return \c 1 if the group can be used, \c 0 otherwise */ int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid); /** * \brief This function computes the ECDSA signature of a * previously-hashed message. * * \note The deterministic version implemented in * mbedtls_ecdsa_sign_det_ext() is usually preferred. * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated * as defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.3, step 5. * * \see ecp.h * * \param grp The context for the elliptic curve to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param r The MPI context in which to store the first part * the signature. This must be initialized. * \param s The MPI context in which to store the second part * the signature. This must be initialized. * \param d The private signing key. This must be initialized. * \param buf The content to be signed. This is usually the hash of * the original data to be signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX * or \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /** * \brief This function computes the ECDSA signature of a * previously-hashed message, deterministic version. * * For more information, see RFC-6979: Deterministic * Usage of the Digital Signature Algorithm (DSA) and Elliptic * Curve Digital Signature Algorithm (ECDSA). * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.3, step 5. * * \see ecp.h * * \param grp The context for the elliptic curve to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param r The MPI context in which to store the first part * the signature. This must be initialized. * \param s The MPI context in which to store the second part * the signature. This must be initialized. * \param d The private signing key. This must be initialized * and setup, for example through mbedtls_ecp_gen_privkey(). * \param buf The hashed content to be signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param md_alg The hash algorithm used to hash the original data. * \param f_rng_blind The RNG function used for blinding. This must not be * \c NULL. * \param p_rng_blind The RNG context to be passed to \p f_rng_blind. This * may be \c NULL if \p f_rng_blind doesn't need a context * parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * error code on failure. */ int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind); #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #if !defined(MBEDTLS_ECDSA_SIGN_ALT) /** * \brief This function computes the ECDSA signature of a * previously-hashed message, in a restartable way. * * \note The deterministic version implemented in * mbedtls_ecdsa_sign_det_restartable() is usually * preferred. * * \note This function is like \c mbedtls_ecdsa_sign() but * it can return early and restart according to the * limit set with \c mbedtls_ecp_set_max_ops() to * reduce blocking. * * \note If the bitlength of the message hash is larger * than the bitlength of the group order, then the * hash is truncated as defined in Standards for * Efficient Cryptography Group (SECG): SEC1 Elliptic * Curve Cryptography, section 4.1.3, step 5. * * \see ecp.h * * \param grp The context for the elliptic curve to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param r The MPI context in which to store the first part * the signature. This must be initialized. * \param s The MPI context in which to store the second part * the signature. This must be initialized. * \param d The private signing key. This must be initialized * and setup, for example through * mbedtls_ecp_gen_privkey(). * \param buf The hashed content to be signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * \param f_rng_blind The RNG function used for blinding. This must not be * \c NULL. * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * \param rs_ctx The restart context to use. This may be \c NULL * to disable restarting. If it is not \c NULL, it * must point to an initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c * mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX, \c * MBEDTLS_ERR_MPI_XXX or \c MBEDTLS_ERR_ASN1_XXX * error code on failure. */ int mbedtls_ecdsa_sign_restartable( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, mbedtls_ecdsa_restart_ctx *rs_ctx); #endif /* !MBEDTLS_ECDSA_SIGN_ALT */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /** * \brief This function computes the ECDSA signature of a * previously-hashed message, in a restartable way. * * \note This function is like \c * mbedtls_ecdsa_sign_det_ext() but it can return * early and restart according to the limit set with * \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \note If the bitlength of the message hash is larger * than the bitlength of the group order, then the * hash is truncated as defined in Standards for * Efficient Cryptography Group (SECG): SEC1 Elliptic * Curve Cryptography, section 4.1.3, step 5. * * \see ecp.h * * \param grp The context for the elliptic curve to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param r The MPI context in which to store the first part * the signature. This must be initialized. * \param s The MPI context in which to store the second part * the signature. This must be initialized. * \param d The private signing key. This must be initialized * and setup, for example through * mbedtls_ecp_gen_privkey(). * \param buf The hashed content to be signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param md_alg The hash algorithm used to hash the original data. * \param f_rng_blind The RNG function used for blinding. This must not be * \c NULL. * \param p_rng_blind The RNG context to be passed to \p f_rng_blind. This may be * \c NULL if \p f_rng_blind doesn't need a context parameter. * \param rs_ctx The restart context to use. This may be \c NULL * to disable restarting. If it is not \c NULL, it * must point to an initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c * mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX, \c * MBEDTLS_ERR_MPI_XXX or \c MBEDTLS_ERR_ASN1_XXX * error code on failure. */ int mbedtls_ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, mbedtls_ecdsa_restart_ctx *rs_ctx); #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ /** * \brief This function verifies the ECDSA signature of a * previously-hashed message. * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.4, step 3. * * \see ecp.h * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param buf The hashed content that was signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param Q The public key to use for verification. This must be * initialized and setup. * \param r The first integer of the signature. * This must be initialized. * \param s The second integer of the signature. * This must be initialized. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * error code on failure. */ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); #if !defined(MBEDTLS_ECDSA_VERIFY_ALT) /** * \brief This function verifies the ECDSA signature of a * previously-hashed message, in a restartable manner * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.4, step 3. * * \see ecp.h * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param buf The hashed content that was signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param Q The public key to use for verification. This must be * initialized and setup. * \param r The first integer of the signature. * This must be initialized. * \param s The second integer of the signature. * This must be initialized. * \param rs_ctx The restart context to use. This may be \c NULL to disable * restarting. If it is not \c NULL, it must point to an * initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * error code on failure. */ int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s, mbedtls_ecdsa_restart_ctx *rs_ctx); #endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ /** * \brief This function computes the ECDSA signature and writes it * to a buffer, serialized as defined in RFC-4492: * Elliptic Curve Cryptography (ECC) Cipher Suites for * Transport Layer Security (TLS). * * \warning It is not thread-safe to use the same context in * multiple threads. * * \note The deterministic version is used if * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more * information, see RFC-6979: Deterministic Usage * of the Digital Signature Algorithm (DSA) and Elliptic * Curve Digital Signature Algorithm (ECDSA). * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.3, step 5. * * \see ecp.h * * \param ctx The ECDSA context to use. This must be initialized * and have a group and private key bound to it, for example * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). * \param md_alg The message digest that was used to hash the message. * \param hash The message hash to be signed. This must be a readable * buffer of length \p hlen Bytes. * \param hlen The length of the hash \p hash in Bytes. * \param sig The buffer to which to write the signature. This must be a * writable buffer of length at least twice as large as the * size of the curve used, plus 9. For example, 73 Bytes if * a 256-bit curve is used. A buffer length of * #MBEDTLS_ECDSA_MAX_LEN is always safe. * \param sig_size The size of the \p sig buffer in bytes. * \param slen The address at which to store the actual length of * the signature written. Must not be \c NULL. * \param f_rng The RNG function. This must not be \c NULL if * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, * it is used only for blinding and may be set to \c NULL, but * doing so is DEPRECATED. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng is \c NULL or doesn't use a context. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function computes the ECDSA signature and writes it * to a buffer, in a restartable way. * * \see \c mbedtls_ecdsa_write_signature() * * \note This function is like \c mbedtls_ecdsa_write_signature() * but it can return early and restart according to the limit * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \param ctx The ECDSA context to use. This must be initialized * and have a group and private key bound to it, for example * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). * \param md_alg The message digest that was used to hash the message. * \param hash The message hash to be signed. This must be a readable * buffer of length \p hlen Bytes. * \param hlen The length of the hash \p hash in Bytes. * \param sig The buffer to which to write the signature. This must be a * writable buffer of length at least twice as large as the * size of the curve used, plus 9. For example, 73 Bytes if * a 256-bit curve is used. A buffer length of * #MBEDTLS_ECDSA_MAX_LEN is always safe. * \param sig_size The size of the \p sig buffer in bytes. * \param slen The address at which to store the actual length of * the signature written. Must not be \c NULL. * \param f_rng The RNG function. This must not be \c NULL if * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, * it is unused and may be set to \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng is \c NULL or doesn't use a context. * \param rs_ctx The restart context to use. This may be \c NULL to disable * restarting. If it is not \c NULL, it must point to an * initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx); /** * \brief This function reads and verifies an ECDSA signature. * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.4, step 3. * * \see ecp.h * * \param ctx The ECDSA context to use. This must be initialized * and have a group and public key bound to it. * \param hash The message hash that was signed. This must be a readable * buffer of length \p hlen Bytes. * \param hlen The size of the hash \p hash. * \param sig The signature to read and verify. This must be a readable * buffer of length \p slen Bytes. * \param slen The size of \p sig in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid * signature in \p sig, but its length is less than \p siglen. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX * error code on failure for any other reason. */ int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen); /** * \brief This function reads and verifies an ECDSA signature, * in a restartable way. * * \see \c mbedtls_ecdsa_read_signature() * * \note This function is like \c mbedtls_ecdsa_read_signature() * but it can return early and restart according to the limit * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \param ctx The ECDSA context to use. This must be initialized * and have a group and public key bound to it. * \param hash The message hash that was signed. This must be a readable * buffer of length \p hlen Bytes. * \param hlen The size of the hash \p hash. * \param sig The signature to read and verify. This must be a readable * buffer of length \p slen Bytes. * \param slen The size of \p sig in Bytes. * \param rs_ctx The restart context to use. This may be \c NULL to disable * restarting. If it is not \c NULL, it must point to an * initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid * signature in \p sig, but its length is less than \p siglen. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX * error code on failure for any other reason. */ int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen, mbedtls_ecdsa_restart_ctx *rs_ctx); /** * \brief This function generates an ECDSA keypair on the given curve. * * \see ecp.h * * \param ctx The ECDSA context to store the keypair in. * This must be initialized. * \param gid The elliptic curve to use. One of the various * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. */ int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function sets up an ECDSA context from an EC key pair. * * \see ecp.h * * \param ctx The ECDSA context to setup. This must be initialized. * \param key The EC key to use. This must be initialized and hold * a private-public key pair or a public key. In the former * case, the ECDSA context may be used for signature creation * and verification after this call. In the latter case, it * may be used for signature verification. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. */ int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key); /** * \brief This function initializes an ECDSA context. * * \param ctx The ECDSA context to initialize. * This must not be \c NULL. */ void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx); /** * \brief This function frees an ECDSA context. * * \param ctx The ECDSA context to free. This may be \c NULL, * in which case this function does nothing. If it * is not \c NULL, it must be initialized. */ void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx); #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context. * * \param ctx The restart context to initialize. * This must not be \c NULL. */ void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx); /** * \brief Free the components of a restart context. * * \param ctx The restart context to free. This may be \c NULL, * in which case this function does nothing. If it * is not \c NULL, it must be initialized. */ void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx); #endif /* MBEDTLS_ECP_RESTARTABLE */ #ifdef __cplusplus } #endif #endif /* ecdsa.h */ webfakes/src/mbedtls/include/mbedtls/psa_util.h0000644000176200001440000001774114740737024021352 0ustar liggesusers/** * \file psa_util.h * * \brief Utility functions for the use of the PSA Crypto library. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PSA_UTIL_H #define MBEDTLS_PSA_UTIL_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "psa/crypto.h" /* ASN1 defines used in the ECDSA conversion functions. * Note: intentionally not adding MBEDTLS_ASN1_[PARSE|WRITE]_C guards here * otherwise error codes would be unknown in test_suite_psa_crypto_util.data.*/ #include #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) /** The random generator function for the PSA subsystem. * * This function is suitable as the `f_rng` random generator function * parameter of many `mbedtls_xxx` functions. * * The implementation of this function depends on the configuration of the * library. * * \note This function may only be used if the PSA crypto subsystem is active. * This means that you must call psa_crypto_init() before any call to * this function, and you must not call this function after calling * mbedtls_psa_crypto_free(). * * \param p_rng This parameter is only kept for backward compatibility * reasons with legacy `f_rng` functions and it's ignored. * Set to #MBEDTLS_PSA_RANDOM_STATE or NULL. * \param output The buffer to fill. It must have room for * \c output_size bytes. * \param output_size The number of bytes to write to \p output. * This function may fail if \p output_size is too * large. It is guaranteed to accept any output size * requested by Mbed TLS library functions. The * maximum request size depends on the library * configuration. * * \return \c 0 on success. * \return An `MBEDTLS_ERR_ENTROPY_xxx`, * `MBEDTLS_ERR_PLATFORM_xxx, * `MBEDTLS_ERR_CTR_DRBG_xxx` or * `MBEDTLS_ERR_HMAC_DRBG_xxx` on error. */ int mbedtls_psa_get_random(void *p_rng, unsigned char *output, size_t output_size); /** The random generator state for the PSA subsystem. * * This macro always expands to NULL because the `p_rng` parameter is unused * in mbedtls_psa_get_random(), but it's kept for interface's backward * compatibility. */ #define MBEDTLS_PSA_RANDOM_STATE NULL /** \defgroup psa_tls_helpers TLS helper functions * @{ */ #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #include /** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. * * \param grpid An Mbed TLS elliptic curve identifier * (`MBEDTLS_ECP_DP_xxx`). * \param[out] bits On success the bit size of the curve; 0 on failure. * * \return If the curve is supported in the PSA API, this function * returns the proper PSA curve identifier * (`PSA_ECC_FAMILY_xxx`). This holds even if the curve is * not supported by the ECP module. * \return \c 0 if the curve is not supported in the PSA API. */ psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid, size_t *bits); /** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. * * \param family A PSA elliptic curve family identifier * (`PSA_ECC_FAMILY_xxx`). * \param bits The bit-length of a private key on \p curve. * * \return If the curve is supported in the PSA API, this function * returns the corresponding Mbed TLS elliptic curve * identifier (`MBEDTLS_ECP_DP_xxx`). * \return #MBEDTLS_ECP_DP_NONE if the combination of \c curve * and \p bits is not supported. */ mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family, size_t bits); #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ /** * \brief This function returns the PSA algorithm identifier * associated with the given digest type. * * \param md_type The type of digest to search for. Must not be NONE. * * \warning If \p md_type is \c MBEDTLS_MD_NONE, this function will * not return \c PSA_ALG_NONE, but an invalid algorithm. * * \warning This function does not check if the algorithm is * supported, it always returns the corresponding identifier. * * \return The PSA algorithm identifier associated with \p md_type, * regardless of whether it is supported or not. */ static inline psa_algorithm_t mbedtls_md_psa_alg_from_type(mbedtls_md_type_t md_type) { return PSA_ALG_CATEGORY_HASH | (psa_algorithm_t) md_type; } /** * \brief This function returns the given digest type * associated with the PSA algorithm identifier. * * \param psa_alg The PSA algorithm identifier to search for. * * \warning This function does not check if the algorithm is * supported, it always returns the corresponding identifier. * * \return The MD type associated with \p psa_alg, * regardless of whether it is supported or not. */ static inline mbedtls_md_type_t mbedtls_md_type_from_psa_alg(psa_algorithm_t psa_alg) { return (mbedtls_md_type_t) (psa_alg & PSA_ALG_HASH_MASK); } #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ #if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** Convert an ECDSA signature from raw format to DER ASN.1 format. * * \param bits Size of each coordinate in bits. * \param raw Buffer that contains the signature in raw format. * \param raw_len Length of \p raw in bytes. This must be * PSA_BITS_TO_BYTES(bits) bytes. * \param[out] der Buffer that will be filled with the converted DER * output. It can overlap with raw buffer. * \param der_size Size of \p der in bytes. It is enough if \p der_size * is at least the size of the actual output. (The size * of the output can vary depending on the presence of * leading zeros in the data.) You can use * #MBEDTLS_ECDSA_MAX_SIG_LEN(\p bits) to determine a * size that is large enough for all signatures for a * given value of \p bits. * \param[out] der_len On success it contains the amount of valid data * (in bytes) written to \p der. It's undefined * in case of failure. */ int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len, unsigned char *der, size_t der_size, size_t *der_len); /** Convert an ECDSA signature from DER ASN.1 format to raw format. * * \param bits Size of each coordinate in bits. * \param der Buffer that contains the signature in DER format. * \param der_len Size of \p der in bytes. * \param[out] raw Buffer that will be filled with the converted raw * signature. It can overlap with der buffer. * \param raw_size Size of \p raw in bytes. Must be at least * 2 * PSA_BITS_TO_BYTES(bits) bytes. * \param[out] raw_len On success it is updated with the amount of valid * data (in bytes) written to \p raw. It's undefined * in case of failure. */ int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len, unsigned char *raw, size_t raw_size, size_t *raw_len); #endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */ /**@}*/ #endif /* MBEDTLS_PSA_UTIL_H */ webfakes/src/mbedtls/include/mbedtls/ripemd160.h0000644000176200001440000000656114740737024021237 0ustar liggesusers/** * \file ripemd160.h * * \brief RIPE MD-160 message digest */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RIPEMD160_H #define MBEDTLS_RIPEMD160_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_RIPEMD160_ALT) // Regular implementation // /** * \brief RIPEMD-160 context structure */ typedef struct mbedtls_ripemd160_context { uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< intermediate digest state */ unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< data block being processed */ } mbedtls_ripemd160_context; #else /* MBEDTLS_RIPEMD160_ALT */ #include "ripemd160_alt.h" #endif /* MBEDTLS_RIPEMD160_ALT */ /** * \brief Initialize RIPEMD-160 context * * \param ctx RIPEMD-160 context to be initialized */ void mbedtls_ripemd160_init(mbedtls_ripemd160_context *ctx); /** * \brief Clear RIPEMD-160 context * * \param ctx RIPEMD-160 context to be cleared */ void mbedtls_ripemd160_free(mbedtls_ripemd160_context *ctx); /** * \brief Clone (the state of) a RIPEMD-160 context * * \param dst The destination context * \param src The context to be cloned */ void mbedtls_ripemd160_clone(mbedtls_ripemd160_context *dst, const mbedtls_ripemd160_context *src); /** * \brief RIPEMD-160 context setup * * \param ctx context to be initialized * * \return 0 if successful */ int mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx); /** * \brief RIPEMD-160 process buffer * * \param ctx RIPEMD-160 context * \param input buffer holding the data * \param ilen length of the input data * * \return 0 if successful */ int mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx, const unsigned char *input, size_t ilen); /** * \brief RIPEMD-160 final digest * * \param ctx RIPEMD-160 context * \param output RIPEMD-160 checksum result * * \return 0 if successful */ int mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx, unsigned char output[20]); /** * \brief RIPEMD-160 process data block (internal use only) * * \param ctx RIPEMD-160 context * \param data buffer holding one block of data * * \return 0 if successful */ int mbedtls_internal_ripemd160_process(mbedtls_ripemd160_context *ctx, const unsigned char data[64]); /** * \brief Output = RIPEMD-160( input buffer ) * * \param input buffer holding the data * \param ilen length of the input data * \param output RIPEMD-160 checksum result * * \return 0 if successful */ int mbedtls_ripemd160(const unsigned char *input, size_t ilen, unsigned char output[20]); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_ripemd160_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_ripemd160.h */ webfakes/src/mbedtls/include/mbedtls/hkdf.h0000644000176200001440000001213214740737024020433 0ustar liggesusers/** * \file hkdf.h * * \brief This file contains the HKDF interface. * * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is * specified by RFC 5869. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_HKDF_H #define MBEDTLS_HKDF_H #include "mbedtls/build_info.h" #include "mbedtls/md.h" /** * \name HKDF Error codes * \{ */ /** Bad input parameters to function. */ #define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /** \} name */ #ifdef __cplusplus extern "C" { #endif /** * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function * (HKDF). * * \param md A hash function; md.size denotes the length of the hash * function output in bytes. * \param salt An optional salt value (a non-secret random value); * if the salt is not provided, a string of all zeros of * md.size length is used as the salt. * \param salt_len The length in bytes of the optional \p salt. * \param ikm The input keying material. * \param ikm_len The length in bytes of \p ikm. * \param info An optional context and application specific information * string. This can be a zero-length string. * \param info_len The length of \p info in bytes. * \param okm The output keying material of \p okm_len bytes. * \param okm_len The length of the output keying material in bytes. This * must be less than or equal to 255 * md.size bytes. * * \return 0 on success. * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying * MD layer. */ int mbedtls_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt, size_t salt_len, const unsigned char *ikm, size_t ikm_len, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len); /** * \brief Take the input keying material \p ikm and extract from it a * fixed-length pseudorandom key \p prk. * * \warning This function should only be used if the security of it has been * studied and established in that particular context (eg. TLS 1.3 * key schedule). For standard HKDF security guarantees use * \c mbedtls_hkdf instead. * * \param md A hash function; md.size denotes the length of the * hash function output in bytes. * \param salt An optional salt value (a non-secret random value); * if the salt is not provided, a string of all zeros * of md.size length is used as the salt. * \param salt_len The length in bytes of the optional \p salt. * \param ikm The input keying material. * \param ikm_len The length in bytes of \p ikm. * \param[out] prk A pseudorandom key of at least md.size bytes. * * \return 0 on success. * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying * MD layer. */ int mbedtls_hkdf_extract(const mbedtls_md_info_t *md, const unsigned char *salt, size_t salt_len, const unsigned char *ikm, size_t ikm_len, unsigned char *prk); /** * \brief Expand the supplied \p prk into several additional pseudorandom * keys, which is the output of the HKDF. * * \warning This function should only be used if the security of it has been * studied and established in that particular context (eg. TLS 1.3 * key schedule). For standard HKDF security guarantees use * \c mbedtls_hkdf instead. * * \param md A hash function; md.size denotes the length of the hash * function output in bytes. * \param prk A pseudorandom key of at least md.size bytes. \p prk is * usually the output from the HKDF extract step. * \param prk_len The length in bytes of \p prk. * \param info An optional context and application specific information * string. This can be a zero-length string. * \param info_len The length of \p info in bytes. * \param okm The output keying material of \p okm_len bytes. * \param okm_len The length of the output keying material in bytes. This * must be less than or equal to 255 * md.size bytes. * * \return 0 on success. * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying * MD layer. */ int mbedtls_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk, size_t prk_len, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len); #ifdef __cplusplus } #endif #endif /* hkdf.h */ webfakes/src/mbedtls/include/mbedtls/md5.h0000644000176200001440000001235714740737024020215 0ustar liggesusers/** * \file md5.h * * \brief MD5 message digest algorithm (hash function) * * \warning MD5 is considered a weak message digest and its use constitutes a * security risk. We recommend considering stronger message * digests instead. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD5_H #define MBEDTLS_MD5_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_MD5_ALT) // Regular implementation // /** * \brief MD5 context structure * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ typedef struct mbedtls_md5_context { uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ uint32_t MBEDTLS_PRIVATE(state)[4]; /*!< intermediate digest state */ unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< data block being processed */ } mbedtls_md5_context; #else /* MBEDTLS_MD5_ALT */ #include "md5_alt.h" #endif /* MBEDTLS_MD5_ALT */ /** * \brief Initialize MD5 context * * \param ctx MD5 context to be initialized * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ void mbedtls_md5_init(mbedtls_md5_context *ctx); /** * \brief Clear MD5 context * * \param ctx MD5 context to be cleared * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ void mbedtls_md5_free(mbedtls_md5_context *ctx); /** * \brief Clone (the state of) an MD5 context * * \param dst The destination context * \param src The context to be cloned * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ void mbedtls_md5_clone(mbedtls_md5_context *dst, const mbedtls_md5_context *src); /** * \brief MD5 context setup * * \param ctx context to be initialized * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5_starts(mbedtls_md5_context *ctx); /** * \brief MD5 process buffer * * \param ctx MD5 context * \param input buffer holding the data * \param ilen length of the input data * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5_update(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen); /** * \brief MD5 final digest * * \param ctx MD5 context * \param output MD5 checksum result * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5_finish(mbedtls_md5_context *ctx, unsigned char output[16]); /** * \brief MD5 process data block (internal use only) * * \param ctx MD5 context * \param data buffer holding one block of data * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, const unsigned char data[64]); /** * \brief Output = MD5( input buffer ) * * \param input buffer holding the data * \param ilen length of the input data * \param output MD5 checksum result * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5(const unsigned char *input, size_t ilen, unsigned char output[16]); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_md5.h */ webfakes/src/mbedtls/include/mbedtls/bignum.h0000644000176200001440000013070714740737024021011 0ustar liggesusers/** * \file bignum.h * * \brief Multi-precision integer library */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_H #define MBEDTLS_BIGNUM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #if defined(MBEDTLS_FS_IO) #include #endif /** An error occurred while reading from or writing to a file. */ #define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /** Bad input parameters to function. */ #define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /** There is an invalid character in the digit string. */ #define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /** The buffer is too small to write to. */ #define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /** The input arguments are negative or result in illegal output. */ #define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /** The input argument for division is zero, which is not allowed. */ #define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /** The input arguments are not acceptable. */ #define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /** Memory allocation failed. */ #define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 #define MBEDTLS_MPI_CHK(f) \ do \ { \ if ((ret = (f)) != 0) \ goto cleanup; \ } while (0) /* * Maximum size MPIs are allowed to grow to in number of limbs. */ #define MBEDTLS_MPI_MAX_LIMBS 10000 #if !defined(MBEDTLS_MPI_WINDOW_SIZE) /* * Maximum window size used for modular exponentiation. Default: 3 * Minimum value: 1. Maximum value: 6. * * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used * for the sliding window calculation. (So 8 by default) * * Reduction in size, reduces speed. */ #define MBEDTLS_MPI_WINDOW_SIZE 3 /**< Maximum window size used. */ #endif /* !MBEDTLS_MPI_WINDOW_SIZE */ #if !defined(MBEDTLS_MPI_MAX_SIZE) /* * Maximum size of MPIs allowed in bits and bytes for user-MPIs. * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) * * Note: Calculations can temporarily result in larger MPIs. So the number * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. */ #define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ #endif /* !MBEDTLS_MPI_MAX_SIZE */ #define MBEDTLS_MPI_MAX_BITS (8 * MBEDTLS_MPI_MAX_SIZE) /**< Maximum number of bits for usable MPIs. */ /* * When reading from files with mbedtls_mpi_read_file() and writing to files with * mbedtls_mpi_write_file() the buffer should have space * for a (short) label, the MPI (in the provided radix), the newline * characters and the '\0'. * * By default we assume at least a 10 char label, a minimum radix of 10 * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). * Autosized at compile time for at least a 10 char label, a minimum radix * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. * * This used to be statically sized to 1250 for a maximum of 4096 bit * numbers (1234 decimal chars). * * Calculate using the formula: * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + * LabelSize + 6 */ #define MBEDTLS_MPI_MAX_BITS_SCALE100 (100 * MBEDTLS_MPI_MAX_BITS) #define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 #define MBEDTLS_MPI_RW_BUFFER_SIZE (((MBEDTLS_MPI_MAX_BITS_SCALE100 + \ MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / \ MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6) /* * Define the base integer type, architecture-wise. * * 32 or 64-bit integer types can be forced regardless of the underlying * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 * respectively and undefining MBEDTLS_HAVE_ASM. * * Double-width integers (e.g. 128-bit in 64-bit architectures) can be * disabled by defining MBEDTLS_NO_UDBL_DIVISION. */ #if !defined(MBEDTLS_HAVE_INT32) #if defined(_MSC_VER) && defined(_M_AMD64) /* Always choose 64-bit when using MSC */ #if !defined(MBEDTLS_HAVE_INT64) #define MBEDTLS_HAVE_INT64 #endif /* !MBEDTLS_HAVE_INT64 */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT64_MAX #elif defined(__GNUC__) && ( \ defined(__amd64__) || defined(__x86_64__) || \ defined(__ppc64__) || defined(__powerpc64__) || \ defined(__ia64__) || defined(__alpha__) || \ (defined(__sparc__) && defined(__arch64__)) || \ defined(__s390x__) || defined(__mips64) || \ defined(__aarch64__)) #if !defined(MBEDTLS_HAVE_INT64) #define MBEDTLS_HAVE_INT64 #endif /* MBEDTLS_HAVE_INT64 */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT64_MAX #if !defined(MBEDTLS_NO_UDBL_DIVISION) /* mbedtls_t_udbl defined as 128-bit unsigned int */ typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); #define MBEDTLS_HAVE_UDBL #endif /* !MBEDTLS_NO_UDBL_DIVISION */ #elif defined(__ARMCC_VERSION) && defined(__aarch64__) /* * __ARMCC_VERSION is defined for both armcc and armclang and * __aarch64__ is only defined by armclang when compiling 64-bit code */ #if !defined(MBEDTLS_HAVE_INT64) #define MBEDTLS_HAVE_INT64 #endif /* !MBEDTLS_HAVE_INT64 */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT64_MAX #if !defined(MBEDTLS_NO_UDBL_DIVISION) /* mbedtls_t_udbl defined as 128-bit unsigned int */ typedef __uint128_t mbedtls_t_udbl; #define MBEDTLS_HAVE_UDBL #endif /* !MBEDTLS_NO_UDBL_DIVISION */ #elif defined(MBEDTLS_HAVE_INT64) /* Force 64-bit integers with unknown compiler */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT64_MAX #endif #endif /* !MBEDTLS_HAVE_INT32 */ #if !defined(MBEDTLS_HAVE_INT64) /* Default to 32-bit compilation */ #if !defined(MBEDTLS_HAVE_INT32) #define MBEDTLS_HAVE_INT32 #endif /* !MBEDTLS_HAVE_INT32 */ typedef int32_t mbedtls_mpi_sint; typedef uint32_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT32_MAX #if !defined(MBEDTLS_NO_UDBL_DIVISION) typedef uint64_t mbedtls_t_udbl; #define MBEDTLS_HAVE_UDBL #endif /* !MBEDTLS_NO_UDBL_DIVISION */ #endif /* !MBEDTLS_HAVE_INT64 */ /* * Sanity check that exactly one of MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 is defined, * so that code elsewhere doesn't have to check. */ #if (!(defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64))) || \ (defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64)) #error "Only 32-bit or 64-bit limbs are supported in bignum" #endif /** \typedef mbedtls_mpi_uint * \brief The type of machine digits in a bignum, called _limbs_. * * This is always an unsigned integer type with no padding bits. The size * is platform-dependent. */ /** \typedef mbedtls_mpi_sint * \brief The signed type corresponding to #mbedtls_mpi_uint. * * This is always an signed integer type with no padding bits. The size * is platform-dependent. */ #ifdef __cplusplus extern "C" { #endif /** * \brief MPI structure */ typedef struct mbedtls_mpi { /** Pointer to limbs. * * This may be \c NULL if \c n is 0. */ mbedtls_mpi_uint *MBEDTLS_PRIVATE(p); /** Sign: -1 if the mpi is negative, 1 otherwise. * * The number 0 must be represented with `s = +1`. Although many library * functions treat all-limbs-zero as equivalent to a valid representation * of 0 regardless of the sign bit, there are exceptions, so bignum * functions and external callers must always set \c s to +1 for the * number zero. * * Note that this implies that calloc() or `... = {0}` does not create * a valid MPI representation. You must call mbedtls_mpi_init(). */ signed short MBEDTLS_PRIVATE(s); /** Total number of limbs in \c p. */ unsigned short MBEDTLS_PRIVATE(n); /* Make sure that MBEDTLS_MPI_MAX_LIMBS fits in n. * Use the same limit value on all platforms so that we don't have to * think about different behavior on the rare platforms where * unsigned short can store values larger than the minimum required by * the C language, which is 65535. */ #if MBEDTLS_MPI_MAX_LIMBS > 65535 #error "MBEDTLS_MPI_MAX_LIMBS > 65535 is not supported" #endif } mbedtls_mpi; /** * \brief Initialize an MPI context. * * This makes the MPI ready to be set or freed, * but does not define a value for the MPI. * * \param X The MPI context to initialize. This must not be \c NULL. */ void mbedtls_mpi_init(mbedtls_mpi *X); /** * \brief This function frees the components of an MPI context. * * \param X The MPI context to be cleared. This may be \c NULL, * in which case this function is a no-op. If it is * not \c NULL, it must point to an initialized MPI. */ void mbedtls_mpi_free(mbedtls_mpi *X); /** * \brief Enlarge an MPI to the specified number of limbs. * * \note This function does nothing if the MPI is * already large enough. * * \param X The MPI to grow. It must be initialized. * \param nblimbs The target number of limbs. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs); /** * \brief This function resizes an MPI downwards, keeping at least the * specified number of limbs. * * If \c X is smaller than \c nblimbs, it is resized up * instead. * * \param X The MPI to shrink. This must point to an initialized MPI. * \param nblimbs The minimum number of limbs to keep. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed * (this can only happen when resizing up). * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs); /** * \brief Make a copy of an MPI. * * \param X The destination MPI. This must point to an initialized MPI. * \param Y The source MPI. This must point to an initialized MPI. * * \note The limb-buffer in the destination MPI is enlarged * if necessary to hold the value in the source MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y); /** * \brief Swap the contents of two MPIs. * * \param X The first MPI. It must be initialized. * \param Y The second MPI. It must be initialized. */ void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y); /** * \brief Perform a safe conditional copy of MPI which doesn't * reveal whether the condition was true or not. * * \param X The MPI to conditionally assign to. This must point * to an initialized MPI. * \param Y The MPI to be assigned from. This must point to an * initialized MPI. * \param assign The condition deciding whether to perform the * assignment or not. Must be either 0 or 1: * * \c 1: Perform the assignment `X = Y`. * * \c 0: Keep the original value of \p X. * * \note This function is equivalent to * `if( assign ) mbedtls_mpi_copy( X, Y );` * except that it avoids leaking any information about whether * the assignment was done or not (the above code may leak * information through branch prediction and/or memory access * patterns analysis). * * \warning If \p assign is neither 0 nor 1, the result of this function * is indeterminate, and the resulting value in \p X might be * neither its original value nor the value in \p Y. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign); /** * \brief Perform a safe conditional swap which doesn't * reveal whether the condition was true or not. * * \param X The first MPI. This must be initialized. * \param Y The second MPI. This must be initialized. * \param swap The condition deciding whether to perform * the swap or not. Must be either 0 or 1: * * \c 1: Swap the values of \p X and \p Y. * * \c 0: Keep the original values of \p X and \p Y. * * \note This function is equivalent to * if( swap ) mbedtls_mpi_swap( X, Y ); * except that it avoids leaking any information about whether * the swap was done or not (the above code may leak * information through branch prediction and/or memory access * patterns analysis). * * \warning If \p swap is neither 0 nor 1, the result of this function * is indeterminate, and both \p X and \p Y might end up with * values different to either of the original ones. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. * */ int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap); /** * \brief Store integer value in MPI. * * \param X The MPI to set. This must be initialized. * \param z The value to use. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z); /** * \brief Get a specific bit from an MPI. * * \param X The MPI to query. This must be initialized. * \param pos Zero-based index of the bit to query. * * \return \c 0 or \c 1 on success, depending on whether bit \c pos * of \c X is unset or set. * \return A negative error code on failure. */ int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos); /** * \brief Modify a specific bit in an MPI. * * \note This function will grow the target MPI if necessary to set a * bit to \c 1 in a not yet existing limb. It will not grow if * the bit should be set to \c 0. * * \param X The MPI to modify. This must be initialized. * \param pos Zero-based index of the bit to modify. * \param val The desired value of bit \c pos: \c 0 or \c 1. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val); /** * \brief Return the number of bits of value \c 0 before the * least significant bit of value \c 1. * * \note This is the same as the zero-based index of * the least significant bit of value \c 1. * * \param X The MPI to query. * * \return The number of bits of value \c 0 before the least significant * bit of value \c 1 in \p X. */ size_t mbedtls_mpi_lsb(const mbedtls_mpi *X); /** * \brief Return the number of bits up to and including the most * significant bit of value \c 1. * * * \note This is same as the one-based index of the most * significant bit of value \c 1. * * \param X The MPI to query. This must point to an initialized MPI. * * \return The number of bits up to and including the most * significant bit of value \c 1. */ size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X); /** * \brief Return the total size of an MPI value in bytes. * * \param X The MPI to use. This must point to an initialized MPI. * * \note The value returned by this function may be less than * the number of bytes used to store \p X internally. * This happens if and only if there are trailing bytes * of value zero. * * \return The least number of bytes capable of storing * the absolute value of \p X. */ size_t mbedtls_mpi_size(const mbedtls_mpi *X); /** * \brief Import an MPI from an ASCII string. * * \param X The destination MPI. This must point to an initialized MPI. * \param radix The numeric base of the input string. * \param s Null-terminated string buffer. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s); /** * \brief Export an MPI to an ASCII string. * * \param X The source MPI. This must point to an initialized MPI. * \param radix The numeric base of the output string. * \param buf The buffer to write the string to. This must be writable * buffer of length \p buflen Bytes. * \param buflen The available size in Bytes of \p buf. * \param olen The address at which to store the length of the string * written, including the final \c NULL byte. This must * not be \c NULL. * * \note You can call this function with `buflen == 0` to obtain the * minimum required buffer size in `*olen`. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf * is too small to hold the value of \p X in the desired base. * In this case, `*olen` is nonetheless updated to contain the * size of \p buf required for a successful call. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix, char *buf, size_t buflen, size_t *olen); #if defined(MBEDTLS_FS_IO) /** * \brief Read an MPI from a line in an opened file. * * \param X The destination MPI. This must point to an initialized MPI. * \param radix The numeric base of the string representation used * in the source line. * \param fin The input file handle to use. This must not be \c NULL. * * \note On success, this function advances the file stream * to the end of the current line or to EOF. * * The function returns \c 0 on an empty line. * * Leading whitespaces are ignored, as is a * '0x' prefix for radix \c 16. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer * is too small. * \return Another negative error code on failure. */ int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin); /** * \brief Export an MPI into an opened file. * * \param p A string prefix to emit prior to the MPI data. * For example, this might be a label, or "0x" when * printing in base \c 16. This may be \c NULL if no prefix * is needed. * \param X The source MPI. This must point to an initialized MPI. * \param radix The numeric base to be used in the emitted string. * \param fout The output file handle. This may be \c NULL, in which case * the output is written to \c stdout. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout); #endif /* MBEDTLS_FS_IO */ /** * \brief Import an MPI from unsigned big endian binary data. * * \param X The destination MPI. This must point to an initialized MPI. * \param buf The input buffer. This must be a readable buffer of length * \p buflen Bytes. * \param buflen The length of the input buffer \p buf in Bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen); /** * \brief Import X from unsigned binary data, little endian * * \param X The destination MPI. This must point to an initialized MPI. * \param buf The input buffer. This must be a readable buffer of length * \p buflen Bytes. * \param buflen The length of the input buffer \p buf in Bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_read_binary_le(mbedtls_mpi *X, const unsigned char *buf, size_t buflen); /** * \brief Export X into unsigned binary data, big endian. * Always fills the whole buffer, which will start with zeros * if the number is smaller. * * \param X The source MPI. This must point to an initialized MPI. * \param buf The output buffer. This must be a writable buffer of length * \p buflen Bytes. * \param buflen The size of the output buffer \p buf in Bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't * large enough to hold the value of \p X. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_write_binary(const mbedtls_mpi *X, unsigned char *buf, size_t buflen); /** * \brief Export X into unsigned binary data, little endian. * Always fills the whole buffer, which will end with zeros * if the number is smaller. * * \param X The source MPI. This must point to an initialized MPI. * \param buf The output buffer. This must be a writable buffer of length * \p buflen Bytes. * \param buflen The size of the output buffer \p buf in Bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't * large enough to hold the value of \p X. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X, unsigned char *buf, size_t buflen); /** * \brief Perform a left-shift on an MPI: X <<= count * * \param X The MPI to shift. This must point to an initialized MPI. * The MPI pointed by \p X may be resized to fit * the resulting number. * \param count The number of bits to shift by. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count); /** * \brief Perform a right-shift on an MPI: X >>= count * * \param X The MPI to shift. This must point to an initialized MPI. * \param count The number of bits to shift by. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count); /** * \brief Compare the absolute values of two MPIs. * * \param X The left-hand MPI. This must point to an initialized MPI. * \param Y The right-hand MPI. This must point to an initialized MPI. * * \return \c 1 if `|X|` is greater than `|Y|`. * \return \c -1 if `|X|` is lesser than `|Y|`. * \return \c 0 if `|X|` is equal to `|Y|`. */ int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y); /** * \brief Compare two MPIs. * * \param X The left-hand MPI. This must point to an initialized MPI. * \param Y The right-hand MPI. This must point to an initialized MPI. * * \return \c 1 if \p X is greater than \p Y. * \return \c -1 if \p X is lesser than \p Y. * \return \c 0 if \p X is equal to \p Y. */ int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y); /** * \brief Check if an MPI is less than the other in constant time. * * \param X The left-hand MPI. This must point to an initialized MPI * with the same allocated length as Y. * \param Y The right-hand MPI. This must point to an initialized MPI * with the same allocated length as X. * \param ret The result of the comparison: * \c 1 if \p X is less than \p Y. * \c 0 if \p X is greater than or equal to \p Y. * * \return 0 on success. * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of * the two input MPIs is not the same. */ int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned *ret); /** * \brief Compare an MPI with an integer. * * \param X The left-hand MPI. This must point to an initialized MPI. * \param z The integer value to compare \p X to. * * \return \c 1 if \p X is greater than \p z. * \return \c -1 if \p X is lesser than \p z. * \return \c 0 if \p X is equal to \p z. */ int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z); /** * \brief Perform an unsigned addition of MPIs: X = |A| + |B| * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first summand. This must point to an initialized MPI. * \param B The second summand. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| * * \param X The destination MPI. This must point to an initialized MPI. * \param A The minuend. This must point to an initialized MPI. * \param B The subtrahend. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. * \return Another negative error code on different kinds of failure. * */ int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a signed addition of MPIs: X = A + B * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first summand. This must point to an initialized MPI. * \param B The second summand. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a signed subtraction of MPIs: X = A - B * * \param X The destination MPI. This must point to an initialized MPI. * \param A The minuend. This must point to an initialized MPI. * \param B The subtrahend. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a signed addition of an MPI and an integer: X = A + b * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first summand. This must point to an initialized MPI. * \param b The second summand. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Perform a signed subtraction of an MPI and an integer: * X = A - b * * \param X The destination MPI. This must point to an initialized MPI. * \param A The minuend. This must point to an initialized MPI. * \param b The subtrahend. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Perform a multiplication of two MPIs: X = A * B * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first factor. This must point to an initialized MPI. * \param B The second factor. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. * */ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a multiplication of an MPI with an unsigned integer: * X = A * b * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first factor. This must point to an initialized MPI. * \param b The second factor. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. * */ int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b); /** * \brief Perform a division with remainder of two MPIs: * A = Q * B + R * * \param Q The destination MPI for the quotient. * This may be \c NULL if the value of the * quotient is not needed. This must not alias A or B. * \param R The destination MPI for the remainder value. * This may be \c NULL if the value of the * remainder is not needed. This must not alias A or B. * \param A The dividend. This must point to an initialized MPI. * \param B The divisor. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a division with remainder of an MPI by an integer: * A = Q * b + R * * \param Q The destination MPI for the quotient. * This may be \c NULL if the value of the * quotient is not needed. This must not alias A. * \param R The destination MPI for the remainder value. * This may be \c NULL if the value of the * remainder is not needed. This must not alias A. * \param A The dividend. This must point to an initialized MPi. * \param b The divisor. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Perform a modular reduction. R = A mod B * * \param R The destination MPI for the residue value. * This must point to an initialized MPI. * \param A The MPI to compute the residue of. * This must point to an initialized MPI. * \param B The base of the modular reduction. * This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. * \return Another negative error code on different kinds of failure. * */ int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a modular reduction with respect to an integer. * r = A mod b * * \param r The address at which to store the residue. * This must not be \c NULL. * \param A The MPI to compute the residue of. * This must point to an initialized MPi. * \param b The integer base of the modular reduction. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Perform a modular exponentiation: X = A^E mod N * * \param X The destination MPI. This must point to an initialized MPI. * This must not alias E or N. * \param A The base of the exponentiation. * This must point to an initialized MPI. * \param E The exponent MPI. This must point to an initialized MPI. * \param N The base for the modular reduction. This must point to an * initialized MPI. * \param prec_RR A helper MPI depending solely on \p N which can be used to * speed-up multiple modular exponentiations for the same value * of \p N. This may be \c NULL. If it is not \c NULL, it must * point to an initialized MPI. If it hasn't been used after * the call to mbedtls_mpi_init(), this function will compute * the helper value and store it in \p prec_RR for reuse on * subsequent calls to this function. Otherwise, the function * will assume that \p prec_RR holds the helper value set by a * previous call to mbedtls_mpi_exp_mod(), and reuse it. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or * even, or if \c E is negative. * \return Another negative error code on different kinds of failures. * */ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *prec_RR); /** * \brief Fill an MPI with a number of random bytes. * * \param X The destination MPI. This must point to an initialized MPI. * \param size The number of random bytes to generate. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on failure. * * \note The bytes obtained from the RNG are interpreted * as a big-endian representation of an MPI; this can * be relevant in applications like deterministic ECDSA. */ int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Generate a random number uniformly in a range. * * This function generates a random number between \p min inclusive and * \p N exclusive. * * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) * when the RNG is a suitably parametrized instance of HMAC_DRBG * and \p min is \c 1. * * \note There are `N - min` possible outputs. The lower bound * \p min can be reached, but the upper bound \p N cannot. * * \param X The destination MPI. This must point to an initialized MPI. * \param min The minimum value to return. * It must be nonnegative. * \param N The upper bound of the range, exclusive. * In other words, this is one plus the maximum value to return. * \p N must be strictly larger than \p min. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p min or \p N is invalid * or if they are incompatible. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was * unable to find a suitable value within a limited number * of attempts. This has a negligible probability if \p N * is significantly larger than \p min, which is the case * for all usual cryptographic applications. * \return Another negative error code on failure. */ int mbedtls_mpi_random(mbedtls_mpi *X, mbedtls_mpi_sint min, const mbedtls_mpi *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Compute the greatest common divisor: G = gcd(A, B) * * \param G The destination MPI. This must point to an initialized MPI. * \param A The first operand. This must point to an initialized MPI. * \param B The second operand. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Compute the modular inverse: X = A^-1 mod N * * \param X The destination MPI. This must point to an initialized MPI. * \param A The MPI to calculate the modular inverse of. This must point * to an initialized MPI. * \param N The base of the modular inversion. This must point to an * initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than * or equal to one. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p A has no modular * inverse with respect to \p N. */ int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N); /** * \brief Miller-Rabin primality test. * * \warning If \p X is potentially generated by an adversary, for example * when validating cryptographic parameters that you didn't * generate yourself and that are supposed to be prime, then * \p rounds should be at least the half of the security * strength of the cryptographic algorithm. On the other hand, * if \p X is chosen uniformly or non-adversarially (as is the * case when mbedtls_mpi_gen_prime calls this function), then * \p rounds can be much lower. * * \param X The MPI to check for primality. * This must point to an initialized MPI. * \param rounds The number of bases to perform the Miller-Rabin primality * test for. The probability of returning 0 on a composite is * at most 2-2*\p rounds . * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * This may be \c NULL if \p f_rng doesn't use * a context parameter. * * \return \c 0 if successful, i.e. \p X is probably prime. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Flags for mbedtls_mpi_gen_prime() * * Each of these flags is a constraint on the result X returned by * mbedtls_mpi_gen_prime(). */ typedef enum { MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2-80 to 2-128 */ } mbedtls_mpi_gen_prime_flag_t; /** * \brief Generate a prime number. * * \param X The destination MPI to store the generated prime in. * This must point to an initialized MPi. * \param nbits The required size of the destination MPI in bits. * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * This may be \c NULL if \p f_rng doesn't use * a context parameter. * * \return \c 0 if successful, in which case \p X holds a * probably prime number. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between * \c 3 and #MBEDTLS_MPI_MAX_BITS. */ int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_mpi_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* bignum.h */ webfakes/src/mbedtls/include/mbedtls/check_config.h0000644000176200001440000013535114740737024022132 0ustar liggesusers/** * \file check_config.h * * \brief Consistency checks for configuration options * * This is an internal header. Do not include it directly. * * This header is included automatically by all public Mbed TLS headers * (via mbedtls/build_info.h). Do not include it directly in a configuration * file such as mbedtls/mbedtls_config.h or #MBEDTLS_USER_CONFIG_FILE! * It would run at the wrong time due to missing derived symbols. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CHECK_CONFIG_H #define MBEDTLS_CHECK_CONFIG_H /* *INDENT-OFF* */ #if !defined(MBEDTLS_CONFIG_IS_FINALIZED) #warning "Do not include mbedtls/check_config.h manually! " \ "This may cause spurious errors. " \ "It is included automatically at the right point since Mbed TLS 3.0." #endif /* !MBEDTLS_CONFIG_IS_FINALIZED */ /* * We assume CHAR_BIT is 8 in many places. In practice, this is true on our * target platforms, so not an issue, but let's just be extra sure. */ #include #if CHAR_BIT != 8 #error "Mbed TLS requires a platform with 8-bit chars" #endif #include #if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) #if !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_C is required on Windows" #endif /* See auto-enabling SNPRINTF_ALT and VSNPRINTF_ALT * in * config_adjust_legacy_crypto.h */ #endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */ #if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C) #error "The NET module is not available for mbed OS - please use the network functions provided by Mbed OS" #endif #if defined(MBEDTLS_DEPRECATED_WARNING) && \ !defined(__GNUC__) && !defined(__clang__) #error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" #endif #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) #error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" #endif /* Limitations on ECC key types acceleration: if we have any of `PUBLIC_KEY`, * `KEY_PAIR_BASIC`, `KEY_PAIR_IMPORT`, `KEY_PAIR_EXPORT` then we must have * all 4 of them. */ #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #error "Unsupported partial support for ECC key type acceleration, see docs/driver-only-builds.md" #endif /* not all of public, basic, import, export */ #endif /* one of public, basic, import, export */ /* Limitations on ECC curves acceleration: partial curve acceleration is only * supported with crypto excluding PK, X.509 or TLS. * Note: no need to check X.509 as it depends on PK. */ #if defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \ defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \ defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \ defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \ defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) #if defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #if defined(MBEDTLS_PK_C) || \ defined(MBEDTLS_SSL_TLS_C) #error "Unsupported partial support for ECC curves acceleration, see docs/driver-only-builds.md" #endif /* modules beyond what's supported */ #endif /* not all curves accelerated */ #endif /* some curve accelerated */ #if defined(MBEDTLS_CTR_DRBG_C) && !(defined(MBEDTLS_AES_C) || \ (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_KEY_TYPE_AES) && \ defined(PSA_WANT_ALG_ECB_NO_PADDING))) #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) #error "MBEDTLS_DHM_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_CMAC_C) && \ ( !defined(MBEDTLS_CIPHER_C ) || ( !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) ) ) #error "MBEDTLS_CMAC_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_NIST_KW_C) && \ ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) #error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) && defined(MBEDTLS_PSA_CRYPTO_CONFIG) #if defined(PSA_WANT_ALG_CBC_NO_PADDING) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_NO_PADDING cannot be defined simultaneously" #endif #if defined(PSA_WANT_ALG_CBC_PKCS7) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_PKCS7 cannot be defined simultaneously" #endif #if defined(PSA_WANT_ALG_ECB_NO_PADDING) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_ECB_NO_PADDING cannot be defined simultaneously" #endif #if defined(PSA_WANT_KEY_TYPE_DES) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_KEY_TYPE_DES cannot be defined simultaneously" #endif #endif #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) #if defined(MBEDTLS_CIPHER_MODE_CBC) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_CBC cannot be defined simultaneously" #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_XTS cannot be defined simultaneously" #endif #if defined(MBEDTLS_DES_C) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_DES_C cannot be defined simultaneously" #endif #if defined(MBEDTLS_NIST_KW_C) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_NIST_KW_C cannot be defined simultaneously" #endif #endif #if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECDH_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECDSA_C) && \ ( !defined(MBEDTLS_ECP_C) || \ !( defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) ) || \ !defined(MBEDTLS_ASN1_PARSE_C) || \ !defined(MBEDTLS_ASN1_WRITE_C) ) #error "MBEDTLS_ECDSA_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && !defined(MBEDTLS_ASN1_WRITE_C) #error "MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_WRITE_C for ECDSA signature" #endif #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) && !defined(MBEDTLS_ASN1_PARSE_C) #error "MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_PARSE_C for ECDSA verification" #endif #endif /* MBEDTLS_PK_C && MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_ECJPAKE_C) && \ !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_RESTARTABLE) && \ ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ defined(MBEDTLS_ECDSA_SIGN_ALT) || \ defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ defined(MBEDTLS_ECP_INTERNAL_ALT) || \ defined(MBEDTLS_ECP_ALT) ) #error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation" #endif #if defined(MBEDTLS_ECP_RESTARTABLE) && \ !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECP_RESTARTABLE defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_LIGHT) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) ) #error "MBEDTLS_ECP_C defined (or a subset enabled), but not all prerequisites" #endif #if defined(MBEDTLS_ENTROPY_C) && \ !(defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA256)) #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ENTROPY_C) && \ defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) #error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" #endif #if defined(MBEDTLS_ENTROPY_C) && \ (defined(MBEDTLS_ENTROPY_FORCE_SHA256) || !defined(MBEDTLS_MD_CAN_SHA512)) \ && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) #error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" #endif #if defined(MBEDTLS_ENTROPY_C) && \ defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_MD_CAN_SHA256) #error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" #endif #if defined(__has_feature) #if __has_feature(memory_sanitizer) #define MBEDTLS_HAS_MEMSAN // #undef at the end of this paragraph #endif #endif #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) #error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" #endif #undef MBEDTLS_HAS_MEMSAN // temporary macro defined above #if defined(MBEDTLS_CCM_C) && \ !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \ defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA)) #error "MBEDTLS_CCM_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_GCM_C) && \ !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \ defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA)) #error "MBEDTLS_GCM_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_CHACHA20_C) #error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_POLY1305_C) #error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_NO_FALLBACK) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled" #endif #if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) #error "MBEDTLS_HKDF_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) #error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ ( !defined(MBEDTLS_CAN_ECDH) || \ !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) #error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ !defined(MBEDTLS_CAN_ECDH) #error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ ( !defined(MBEDTLS_CAN_ECDH) || \ !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ ( !defined(PSA_WANT_ALG_JPAKE) || \ !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ !defined(PSA_WANT_ECC_SECP_R1_256) ) #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" #endif #else /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ ( !defined(MBEDTLS_ECJPAKE_C) || \ !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Use of EC J-PAKE in TLS requires SHA-256. */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ !defined(MBEDTLS_MD_CAN_SHA256) #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ !defined(MBEDTLS_MD_CAN_SHA256) && \ !defined(MBEDTLS_MD_CAN_SHA512) && \ !defined(MBEDTLS_MD_CAN_SHA1) #error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires SHA-512, SHA-256 or SHA-1". #endif #if defined(MBEDTLS_MD_C) && \ !defined(MBEDTLS_MD_CAN_MD5) && \ !defined(MBEDTLS_MD_CAN_RIPEMD160) && \ !defined(MBEDTLS_MD_CAN_SHA1) && \ !defined(MBEDTLS_MD_CAN_SHA224) && \ !defined(MBEDTLS_MD_CAN_SHA256) && \ !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA512) && \ !defined(MBEDTLS_MD_CAN_SHA3_224) && \ !defined(MBEDTLS_MD_CAN_SHA3_256) && \ !defined(MBEDTLS_MD_CAN_SHA3_384) && \ !defined(MBEDTLS_MD_CAN_SHA3_512) #error "MBEDTLS_MD_C defined, but no hash algorithm" #endif #if defined(MBEDTLS_LMS_C) && \ ! ( defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_ALG_SHA_256) ) #error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256" #endif #if defined(MBEDTLS_LMS_PRIVATE) && \ ( !defined(MBEDTLS_LMS_C) ) #error "MBEDTLS_LMS_PRIVATE requires MBEDTLS_LMS_C" #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) #error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequisites" #endif #if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites" #endif #if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) #error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) #error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PK_C) && \ !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_PK_HAVE_ECC_KEYS) #error "MBEDTLS_PK_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PK_PARSE_C) && \ (!defined(MBEDTLS_ASN1_PARSE_C) || \ !defined(MBEDTLS_OID_C) || \ !defined(MBEDTLS_PK_C)) #error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PK_WRITE_C) && \ (!defined(MBEDTLS_ASN1_WRITE_C) || \ !defined(MBEDTLS_OID_C) || \ !defined(MBEDTLS_PK_C)) #error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ defined(MBEDTLS_PLATFORM_EXIT_ALT) ) #error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_SETBUF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_SETBUF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_SETBUF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_SETBUF) ||\ defined(MBEDTLS_PLATFORM_SETBUF_ALT) ) #error "MBEDTLS_PLATFORM_SETBUF_MACRO and MBEDTLS_PLATFORM_STD_SETBUF/MBEDTLS_PLATFORM_SETBUF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ ( !defined(MBEDTLS_PLATFORM_C) ||\ !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) ||\ !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_MS_TIME_ALT) && \ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_MS_TIME_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) ||\ !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ defined(MBEDTLS_PLATFORM_TIME_ALT) ) #error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ defined(MBEDTLS_PLATFORM_TIME_ALT) ) #error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) #error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) #error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ defined(MBEDTLS_PLATFORM_STD_FREE) #error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) #error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" #endif #if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) #error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ defined(MBEDTLS_PLATFORM_STD_CALLOC) #error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) #error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" #endif #if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) #error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) #error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_VSNPRINTF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) ||\ defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) ) #error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_VSNPRINTF/MBEDTLS_PLATFORM_VSNPRINTF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) #error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) #error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) #error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ !defined(MBEDTLS_PLATFORM_EXIT_ALT) #error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) #error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ !defined(MBEDTLS_PLATFORM_PRINTF_ALT) #error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) #error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) #error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ !defined(MBEDTLS_ENTROPY_NV_SEED) #error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) #error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) #error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) #error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) #error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" #endif #if defined(MBEDTLS_PSA_CRYPTO_C) && \ !( ( ( defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C) ) && \ defined(MBEDTLS_ENTROPY_C) ) || \ defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) ) #error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)" #endif #if defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_HAVE_SOFT_BLOCK_MODE) && \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) && !defined(MBEDTLS_CIPHER_C) #error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C) #error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \ ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \ defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) ) #error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #if defined(MBEDTLS_DEPRECATED_REMOVED) #error "MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS" #elif defined(MBEDTLS_DEPRECATED_WARNING) #warning "MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS" #endif #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ ! defined(MBEDTLS_PSA_CRYPTO_C) #error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ defined(MBEDTLS_ENTROPY_NV_SEED) ) #error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) #error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" #endif #if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) #error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG" #endif #if defined(MBEDTLS_PSA_ITS_FILE_C) && \ !defined(MBEDTLS_FS_IO) #error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ !defined(MBEDTLS_OID_C) ) #error "MBEDTLS_RSA_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) #error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" #endif #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) && \ defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) #error "Must only define one of MBEDTLS_SHA512_USE_A64_CRYPTO_*" #endif #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) #if !defined(MBEDTLS_SHA512_C) #error "MBEDTLS_SHA512_USE_A64_CRYPTO_* defined without MBEDTLS_SHA512_C" #endif #if defined(MBEDTLS_SHA512_ALT) || defined(MBEDTLS_SHA512_PROCESS_ALT) #error "MBEDTLS_SHA512_*ALT can't be used with MBEDTLS_SHA512_USE_A64_CRYPTO_*" #endif #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) && !defined(__aarch64__) #error "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system" #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) && \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #error "Must only define one of MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #if !defined(MBEDTLS_SHA256_C) #error "MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_* defined without MBEDTLS_SHA256_C" #endif #if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA256_PROCESS_ALT) #error "MBEDTLS_SHA256_*ALT can't be used with MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" #endif #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) && !defined(MBEDTLS_ARCH_IS_ARMV8_A) #error "MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY defined on non-Armv8-A system" #endif /* TLS 1.3 requires separate HKDF parts from PSA, * and at least one ciphersuite, so at least SHA-256 or SHA-384 * from PSA to use with HKDF. * * Note: for dependencies common with TLS 1.2 (running handshake hash), * see MBEDTLS_SSL_TLS_C. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ !(defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \ defined(PSA_WANT_ALG_HKDF_EXTRACT) && \ defined(PSA_WANT_ALG_HKDF_EXPAND) && \ (defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384))) #error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #if !( (defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)) && \ defined(MBEDTLS_X509_CRT_PARSE_C) && \ ( defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || defined(MBEDTLS_PKCS1_V21) ) ) #error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED defined, but not all prerequisites" #endif #endif #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) #if !( defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) ) #error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED defined, but not all prerequisites" #endif #endif /* * The current implementation of TLS 1.3 requires MBEDTLS_SSL_KEEP_PEER_CERTIFICATE. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) #error "MBEDTLS_SSL_PROTO_TLS1_3 defined without MBEDTLS_SSL_KEEP_PEER_CERTIFICATE" #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ) #error "One or more versions of the TLS protocol are enabled " \ "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" #endif #if defined(MBEDTLS_SSL_EARLY_DATA) && \ ( !defined(MBEDTLS_SSL_SESSION_TICKETS) || \ ( !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) && \ !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) ) ) #error "MBEDTLS_SSL_EARLY_DATA defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) && \ ((MBEDTLS_SSL_MAX_EARLY_DATA_SIZE < 0) || \ (MBEDTLS_SSL_MAX_EARLY_DATA_SIZE > UINT32_MAX)) #error "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE must be in the range(0..UINT32_MAX)" #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) #error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && !defined(MBEDTLS_X509_CRT_PARSE_C) #error "MBEDTLS_SSL_ASYNC_PRIVATE defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TLS_C) && !(defined(MBEDTLS_CIPHER_C) || \ defined(MBEDTLS_USE_PSA_CRYPTO)) #error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" #endif /* TLS 1.2 and 1.3 require SHA-256 or SHA-384 (running handshake hash) */ #if defined(MBEDTLS_SSL_TLS_C) #if defined(MBEDTLS_USE_PSA_CRYPTO) #if !(defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384)) #error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" #endif #else /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_MD_C) || \ !(defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA384)) #error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) #error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TLS_C) && \ !( defined(MBEDTLS_SSL_PROTO_TLS1_2) || defined(MBEDTLS_SSL_PROTO_TLS1_3) ) #error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) #error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) #error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) #error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) #error "MBEDTLS_SSL_DTLS_CONNECTION_ID defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && \ MBEDTLS_SSL_CID_IN_LEN_MAX > 255 #error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && \ MBEDTLS_SSL_CID_OUT_LEN_MAX > 255 #error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) && \ !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 #if defined(MBEDTLS_DEPRECATED_REMOVED) #error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS" #elif defined(MBEDTLS_DEPRECATED_WARNING) #warning "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS" #endif #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_RENEGOTIATION defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TICKET_C) && ( !defined(MBEDTLS_CIPHER_C) && \ !defined(MBEDTLS_USE_PSA_CRYPTO) ) #error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TICKET_C) && \ !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \ defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) ) #error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH) && \ MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH >= 256 #error "MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH must be less than 256" #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ !defined(MBEDTLS_X509_CRT_PARSE_C) #error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" #endif #if defined(MBEDTLS_THREADING_PTHREAD) #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" #endif #define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph #endif #if defined(MBEDTLS_THREADING_ALT) #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" #endif #define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph #endif #if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_C defined, single threading implementation required" #endif #undef MBEDTLS_THREADING_IMPL // temporary macro defined above #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_CLIENT) #error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites" #endif #if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) #error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_USE_C) && \ (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ !defined(MBEDTLS_PK_PARSE_C) || \ ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) ) #error "MBEDTLS_X509_USE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CREATE_C) && \ (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ !defined(MBEDTLS_PK_PARSE_C) || \ ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) ) #error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) #error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) #error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) #error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) #error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) #error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) && \ ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK defined, but not all prerequisites" #endif #if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) #error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" #endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ #if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ defined(MBEDTLS_HAVE_ASM) #error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" #endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ #if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) ) #error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && ( !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) ) #error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && ( !defined(MBEDTLS_SSL_PROTO_TLS1_3) ) #error "MBEDTLS_SSL_RECORD_SIZE_LIMIT defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && \ !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \ defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) ) #error "MBEDTLS_SSL_CONTEXT_SERIALIZATION defined, but not all prerequisites" #endif /* Reject attempts to enable options that have been removed and that could * cause a build to succeed but with features removed. */ #if defined(MBEDTLS_HAVEGE_C) //no-check-names #error "MBEDTLS_HAVEGE_C was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/2599" #endif #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) //no-check-names #error "MBEDTLS_SSL_HW_RECORD_ACCEL was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_SSL_PROTO_SSL3) //no-check-names #error "MBEDTLS_SSL_PROTO_SSL3 (SSL v3.0 support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) //no-check-names #error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO (SSL v2 ClientHello support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) //no-check-names #error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT (compatibility with the buggy implementation of truncated HMAC in Mbed TLS up to 2.7) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) //no-check-names #error "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES was removed in Mbed TLS 3.0. See the ChangeLog entry if you really need SHA-1-signed certificates." #endif #if defined(MBEDTLS_ZLIB_SUPPORT) //no-check-names #error "MBEDTLS_ZLIB_SUPPORT was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_CHECK_PARAMS) //no-check-names #error "MBEDTLS_CHECK_PARAMS was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4313" #endif #if defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) //no-check-names #error "MBEDTLS_SSL_CID_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335" #endif #if defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) //no-check-names #error "MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335" #endif #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) //no-check-names #error "MBEDTLS_SSL_TRUNCATED_HMAC was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4341" #endif #if defined(MBEDTLS_PKCS7_C) && ( ( !defined(MBEDTLS_ASN1_PARSE_C) ) || \ ( !defined(MBEDTLS_OID_C) ) || ( !defined(MBEDTLS_PK_PARSE_C) ) || \ ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) || \ ( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || \ ( !defined(MBEDTLS_MD_C) ) ) #error "MBEDTLS_PKCS7_C is defined, but not all prerequisites" #endif /* * Avoid warning from -pedantic. This is a convenient place for this * workaround since this is included by every single file before the * #if defined(MBEDTLS_xxx_C) that results in empty translation units. */ typedef int mbedtls_iso_c_forbids_empty_translation_units; /* *INDENT-ON* */ #endif /* MBEDTLS_CHECK_CONFIG_H */ webfakes/src/mbedtls/include/mbedtls/debug.h0000644000176200001440000001216514740737024020613 0ustar liggesusers/** * \file debug.h * * \brief Functions for controlling and providing debug output from the library. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_DEBUG_H #define MBEDTLS_DEBUG_H #include "mbedtls/build_info.h" #include "mbedtls/ssl.h" #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_DEBUG_C) #define MBEDTLS_DEBUG_STRIP_PARENS(...) __VA_ARGS__ #define MBEDTLS_SSL_DEBUG_MSG(level, args) \ mbedtls_debug_print_msg(ssl, level, __FILE__, __LINE__, \ MBEDTLS_DEBUG_STRIP_PARENS args) #define MBEDTLS_SSL_DEBUG_RET(level, text, ret) \ mbedtls_debug_print_ret(ssl, level, __FILE__, __LINE__, text, ret) #define MBEDTLS_SSL_DEBUG_BUF(level, text, buf, len) \ mbedtls_debug_print_buf(ssl, level, __FILE__, __LINE__, text, buf, len) #if defined(MBEDTLS_BIGNUM_C) #define MBEDTLS_SSL_DEBUG_MPI(level, text, X) \ mbedtls_debug_print_mpi(ssl, level, __FILE__, __LINE__, text, X) #endif #if defined(MBEDTLS_ECP_C) #define MBEDTLS_SSL_DEBUG_ECP(level, text, X) \ mbedtls_debug_print_ecp(ssl, level, __FILE__, __LINE__, text, X) #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if !defined(MBEDTLS_X509_REMOVE_INFO) #define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) \ mbedtls_debug_print_crt(ssl, level, __FILE__, __LINE__, text, crt) #else #define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) do { } while (0) #endif /* MBEDTLS_X509_REMOVE_INFO */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_ECDH_C) #define MBEDTLS_SSL_DEBUG_ECDH(level, ecdh, attr) \ mbedtls_debug_printf_ecdh(ssl, level, __FILE__, __LINE__, ecdh, attr) #endif #else /* MBEDTLS_DEBUG_C */ #define MBEDTLS_SSL_DEBUG_MSG(level, args) do { } while (0) #define MBEDTLS_SSL_DEBUG_RET(level, text, ret) do { } while (0) #define MBEDTLS_SSL_DEBUG_BUF(level, text, buf, len) do { } while (0) #define MBEDTLS_SSL_DEBUG_MPI(level, text, X) do { } while (0) #define MBEDTLS_SSL_DEBUG_ECP(level, text, X) do { } while (0) #define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) do { } while (0) #define MBEDTLS_SSL_DEBUG_ECDH(level, ecdh, attr) do { } while (0) #endif /* MBEDTLS_DEBUG_C */ /** * \def MBEDTLS_PRINTF_ATTRIBUTE * * Mark a function as having printf attributes, and thus enable checking * via -wFormat and other flags. This does nothing on builds with compilers * that do not support the format attribute * * Module: library/debug.c * Caller: * * This module provides debugging functions. */ #if defined(__has_attribute) #if __has_attribute(format) #if defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 #define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) \ __attribute__((__format__(gnu_printf, string_index, first_to_check))) #else /* defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 */ #define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) \ __attribute__((format(printf, string_index, first_to_check))) #endif #else /* __has_attribute(format) */ #define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) #endif /* __has_attribute(format) */ #else /* defined(__has_attribute) */ #define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) #endif /** * \def MBEDTLS_PRINTF_SIZET * * MBEDTLS_PRINTF_xxx: Due to issues with older window compilers * and MinGW we need to define the printf specifier for size_t * and long long per platform. * * Module: library/debug.c * Caller: * * This module provides debugging functions. */ #if (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) #include #define MBEDTLS_PRINTF_SIZET PRIuPTR #define MBEDTLS_PRINTF_LONGLONG "I64d" #else \ /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ #define MBEDTLS_PRINTF_SIZET "zu" #define MBEDTLS_PRINTF_LONGLONG "lld" #endif \ /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ #if !defined(MBEDTLS_PRINTF_MS_TIME) #include #if !defined(PRId64) #define MBEDTLS_PRINTF_MS_TIME MBEDTLS_PRINTF_LONGLONG #else #define MBEDTLS_PRINTF_MS_TIME PRId64 #endif #endif /* MBEDTLS_PRINTF_MS_TIME */ #ifdef __cplusplus extern "C" { #endif /** * \brief Set the threshold error level to handle globally all debug output. * Debug messages that have a level over the threshold value are * discarded. * (Default value: 0 = No debug ) * * \param threshold threshold level of messages to filter on. Messages at a * higher level will be discarded. * - Debug levels * - 0 No debug * - 1 Error * - 2 State change * - 3 Informational * - 4 Verbose */ void mbedtls_debug_set_threshold(int threshold); #ifdef __cplusplus } #endif #endif /* MBEDTLS_DEBUG_H */ webfakes/src/mbedtls/include/mbedtls/sha256.h0000644000176200001440000001533714740737024020541 0ustar liggesusers/** * \file sha256.h * * \brief This file contains SHA-224 and SHA-256 definitions and functions. * * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA256_H #define MBEDTLS_SHA256_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** SHA-256 input data was malformed. */ #define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_SHA256_ALT) // Regular implementation // /** * \brief The SHA-256 context structure. * * The structure is used both for SHA-256 and for SHA-224 * checksum calculations. The choice between these two is * made in the call to mbedtls_sha256_starts(). */ typedef struct mbedtls_sha256_context { unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ uint32_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ #if defined(MBEDTLS_SHA224_C) int MBEDTLS_PRIVATE(is224); /*!< Determines which function to use: 0: Use SHA-256, or 1: Use SHA-224. */ #endif } mbedtls_sha256_context; #else /* MBEDTLS_SHA256_ALT */ #include "sha256_alt.h" #endif /* MBEDTLS_SHA256_ALT */ /** * \brief This function initializes a SHA-256 context. * * \param ctx The SHA-256 context to initialize. This must not be \c NULL. */ void mbedtls_sha256_init(mbedtls_sha256_context *ctx); /** * \brief This function clears a SHA-256 context. * * \param ctx The SHA-256 context to clear. This may be \c NULL, in which * case this function returns immediately. If it is not \c NULL, * it must point to an initialized SHA-256 context. */ void mbedtls_sha256_free(mbedtls_sha256_context *ctx); /** * \brief This function clones the state of a SHA-256 context. * * \param dst The destination context. This must be initialized. * \param src The context to clone. This must be initialized. */ void mbedtls_sha256_clone(mbedtls_sha256_context *dst, const mbedtls_sha256_context *src); /** * \brief This function starts a SHA-224 or SHA-256 checksum * calculation. * * \param ctx The context to use. This must be initialized. * \param is224 This determines which function to use. This must be * either \c 0 for SHA-256, or \c 1 for SHA-224. * * \note is224 must be defined accordingly to the enabled * MBEDTLS_SHA224_C/MBEDTLS_SHA256_C symbols otherwise the * function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224); /** * \brief This function feeds an input buffer into an ongoing * SHA-256 checksum calculation. * * \param ctx The SHA-256 context. This must be initialized * and have a hash operation started. * \param input The buffer holding the data. This must be a readable * buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the SHA-256 operation, and writes * the result to the output buffer. * * \param ctx The SHA-256 context. This must be initialized * and have a hash operation started. * \param output The SHA-224 or SHA-256 checksum result. * This must be a writable buffer of length \c 32 bytes * for SHA-256, \c 28 bytes for SHA-224. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char *output); /** * \brief This function processes a single data block within * the ongoing SHA-256 computation. This function is for * internal use only. * * \param ctx The SHA-256 context. This must be initialized. * \param data The buffer holding one block of data. This must * be a readable buffer of length \c 64 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64]); /** * \brief This function calculates the SHA-224 or SHA-256 * checksum of a buffer. * * The function allocates the context, performs the * calculation, and frees the context. * * The SHA-256 result is calculated as * output = SHA-256(input buffer). * * \param input The buffer holding the data. This must be a readable * buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * \param output The SHA-224 or SHA-256 checksum result. * This must be a writable buffer of length \c 32 bytes * for SHA-256, \c 28 bytes for SHA-224. * \param is224 Determines which function to use. This must be * either \c 0 for SHA-256, or \c 1 for SHA-224. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha256(const unsigned char *input, size_t ilen, unsigned char *output, int is224); #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SHA224_C) /** * \brief The SHA-224 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha224_self_test(int verbose); #endif /* MBEDTLS_SHA224_C */ #if defined(MBEDTLS_SHA256_C) /** * \brief The SHA-256 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha256_self_test(int verbose); #endif /* MBEDTLS_SHA256_C */ #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_sha256.h */ webfakes/src/mbedtls/include/mbedtls/private_access.h0000644000176200001440000000066314740737024022520 0ustar liggesusers/** * \file private_access.h * * \brief Macro wrapper for struct's members. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PRIVATE_ACCESS_H #define MBEDTLS_PRIVATE_ACCESS_H #ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS #define MBEDTLS_PRIVATE(member) private_##member #else #define MBEDTLS_PRIVATE(member) member #endif #endif /* MBEDTLS_PRIVATE_ACCESS_H */ webfakes/src/mbedtls/include/mbedtls/entropy.h0000644000176200001440000002241214740737024021221 0ustar liggesusers/** * \file entropy.h * * \brief Entropy accumulator implementation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ENTROPY_H #define MBEDTLS_ENTROPY_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include "md.h" #if defined(MBEDTLS_MD_CAN_SHA512) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) #define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR #define MBEDTLS_ENTROPY_MD MBEDTLS_MD_SHA512 #define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ #else #if defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR #define MBEDTLS_ENTROPY_MD MBEDTLS_MD_SHA256 #define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ #endif #endif #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /** Critical entropy source failure. */ #define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /** No more sources can be added. */ #define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /** No sources have been added to poll. */ #define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /** No strong sources have been added to poll. */ #define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /** Read/write error in file. */ #define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) #define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ #endif #if !defined(MBEDTLS_ENTROPY_MAX_GATHER) #define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ #endif /** \} name SECTION: Module settings */ #define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ #define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES #define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ #define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ #ifdef __cplusplus extern "C" { #endif /** * \brief Entropy poll callback pointer * * \param data Callback-specific data pointer * \param output Data to fill * \param len Maximum size to provide * \param olen The actual amount of bytes put into the buffer (Can be 0) * * \return 0 if no critical failures occurred, * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise */ typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, size_t *olen); /** * \brief Entropy source state */ typedef struct mbedtls_entropy_source_state { mbedtls_entropy_f_source_ptr MBEDTLS_PRIVATE(f_source); /**< The entropy source callback */ void *MBEDTLS_PRIVATE(p_source); /**< The callback data pointer */ size_t MBEDTLS_PRIVATE(size); /**< Amount received in bytes */ size_t MBEDTLS_PRIVATE(threshold); /**< Minimum bytes required before release */ int MBEDTLS_PRIVATE(strong); /**< Is the source strong? */ } mbedtls_entropy_source_state; /** * \brief Entropy context structure */ typedef struct mbedtls_entropy_context { mbedtls_md_context_t MBEDTLS_PRIVATE(accumulator); int MBEDTLS_PRIVATE(accumulator_started); /* 0 after init. * 1 after the first update. * -1 after free. */ int MBEDTLS_PRIVATE(source_count); /* Number of entries used in source. */ mbedtls_entropy_source_state MBEDTLS_PRIVATE(source)[MBEDTLS_ENTROPY_MAX_SOURCES]; #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< mutex */ #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) int MBEDTLS_PRIVATE(initial_entropy_run); #endif } mbedtls_entropy_context; #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) /** * \brief Platform-specific entropy poll callback */ int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen); #endif /** * \brief Initialize the context * * \param ctx Entropy context to initialize */ void mbedtls_entropy_init(mbedtls_entropy_context *ctx); /** * \brief Free the data in the context * * \param ctx Entropy context to free */ void mbedtls_entropy_free(mbedtls_entropy_context *ctx); /** * \brief Adds an entropy source to poll * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param ctx Entropy context * \param f_source Entropy function * \param p_source Function data * \param threshold Minimum required from source before entropy is released * ( with mbedtls_entropy_func() ) (in bytes) * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or * MBEDTLS_ENTROPY_SOURCE_WEAK. * At least one strong source needs to be added. * Weaker sources (such as the cycle counter) can be used as * a complement. * * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES */ int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx, mbedtls_entropy_f_source_ptr f_source, void *p_source, size_t threshold, int strong); /** * \brief Trigger an extra gather poll for the accumulator * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param ctx Entropy context * * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ int mbedtls_entropy_gather(mbedtls_entropy_context *ctx); /** * \brief Retrieve entropy from the accumulator * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param data Entropy context * \param output Buffer to fill * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE * * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ int mbedtls_entropy_func(void *data, unsigned char *output, size_t len); /** * \brief Add data to the accumulator manually * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param ctx Entropy context * \param data Data to add * \param len Length of data * * \return 0 if successful */ int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx, const unsigned char *data, size_t len); #if defined(MBEDTLS_ENTROPY_NV_SEED) /** * \brief Trigger an update of the seed file in NV by using the * current entropy pool. * * \param ctx Entropy context * * \return 0 if successful */ int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx); #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if defined(MBEDTLS_FS_IO) /** * \brief Write a seed file * * \param ctx Entropy context * \param path Name of the file * * \return 0 if successful, * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path); /** * \brief Read and update a seed file. Seed is added to this * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are * read from the seed file. The rest is ignored. * * \param ctx Entropy context * \param path Name of the file * * \return 0 if successful, * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * This module self-test also calls the entropy self-test, * mbedtls_entropy_source_self_test(); * * \return 0 if successful, or 1 if a test failed */ int mbedtls_entropy_self_test(int verbose); #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) /** * \brief Checkup routine * * Verifies the integrity of the hardware entropy source * provided by the function 'mbedtls_hardware_poll()'. * * Note this is the only hardware entropy source that is known * at link time, and other entropy sources configured * dynamically at runtime by the function * mbedtls_entropy_add_source() will not be tested. * * \return 0 if successful, or 1 if a test failed */ int mbedtls_entropy_source_self_test(int verbose); #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* entropy.h */ webfakes/src/mbedtls/library/0000755000176200001440000000000015026563042015731 5ustar liggesuserswebfakes/src/mbedtls/library/ecdh.c0000644000176200001440000005221414740737024017011 0ustar liggesusers/* * Elliptic curve Diffie-Hellman * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * SEC1 https://www.secg.org/sec1-v2.pdf * RFC 4492 */ #include "common.h" #if defined(MBEDTLS_ECDH_C) #include "mbedtls/ecdh.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; #endif static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( const mbedtls_ecdh_context *ctx) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ctx->grp.id; #else return ctx->grp_id; #endif } int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid) { /* At this time, all groups support ECDH. */ (void) gid; return 1; } #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) /* * Generate public key (restartable version) * * Note: this internal function relies on its caller preserving the value of * the output parameter 'd' across continuation calls. This would not be * acceptable for a public function but is OK here as we control call sites. */ static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int restarting = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL); #endif /* If multiplication is in progress, we already generated a privkey */ if (!restarting) { MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng)); } MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G, f_rng, p_rng, rs_ctx)); cleanup: return ret; } /* * Generate public key */ int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL); } #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) /* * Compute shared secret (SEC1 3.3.1) */ static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point P; mbedtls_ecp_point_init(&P); MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q, f_rng, p_rng, rs_ctx)); if (mbedtls_ecp_is_zero(&P)) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X)); cleanup: mbedtls_ecp_point_free(&P); return ret; } /* * Compute shared secret (SEC1 3.3.1) */ int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return ecdh_compute_shared_restartable(grp, z, Q, d, f_rng, p_rng, NULL); } #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx) { mbedtls_ecp_group_init(&ctx->grp); mbedtls_mpi_init(&ctx->d); mbedtls_ecp_point_init(&ctx->Q); mbedtls_ecp_point_init(&ctx->Qp); mbedtls_mpi_init(&ctx->z); #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_init(&ctx->rs); #endif } mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ctx->MBEDTLS_PRIVATE(grp).id; #else return ctx->MBEDTLS_PRIVATE(grp_id); #endif } /* * Initialize context */ void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) ecdh_init_internal(ctx); mbedtls_ecp_point_init(&ctx->Vi); mbedtls_ecp_point_init(&ctx->Vf); mbedtls_mpi_init(&ctx->_d); #else memset(ctx, 0, sizeof(mbedtls_ecdh_context)); ctx->var = MBEDTLS_ECDH_VARIANT_NONE; #endif ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; #if defined(MBEDTLS_ECP_RESTARTABLE) ctx->restart_enabled = 0; #endif } static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx, mbedtls_ecp_group_id grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ecp_group_load(&ctx->grp, grp_id); if (ret != 0) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } return 0; } /* * Setup context */ int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_setup_internal(ctx, grp_id); #else switch (grp_id) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECP_DP_CURVE25519: ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED; ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST; ctx->grp_id = grp_id; return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id); #endif default: ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; ctx->grp_id = grp_id; ecdh_init_internal(&ctx->ctx.mbed_ecdh); return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id); } #endif } static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx) { mbedtls_ecp_group_free(&ctx->grp); mbedtls_mpi_free(&ctx->d); mbedtls_ecp_point_free(&ctx->Q); mbedtls_ecp_point_free(&ctx->Qp); mbedtls_mpi_free(&ctx->z); #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_free(&ctx->rs); #endif } #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Enable restartable operations for context */ void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx) { ctx->restart_enabled = 1; } #endif /* * Free context */ void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) mbedtls_ecp_point_free(&ctx->Vi); mbedtls_ecp_point_free(&ctx->Vf); mbedtls_mpi_free(&ctx->_d); ecdh_free_internal(ctx); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: mbedtls_everest_free(&ctx->ctx.everest_ecdh); break; #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: ecdh_free_internal(&ctx->ctx.mbed_ecdh); break; default: break; } ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; ctx->var = MBEDTLS_ECDH_VARIANT_NONE; ctx->grp_id = MBEDTLS_ECP_DP_NONE; #endif } static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx, size_t *olen, int point_format, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int restart_enabled) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t grp_len, pt_len; #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_ctx *rs_ctx = NULL; #endif if (ctx->grp.pbits == 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_RESTARTABLE) if (restart_enabled) { rs_ctx = &ctx->rs; } #else (void) restart_enabled; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng, rs_ctx)) != 0) { return ret; } #else if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng)) != 0) { return ret; } #endif /* MBEDTLS_ECP_RESTARTABLE */ if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf, blen)) != 0) { return ret; } buf += grp_len; blen -= grp_len; if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, &pt_len, buf, blen)) != 0) { return ret; } *olen = grp_len + pt_len; return 0; } /* * Setup and write the ServerKeyExchange parameters (RFC 4492) * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int restart_enabled = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restart_enabled = ctx->restart_enabled; #else (void) restart_enabled; #endif #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen, f_rng, p_rng, restart_enabled); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen, buf, blen, f_rng, p_rng); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen, ctx->point_format, buf, blen, f_rng, p_rng, restart_enabled); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx, const unsigned char **buf, const unsigned char *end) { return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf, (size_t) (end - *buf)); } /* * Read the ServerKeyExchange parameters (RFC 4492) * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx, const unsigned char **buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group_id grp_id; if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf))) != 0) { return ret; } if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) { return ret; } #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_read_params_internal(ctx, buf, end); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh, buf, end); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh, buf, end); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* If it's not our key, just import the public part as Qp */ if (side == MBEDTLS_ECDH_THEIRS) { return mbedtls_ecp_copy(&ctx->Qp, &key->Q); } /* Our key: import public (as Q) and private parts */ if (side != MBEDTLS_ECDH_OURS) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 || (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) { return ret; } return 0; } /* * Get parameters from a keypair */ int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) { /* This is the first call to get_params(). Set up the context * for use with the group. */ if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) { return ret; } } else { /* This is not the first call to get_params(). Check that the * current key's group is the same as the context's, which was set * from the first key's group. */ if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } } #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_get_params_internal(ctx, key, side); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: { mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ? MBEDTLS_EVEREST_ECDH_OURS : MBEDTLS_EVEREST_ECDH_THEIRS; return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh, key, s); } #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh, key, side); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx, size_t *olen, int point_format, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int restart_enabled) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_ctx *rs_ctx = NULL; #endif if (ctx->grp.pbits == 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_RESTARTABLE) if (restart_enabled) { rs_ctx = &ctx->rs; } #else (void) restart_enabled; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng, rs_ctx)) != 0) { return ret; } #else if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng)) != 0) { return ret; } #endif /* MBEDTLS_ECP_RESTARTABLE */ return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen, buf, blen); } /* * Setup and export the client public value */ int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int restart_enabled = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restart_enabled = ctx->restart_enabled; #endif #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen, f_rng, p_rng, restart_enabled); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen, buf, blen, f_rng, p_rng); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen, ctx->point_format, buf, blen, f_rng, p_rng, restart_enabled); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx, const unsigned char *buf, size_t blen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p, blen)) != 0) { return ret; } if ((size_t) (p - buf) != blen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return 0; } /* * Parse and import the client's public value */ int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx, const unsigned char *buf, size_t blen) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_read_public_internal(ctx, buf, blen); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh, buf, blen); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh, buf, blen); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int restart_enabled) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_ctx *rs_ctx = NULL; #endif if (ctx == NULL || ctx->grp.pbits == 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_RESTARTABLE) if (restart_enabled) { rs_ctx = &ctx->rs; } #else (void) restart_enabled; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng, rs_ctx)) != 0) { return ret; } #else if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng)) != 0) { return ret; } #endif /* MBEDTLS_ECP_RESTARTABLE */ if (mbedtls_mpi_size(&ctx->z) > blen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0); if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen); } return mbedtls_mpi_write_binary(&ctx->z, buf, *olen); } /* * Derive and export the shared secret */ int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int restart_enabled = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restart_enabled = ctx->restart_enabled; #endif #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng, restart_enabled); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen, buf, blen, f_rng, p_rng); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf, blen, f_rng, p_rng, restart_enabled); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } #endif /* MBEDTLS_ECDH_C */ webfakes/src/mbedtls/library/padlock.h0000644000176200001440000000633514740737024017533 0ustar liggesusers/** * \file padlock.h * * \brief VIA PadLock ACE for HW encryption/decryption supported by some * processors * * \warning These functions are only for internal use by other library * functions; you must not call them directly. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PADLOCK_H #define MBEDTLS_PADLOCK_H #include "mbedtls/build_info.h" #include "mbedtls/aes.h" #define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ #if defined(__has_feature) #if __has_feature(address_sanitizer) #define MBEDTLS_HAVE_ASAN #endif #endif /* * - `padlock` is implements with GNUC assembly for x86 target. * - Some versions of ASan result in errors about not enough registers. */ #if defined(MBEDTLS_PADLOCK_C) && \ defined(__GNUC__) && defined(MBEDTLS_ARCH_IS_X86) && \ defined(MBEDTLS_HAVE_ASM) && \ !defined(MBEDTLS_HAVE_ASAN) #define MBEDTLS_VIA_PADLOCK_HAVE_CODE #include #define MBEDTLS_PADLOCK_RNG 0x000C #define MBEDTLS_PADLOCK_ACE 0x00C0 #define MBEDTLS_PADLOCK_PHE 0x0C00 #define MBEDTLS_PADLOCK_PMM 0x3000 #define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15)) #ifdef __cplusplus extern "C" { #endif /** * \brief Internal PadLock detection routine * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param feature The feature to detect * * \return non-zero if CPU has support for the feature, 0 otherwise */ int mbedtls_padlock_has_support(int feature); /** * \brief Internal PadLock AES-ECB block en(de)cryption * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT * \param input 16-byte input block * \param output 16-byte output block * * \return 0 if success, 1 if operation failed */ int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); /** * \brief Internal PadLock AES-CBC buffer en(de)cryption * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT * \param length length of the input data * \param iv initialization vector (updated after use) * \param input buffer holding the input data * \param output buffer holding the output data * * \return 0 if success, 1 if operation failed */ int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); #ifdef __cplusplus } #endif #endif /* HAVE_X86 */ #endif /* padlock.h */ webfakes/src/mbedtls/library/oid.c0000644000176200001440000011311314740737024016655 0ustar liggesusers/** * \file oid.c * * \brief Object Identifier (OID) database * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_OID_C) #include "mbedtls/oid.h" #include "mbedtls/rsa.h" #include "mbedtls/error.h" #include "mbedtls/pk.h" #include #include #include "mbedtls/platform.h" /* * Macro to automatically add the size of #define'd OIDs */ #define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) /* * Macro to generate mbedtls_oid_descriptor_t */ #if !defined(MBEDTLS_X509_REMOVE_INFO) #define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s), name, description } #define NULL_OID_DESCRIPTOR { NULL, 0, NULL, NULL } #else #define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s) } #define NULL_OID_DESCRIPTOR { NULL, 0 } #endif /* * Macro to generate an internal function for oid_XXX_from_asn1() (used by * the other functions) */ #define FN_OID_TYPED_FROM_ASN1(TYPE_T, NAME, LIST) \ static const TYPE_T *oid_ ## NAME ## _from_asn1( \ const mbedtls_asn1_buf *oid) \ { \ const TYPE_T *p = (LIST); \ const mbedtls_oid_descriptor_t *cur = \ (const mbedtls_oid_descriptor_t *) p; \ if (p == NULL || oid == NULL) return NULL; \ while (cur->asn1 != NULL) { \ if (cur->asn1_len == oid->len && \ memcmp(cur->asn1, oid->p, oid->len) == 0) { \ return p; \ } \ p++; \ cur = (const mbedtls_oid_descriptor_t *) p; \ } \ return NULL; \ } #if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Macro to generate a function for retrieving a single attribute from the * descriptor of an mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1) \ { \ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ *ATTR1 = data->descriptor.ATTR1; \ return 0; \ } #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Macro to generate a function for retrieving a single attribute from an * mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1) \ { \ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ *ATTR1 = data->ATTR1; \ return 0; \ } /* * Macro to generate a function for retrieving two attributes from an * mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ ATTR2_TYPE, ATTR2) \ int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ ATTR2_TYPE * ATTR2) \ { \ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ *(ATTR1) = data->ATTR1; \ *(ATTR2) = data->ATTR2; \ return 0; \ } /* * Macro to generate a function for retrieving the OID based on a single * attribute from a mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ int FN_NAME(ATTR1_TYPE ATTR1, const char **oid, size_t *olen) \ { \ const TYPE_T *cur = (LIST); \ while (cur->descriptor.asn1 != NULL) { \ if (cur->ATTR1 == (ATTR1)) { \ *oid = cur->descriptor.asn1; \ *olen = cur->descriptor.asn1_len; \ return 0; \ } \ cur++; \ } \ return MBEDTLS_ERR_OID_NOT_FOUND; \ } /* * Macro to generate a function for retrieving the OID based on two * attributes from a mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ ATTR2_TYPE, ATTR2) \ int FN_NAME(ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid, \ size_t *olen) \ { \ const TYPE_T *cur = (LIST); \ while (cur->descriptor.asn1 != NULL) { \ if (cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2)) { \ *oid = cur->descriptor.asn1; \ *olen = cur->descriptor.asn1_len; \ return 0; \ } \ cur++; \ } \ return MBEDTLS_ERR_OID_NOT_FOUND; \ } /* * For X520 attribute types */ typedef struct { mbedtls_oid_descriptor_t descriptor; const char *short_name; } oid_x520_attr_t; static const oid_x520_attr_t oid_x520_attr_type[] = { { OID_DESCRIPTOR(MBEDTLS_OID_AT_CN, "id-at-commonName", "Common Name"), "CN", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_COUNTRY, "id-at-countryName", "Country"), "C", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_LOCALITY, "id-at-locality", "Locality"), "L", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_STATE, "id-at-state", "State"), "ST", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_ORGANIZATION, "id-at-organizationName", "Organization"), "O", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_ORG_UNIT, "id-at-organizationalUnitName", "Org Unit"), "OU", }, { OID_DESCRIPTOR(MBEDTLS_OID_PKCS9_EMAIL, "emailAddress", "E-mail address"), "emailAddress", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_SERIAL_NUMBER, "id-at-serialNumber", "Serial number"), "serialNumber", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_ADDRESS, "id-at-postalAddress", "Postal address"), "postalAddress", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_CODE, "id-at-postalCode", "Postal code"), "postalCode", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_SUR_NAME, "id-at-surName", "Surname"), "SN", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_GIVEN_NAME, "id-at-givenName", "Given name"), "GN", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_INITIALS, "id-at-initials", "Initials"), "initials", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_GENERATION_QUALIFIER, "id-at-generationQualifier", "Generation qualifier"), "generationQualifier", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_TITLE, "id-at-title", "Title"), "title", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_DN_QUALIFIER, "id-at-dnQualifier", "Distinguished Name qualifier"), "dnQualifier", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_PSEUDONYM, "id-at-pseudonym", "Pseudonym"), "pseudonym", }, { OID_DESCRIPTOR(MBEDTLS_OID_UID, "id-uid", "User Id"), "uid", }, { OID_DESCRIPTOR(MBEDTLS_OID_DOMAIN_COMPONENT, "id-domainComponent", "Domain component"), "DC", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, "id-at-uniqueIdentifier", "Unique Identifier"), "uniqueIdentifier", }, { NULL_OID_DESCRIPTOR, NULL, } }; FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) /* * For X509 extensions */ typedef struct { mbedtls_oid_descriptor_t descriptor; int ext_type; } oid_x509_ext_t; static const oid_x509_ext_t oid_x509_ext[] = { { OID_DESCRIPTOR(MBEDTLS_OID_BASIC_CONSTRAINTS, "id-ce-basicConstraints", "Basic Constraints"), MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, }, { OID_DESCRIPTOR(MBEDTLS_OID_KEY_USAGE, "id-ce-keyUsage", "Key Usage"), MBEDTLS_OID_X509_EXT_KEY_USAGE, }, { OID_DESCRIPTOR(MBEDTLS_OID_EXTENDED_KEY_USAGE, "id-ce-extKeyUsage", "Extended Key Usage"), MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, }, { OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_ALT_NAME, "id-ce-subjectAltName", "Subject Alt Name"), MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, }, { OID_DESCRIPTOR(MBEDTLS_OID_NS_CERT_TYPE, "id-netscape-certtype", "Netscape Certificate Type"), MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, }, { OID_DESCRIPTOR(MBEDTLS_OID_CERTIFICATE_POLICIES, "id-ce-certificatePolicies", "Certificate Policies"), MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, }, { OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, "id-ce-subjectKeyIdentifier", "Subject Key Identifier"), MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER, }, { OID_DESCRIPTOR(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, "id-ce-authorityKeyIdentifier", "Authority Key Identifier"), MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER, }, { NULL_OID_DESCRIPTOR, 0, }, }; FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) #if !defined(MBEDTLS_X509_REMOVE_INFO) static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = { OID_DESCRIPTOR(MBEDTLS_OID_SERVER_AUTH, "id-kp-serverAuth", "TLS Web Server Authentication"), OID_DESCRIPTOR(MBEDTLS_OID_CLIENT_AUTH, "id-kp-clientAuth", "TLS Web Client Authentication"), OID_DESCRIPTOR(MBEDTLS_OID_CODE_SIGNING, "id-kp-codeSigning", "Code Signing"), OID_DESCRIPTOR(MBEDTLS_OID_EMAIL_PROTECTION, "id-kp-emailProtection", "E-mail Protection"), OID_DESCRIPTOR(MBEDTLS_OID_TIME_STAMPING, "id-kp-timeStamping", "Time Stamping"), OID_DESCRIPTOR(MBEDTLS_OID_OCSP_SIGNING, "id-kp-OCSPSigning", "OCSP Signing"), OID_DESCRIPTOR(MBEDTLS_OID_WISUN_FAN, "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)"), NULL_OID_DESCRIPTOR, }; FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) static const mbedtls_oid_descriptor_t oid_certificate_policies[] = { OID_DESCRIPTOR(MBEDTLS_OID_ANY_POLICY, "anyPolicy", "Any Policy"), NULL_OID_DESCRIPTOR, }; FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description) #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * For SignatureAlgorithmIdentifier */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_md_type_t md_alg; mbedtls_pk_type_t pk_alg; } oid_sig_alg_t; static const oid_sig_alg_t oid_sig_alg[] = { #if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_MD_CAN_MD5) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_MD5, "md5WithRSAEncryption", "RSA with MD5"), MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_MD5 */ #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA1, "sha-1WithRSAEncryption", "RSA with SHA1"), MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA224) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA224, "sha224WithRSAEncryption", "RSA with SHA-224"), MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA224 */ #if defined(MBEDTLS_MD_CAN_SHA256) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA256, "sha256WithRSAEncryption", "RSA with SHA-256"), MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA384, "sha384WithRSAEncryption", "RSA with SHA-384"), MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA512, "sha512WithRSAEncryption", "RSA with SHA-512"), MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA512 */ #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_RSA_SHA_OBS, "sha-1WithRSAEncryption", "RSA with SHA1"), MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA1, "ecdsa-with-SHA1", "ECDSA with SHA1"), MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA224) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA224, "ecdsa-with-SHA224", "ECDSA with SHA224"), MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, }, #endif #if defined(MBEDTLS_MD_CAN_SHA256) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA256, "ecdsa-with-SHA256", "ECDSA with SHA256"), MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA384, "ecdsa-with-SHA384", "ECDSA with SHA384"), MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA512, "ecdsa-with-SHA512", "ECDSA with SHA512"), MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, }, #endif /* MBEDTLS_MD_CAN_SHA512 */ #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ #if defined(MBEDTLS_RSA_C) { OID_DESCRIPTOR(MBEDTLS_OID_RSASSA_PSS, "RSASSA-PSS", "RSASSA-PSS"), MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, }, #endif /* MBEDTLS_RSA_C */ { NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) #if !defined(MBEDTLS_X509_REMOVE_INFO) FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) #endif FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) /* * For PublicKeyInfo (PKCS1, RFC 5480) */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_pk_type_t pk_alg; } oid_pk_alg_t; static const oid_pk_alg_t oid_pk_alg[] = { { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_RSA, "rsaEncryption", "RSA"), MBEDTLS_PK_RSA, }, { OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey", "Generic EC key"), MBEDTLS_PK_ECKEY, }, { OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_ECDH, "id-ecDH", "EC key for ECDH"), MBEDTLS_PK_ECKEY_DH, }, { NULL_OID_DESCRIPTOR, MBEDTLS_PK_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * For elliptic curves that use namedCurve inside ECParams (RFC 5480) */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_ecp_group_id grp_id; } oid_ecp_grp_t; static const oid_ecp_grp_t oid_ecp_grp[] = { #if defined(MBEDTLS_ECP_HAVE_SECP192R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1", "secp192r1"), MBEDTLS_ECP_DP_SECP192R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP192R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP224R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1", "secp224r1"), MBEDTLS_ECP_DP_SECP224R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP224R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP256R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1", "secp256r1"), MBEDTLS_ECP_DP_SECP256R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP256R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP384R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1", "secp384r1"), MBEDTLS_ECP_DP_SECP384R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP384R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP521R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1", "secp521r1"), MBEDTLS_ECP_DP_SECP521R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP521R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP192K1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1", "secp192k1"), MBEDTLS_ECP_DP_SECP192K1, }, #endif /* MBEDTLS_ECP_HAVE_SECP192K1 */ #if defined(MBEDTLS_ECP_HAVE_SECP224K1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1", "secp224k1"), MBEDTLS_ECP_DP_SECP224K1, }, #endif /* MBEDTLS_ECP_HAVE_SECP224K1 */ #if defined(MBEDTLS_ECP_HAVE_SECP256K1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1", "secp256k1"), MBEDTLS_ECP_DP_SECP256K1, }, #endif /* MBEDTLS_ECP_HAVE_SECP256K1 */ #if defined(MBEDTLS_ECP_HAVE_BP256R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP256R1, "brainpoolP256r1", "brainpool256r1"), MBEDTLS_ECP_DP_BP256R1, }, #endif /* MBEDTLS_ECP_HAVE_BP256R1 */ #if defined(MBEDTLS_ECP_HAVE_BP384R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP384R1, "brainpoolP384r1", "brainpool384r1"), MBEDTLS_ECP_DP_BP384R1, }, #endif /* MBEDTLS_ECP_HAVE_BP384R1 */ #if defined(MBEDTLS_ECP_HAVE_BP512R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP512R1, "brainpoolP512r1", "brainpool512r1"), MBEDTLS_ECP_DP_BP512R1, }, #endif /* MBEDTLS_ECP_HAVE_BP512R1 */ { NULL_OID_DESCRIPTOR, MBEDTLS_ECP_DP_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) /* * For Elliptic Curve algorithms that are directly * encoded in the AlgorithmIdentifier (RFC 8410) */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_ecp_group_id grp_id; } oid_ecp_grp_algid_t; static const oid_ecp_grp_algid_t oid_ecp_grp_algid[] = { #if defined(MBEDTLS_ECP_HAVE_CURVE25519) { OID_DESCRIPTOR(MBEDTLS_OID_X25519, "X25519", "X25519"), MBEDTLS_ECP_DP_CURVE25519, }, #endif /* MBEDTLS_ECP_HAVE_CURVE25519 */ #if defined(MBEDTLS_ECP_HAVE_CURVE448) { OID_DESCRIPTOR(MBEDTLS_OID_X448, "X448", "X448"), MBEDTLS_ECP_DP_CURVE448, }, #endif /* MBEDTLS_ECP_HAVE_CURVE448 */ { NULL_OID_DESCRIPTOR, MBEDTLS_ECP_DP_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_algid_t, grp_id_algid, oid_ecp_grp_algid) FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp_algid, oid_ecp_grp_algid_t, grp_id_algid, mbedtls_ecp_group_id, grp_id) FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp_algid, oid_ecp_grp_algid_t, oid_ecp_grp_algid, mbedtls_ecp_group_id, grp_id) #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_CIPHER_C) /* * For PKCS#5 PBES2 encryption algorithm */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_cipher_type_t cipher_alg; } oid_cipher_alg_t; static const oid_cipher_alg_t oid_cipher_alg[] = { { OID_DESCRIPTOR(MBEDTLS_OID_DES_CBC, "desCBC", "DES-CBC"), MBEDTLS_CIPHER_DES_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC, "des-ede3-cbc", "DES-EDE3-CBC"), MBEDTLS_CIPHER_DES_EDE3_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_AES_128_CBC, "aes128-cbc", "AES128-CBC"), MBEDTLS_CIPHER_AES_128_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_AES_192_CBC, "aes192-cbc", "AES192-CBC"), MBEDTLS_CIPHER_AES_192_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_AES_256_CBC, "aes256-cbc", "AES256-CBC"), MBEDTLS_CIPHER_AES_256_CBC, }, { NULL_OID_DESCRIPTOR, MBEDTLS_CIPHER_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) #endif /* MBEDTLS_CIPHER_C */ /* * For digestAlgorithm */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_md_type_t md_alg; } oid_md_alg_t; static const oid_md_alg_t oid_md_alg[] = { #if defined(MBEDTLS_MD_CAN_MD5) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_MD5, "id-md5", "MD5"), MBEDTLS_MD_MD5, }, #endif #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA1, "id-sha1", "SHA-1"), MBEDTLS_MD_SHA1, }, #endif #if defined(MBEDTLS_MD_CAN_SHA224) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA224, "id-sha224", "SHA-224"), MBEDTLS_MD_SHA224, }, #endif #if defined(MBEDTLS_MD_CAN_SHA256) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA256, "id-sha256", "SHA-256"), MBEDTLS_MD_SHA256, }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA384, "id-sha384", "SHA-384"), MBEDTLS_MD_SHA384, }, #endif #if defined(MBEDTLS_MD_CAN_SHA512) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA512, "id-sha512", "SHA-512"), MBEDTLS_MD_SHA512, }, #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160"), MBEDTLS_MD_RIPEMD160, }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_224, "id-sha3-224", "SHA-3-224"), MBEDTLS_MD_SHA3_224, }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_256, "id-sha3-256", "SHA-3-256"), MBEDTLS_MD_SHA3_256, }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_384, "id-sha3-384", "SHA-3-384"), MBEDTLS_MD_SHA3_384, }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_512, "id-sha3-512", "SHA-3-512"), MBEDTLS_MD_SHA3_512, }, #endif { NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) /* * For HMAC digestAlgorithm */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_md_type_t md_hmac; } oid_md_hmac_t; static const oid_md_hmac_t oid_md_hmac[] = { #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA1, "hmacSHA1", "HMAC-SHA-1"), MBEDTLS_MD_SHA1, }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA224) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA224, "hmacSHA224", "HMAC-SHA-224"), MBEDTLS_MD_SHA224, }, #endif /* MBEDTLS_MD_CAN_SHA224 */ #if defined(MBEDTLS_MD_CAN_SHA256) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA256, "hmacSHA256", "HMAC-SHA-256"), MBEDTLS_MD_SHA256, }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA384, "hmacSHA384", "HMAC-SHA-384"), MBEDTLS_MD_SHA384, }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA512, "hmacSHA512", "HMAC-SHA-512"), MBEDTLS_MD_SHA512, }, #endif /* MBEDTLS_MD_CAN_SHA512 */ #if defined(MBEDTLS_MD_CAN_SHA3_224) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_224, "hmacSHA3-224", "HMAC-SHA3-224"), MBEDTLS_MD_SHA3_224, }, #endif /* MBEDTLS_MD_CAN_SHA3_224 */ #if defined(MBEDTLS_MD_CAN_SHA3_256) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_256, "hmacSHA3-256", "HMAC-SHA3-256"), MBEDTLS_MD_SHA3_256, }, #endif /* MBEDTLS_MD_CAN_SHA3_256 */ #if defined(MBEDTLS_MD_CAN_SHA3_384) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_384, "hmacSHA3-384", "HMAC-SHA3-384"), MBEDTLS_MD_SHA3_384, }, #endif /* MBEDTLS_MD_CAN_SHA3_384 */ #if defined(MBEDTLS_MD_CAN_SHA3_512) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_512, "hmacSHA3-512", "HMAC-SHA3-512"), MBEDTLS_MD_SHA3_512, }, #endif /* MBEDTLS_MD_CAN_SHA3_512 */ #if defined(MBEDTLS_MD_CAN_RIPEMD160) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_RIPEMD160, "hmacRIPEMD160", "HMAC-RIPEMD160"), MBEDTLS_MD_RIPEMD160, }, #endif /* MBEDTLS_MD_CAN_RIPEMD160 */ { NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) #if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_C) /* * For PKCS#12 PBEs */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_md_type_t md_alg; mbedtls_cipher_type_t cipher_alg; } oid_pkcs12_pbe_alg_t; static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = { { OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC, "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES"), MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC, "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES"), MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, }, { NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) #endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_C */ /* Return the x.y.z.... style numeric string for the given OID */ int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; char *p = buf; size_t n = size; unsigned int value = 0; if (size > INT_MAX) { /* Avoid overflow computing return value */ return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } if (oid->len <= 0) { /* OID must not be empty */ return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } for (size_t i = 0; i < oid->len; i++) { /* Prevent overflow in value. */ if (value > (UINT_MAX >> 7)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } if ((value == 0) && ((oid->p[i]) == 0x80)) { /* Overlong encoding is not allowed */ return MBEDTLS_ERR_ASN1_INVALID_DATA; } value <<= 7; value |= oid->p[i] & 0x7F; if (!(oid->p[i] & 0x80)) { /* Last byte */ if (n == size) { int component1; unsigned int component2; /* First subidentifier contains first two OID components */ if (value >= 80) { component1 = '2'; component2 = value - 80; } else if (value >= 40) { component1 = '1'; component2 = value - 40; } else { component1 = '0'; component2 = value; } ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2); } else { ret = mbedtls_snprintf(p, n, ".%u", value); } if (ret < 2 || (size_t) ret >= n) { return MBEDTLS_ERR_OID_BUF_TOO_SMALL; } n -= (size_t) ret; p += ret; value = 0; } } if (value != 0) { /* Unterminated subidentifier */ return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } return (int) (size - n); } static int oid_parse_number(unsigned int *num, const char **p, const char *bound) { int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; *num = 0; while (*p < bound && **p >= '0' && **p <= '9') { ret = 0; if (*num > (UINT_MAX / 10)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } *num *= 10; *num += **p - '0'; (*p)++; } return ret; } static size_t oid_subidentifier_num_bytes(unsigned int value) { size_t num_bytes = 0; do { value >>= 7; num_bytes++; } while (value != 0); return num_bytes; } static int oid_subidentifier_encode_into(unsigned char **p, unsigned char *bound, unsigned int value) { size_t num_bytes = oid_subidentifier_num_bytes(value); if ((size_t) (bound - *p) < num_bytes) { return MBEDTLS_ERR_OID_BUF_TOO_SMALL; } (*p)[num_bytes - 1] = (unsigned char) (value & 0x7f); value >>= 7; for (size_t i = 2; i <= num_bytes; i++) { (*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f); value >>= 7; } *p += num_bytes; return 0; } /* Return the OID for the given x.y.z.... style numeric string */ int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size) { int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; const char *str_ptr = oid_str; const char *str_bound = oid_str + size; unsigned int val = 0; unsigned int component1, component2; size_t encoded_len; unsigned char *resized_mem; /* Count the number of dots to get a worst-case allocation size. */ size_t num_dots = 0; for (size_t i = 0; i < size; i++) { if (oid_str[i] == '.') { num_dots++; } } /* Allocate maximum possible required memory: * There are (num_dots + 1) integer components, but the first 2 share the * same subidentifier, so we only need num_dots subidentifiers maximum. */ if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } /* Each byte can store 7 bits, calculate number of bytes for a * subidentifier: * * bytes = ceil(subidentifer_size * 8 / 7) */ size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7) + 1; size_t max_possible_bytes = num_dots * bytes_per_subidentifier; oid->p = mbedtls_calloc(max_possible_bytes, 1); if (oid->p == NULL) { return MBEDTLS_ERR_ASN1_ALLOC_FAILED; } unsigned char *out_ptr = oid->p; unsigned char *out_bound = oid->p + max_possible_bytes; ret = oid_parse_number(&component1, &str_ptr, str_bound); if (ret != 0) { goto error; } if (component1 > 2) { /* First component can't be > 2 */ ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } if (str_ptr >= str_bound || *str_ptr != '.') { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } str_ptr++; ret = oid_parse_number(&component2, &str_ptr, str_bound); if (ret != 0) { goto error; } if ((component1 < 2) && (component2 > 39)) { /* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */ ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } if (str_ptr < str_bound) { if (*str_ptr == '.') { str_ptr++; } else { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } } if (component2 > (UINT_MAX - (component1 * 40))) { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } ret = oid_subidentifier_encode_into(&out_ptr, out_bound, (component1 * 40) + component2); if (ret != 0) { goto error; } while (str_ptr < str_bound) { ret = oid_parse_number(&val, &str_ptr, str_bound); if (ret != 0) { goto error; } if (str_ptr < str_bound) { if (*str_ptr == '.') { str_ptr++; } else { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } } ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val); if (ret != 0) { goto error; } } encoded_len = (size_t) (out_ptr - oid->p); resized_mem = mbedtls_calloc(encoded_len, 1); if (resized_mem == NULL) { ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED; goto error; } memcpy(resized_mem, oid->p, encoded_len); mbedtls_free(oid->p); oid->p = resized_mem; oid->len = encoded_len; oid->tag = MBEDTLS_ASN1_OID; return 0; error: mbedtls_free(oid->p); oid->p = NULL; oid->len = 0; return ret; } #endif /* MBEDTLS_OID_C */ webfakes/src/mbedtls/library/ssl_debug_helpers.h0000644000176200001440000000602214740737024021600 0ustar liggesusers/** * \file ssl_debug_helpers.h * * \brief Automatically generated helper functions for debugging */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_DEBUG_HELPERS_H #define MBEDTLS_SSL_DEBUG_HELPERS_H #include "common.h" #if defined(MBEDTLS_DEBUG_C) #include "mbedtls/ssl.h" #include "ssl_misc.h" const char *mbedtls_ssl_states_str(mbedtls_ssl_states in); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in); const char *mbedtls_ssl_early_data_state_str(mbedtls_ssl_early_data_state in); #endif const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in); const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in); const char *mbedtls_ssl_key_export_type_str(mbedtls_ssl_key_export_type in); const char *mbedtls_ssl_sig_alg_to_str(uint16_t in); const char *mbedtls_ssl_named_group_to_str(uint16_t in); const char *mbedtls_ssl_get_extension_name(unsigned int extension_type); void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl, int level, const char *file, int line, int hs_msg_type, uint32_t extensions_mask, const char *extra); void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl, int level, const char *file, int line, int hs_msg_type, unsigned int extension_type, const char *extra_msg0, const char *extra_msg1); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl, int level, const char *file, int line, unsigned int flags); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ #define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extensions_mask) \ mbedtls_ssl_print_extensions(ssl, level, __FILE__, __LINE__, \ hs_msg_type, extensions_mask, NULL) #define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra) \ mbedtls_ssl_print_extension(ssl, level, __FILE__, __LINE__, \ hs_msg_type, extension_type, \ extra, NULL) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags) \ mbedtls_ssl_print_ticket_flags(ssl, level, __FILE__, __LINE__, flags) #endif #else #define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extension_mask) #define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags) #endif #endif /* MBEDTLS_DEBUG_C */ #endif /* MBEDTLS_SSL_DEBUG_HELPERS_H */ webfakes/src/mbedtls/library/CMakeLists.txt0000644000176200001440000002707714740737024020513 0ustar liggesusersoption(USE_STATIC_MBEDTLS_LIBRARY "Build Mbed TLS static library." ON) option(USE_SHARED_MBEDTLS_LIBRARY "Build Mbed TLS shared library." OFF) option(LINK_WITH_PTHREAD "Explicitly link Mbed TLS library to pthread." OFF) option(LINK_WITH_TRUSTED_STORAGE "Explicitly link Mbed TLS library to trusted_storage." OFF) # Set the project root directory if it's not already defined, as may happen if # the library folder is included directly by a parent project, without # including the top level CMakeLists.txt. if(NOT DEFINED MBEDTLS_DIR) set(MBEDTLS_DIR ${CMAKE_SOURCE_DIR}) endif() set(src_crypto aes.c aesni.c aesce.c aria.c asn1parse.c asn1write.c base64.c bignum.c bignum_core.c bignum_mod.c bignum_mod_raw.c block_cipher.c camellia.c ccm.c chacha20.c chachapoly.c cipher.c cipher_wrap.c constant_time.c cmac.c ctr_drbg.c des.c dhm.c ecdh.c ecdsa.c ecjpake.c ecp.c ecp_curves.c ecp_curves_new.c entropy.c entropy_poll.c error.c gcm.c hkdf.c hmac_drbg.c lmots.c lms.c md.c md5.c memory_buffer_alloc.c nist_kw.c oid.c padlock.c pem.c pk.c pk_ecc.c pk_wrap.c pkcs12.c pkcs5.c pkparse.c pkwrite.c platform.c platform_util.c poly1305.c psa_crypto.c psa_crypto_aead.c psa_crypto_cipher.c psa_crypto_client.c psa_crypto_driver_wrappers_no_static.c psa_crypto_ecp.c psa_crypto_ffdh.c psa_crypto_hash.c psa_crypto_mac.c psa_crypto_pake.c psa_crypto_rsa.c psa_crypto_se.c psa_crypto_slot_management.c psa_crypto_storage.c psa_its_file.c psa_util.c ripemd160.c rsa.c rsa_alt_helpers.c sha1.c sha256.c sha512.c sha3.c threading.c timing.c version.c version_features.c ) set(src_x509 pkcs7.c x509.c x509_create.c x509_crl.c x509_crt.c x509_csr.c x509write.c x509write_crt.c x509write_csr.c ) set(src_tls debug.c mps_reader.c mps_trace.c net_sockets.c ssl_cache.c ssl_ciphersuites.c ssl_client.c ssl_cookie.c ssl_debug_helpers_generated.c ssl_msg.c ssl_ticket.c ssl_tls.c ssl_tls12_client.c ssl_tls12_server.c ssl_tls13_keys.c ssl_tls13_server.c ssl_tls13_client.c ssl_tls13_generic.c ) if(GEN_FILES) find_package(Perl REQUIRED) file(GLOB error_headers ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls/*.h) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/error.c COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_errors.pl ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files ${CMAKE_CURRENT_BINARY_DIR}/error.c DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_errors.pl ${error_headers} ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/error.fmt ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version_features.c COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_features.pl ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files ${CMAKE_CURRENT_BINARY_DIR}/version_features.c DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_features.pl ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls/mbedtls_config.h ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/version_features.fmt ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ssl_debug_helpers_generated.c COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_ssl_debug_helpers.py --mbedtls-root ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_ssl_debug_helpers.py ${error_headers} ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/psa_crypto_driver_wrappers.h ${CMAKE_CURRENT_BINARY_DIR}/psa_crypto_driver_wrappers_no_static.c COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_driver_wrappers.py ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_driver_wrappers.py ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja ) else() link_to_source(error.c) link_to_source(version_features.c) link_to_source(ssl_debug_helpers_generated.c) link_to_source(psa_crypto_driver_wrappers_no_static.c) endif() if(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations") endif(CMAKE_COMPILER_IS_GNUCC) if(CMAKE_COMPILER_IS_CLANG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code") endif(CMAKE_COMPILER_IS_CLANG) if(CMAKE_COMPILER_IS_MSVC) option(MSVC_STATIC_RUNTIME "Build the libraries with /MT compiler flag" OFF) if(MSVC_STATIC_RUNTIME) foreach(flag_var CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_CHECK) string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") endforeach(flag_var) endif() endif() if(WIN32) set(libs ${libs} ws2_32 bcrypt) endif(WIN32) if(CMAKE_C_COMPILER_ID MATCHES "AppleClang") set(CMAKE_C_ARCHIVE_CREATE " Scr ") set(CMAKE_C_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") endif() if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang") set(CMAKE_CXX_ARCHIVE_CREATE " Scr ") set(CMAKE_CXX_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") endif() if(HAIKU) set(libs ${libs} network) endif(HAIKU) if(LINK_WITH_PTHREAD) set(libs ${libs} ${CMAKE_THREAD_LIBS_INIT}) endif() if(LINK_WITH_TRUSTED_STORAGE) set(libs ${libs} trusted_storage) endif() if (NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) message(FATAL_ERROR "Need to choose static or shared mbedtls build!") endif(NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) set(mbedtls_target "${MBEDTLS_TARGET_PREFIX}mbedtls") set(mbedx509_target "${MBEDTLS_TARGET_PREFIX}mbedx509") set(mbedcrypto_target "${MBEDTLS_TARGET_PREFIX}mbedcrypto") set(mbedtls_target ${mbedtls_target} PARENT_SCOPE) set(mbedx509_target ${mbedx509_target} PARENT_SCOPE) set(mbedcrypto_target ${mbedcrypto_target} PARENT_SCOPE) if (USE_STATIC_MBEDTLS_LIBRARY) set(mbedtls_static_target ${mbedtls_target}) set(mbedx509_static_target ${mbedx509_target}) set(mbedcrypto_static_target ${mbedcrypto_target}) endif() set(target_libraries ${mbedcrypto_target} ${mbedx509_target} ${mbedtls_target}) if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) string(APPEND mbedtls_static_target "_static") string(APPEND mbedx509_static_target "_static") string(APPEND mbedcrypto_static_target "_static") list(APPEND target_libraries ${mbedcrypto_static_target} ${mbedx509_static_target} ${mbedtls_static_target}) endif() set(p256m_target "${MBEDTLS_TARGET_PREFIX}p256m") set(everest_target "${MBEDTLS_TARGET_PREFIX}everest") if(USE_STATIC_MBEDTLS_LIBRARY) add_library(${mbedcrypto_static_target} STATIC ${src_crypto}) set_target_properties(${mbedcrypto_static_target} PROPERTIES OUTPUT_NAME mbedcrypto) target_link_libraries(${mbedcrypto_static_target} PUBLIC ${libs}) if(TARGET ${everest_target}) target_link_libraries(${mbedcrypto_static_target} PUBLIC ${everest_target}) endif() if(TARGET ${p256m_target}) target_link_libraries(${mbedcrypto_static_target} PUBLIC ${p256m_target}) endif() add_library(${mbedx509_static_target} STATIC ${src_x509}) set_target_properties(${mbedx509_static_target} PROPERTIES OUTPUT_NAME mbedx509) target_link_libraries(${mbedx509_static_target} PUBLIC ${libs} ${mbedcrypto_static_target}) add_library(${mbedtls_static_target} STATIC ${src_tls}) set_target_properties(${mbedtls_static_target} PROPERTIES OUTPUT_NAME mbedtls) target_link_libraries(${mbedtls_static_target} PUBLIC ${libs} ${mbedx509_static_target}) endif(USE_STATIC_MBEDTLS_LIBRARY) if(USE_SHARED_MBEDTLS_LIBRARY) set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR}) add_library(${mbedcrypto_target} SHARED ${src_crypto}) set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.6.2 SOVERSION 16) target_link_libraries(${mbedcrypto_target} PUBLIC ${libs}) if(TARGET ${everest_target}) target_link_libraries(${mbedcrypto_target} PUBLIC ${everest_target}) endif() if(TARGET ${p256m_target}) target_link_libraries(${mbedcrypto_target} PUBLIC ${p256m_target}) endif() add_library(${mbedx509_target} SHARED ${src_x509}) set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.6.2 SOVERSION 7) target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target}) add_library(${mbedtls_target} SHARED ${src_tls}) set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.6.2 SOVERSION 21) target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target}) endif(USE_SHARED_MBEDTLS_LIBRARY) foreach(target IN LISTS target_libraries) add_library(MbedTLS::${target} ALIAS ${target}) # add_subdirectory support # Include public header files from /include and other directories # declared by /3rdparty/**/CMakeLists.txt. Include private header files # from /library and others declared by /3rdparty/**/CMakeLists.txt. # /library needs to be listed explicitly when building .c files outside # of /library (which currently means: under /3rdparty). target_include_directories(${target} PUBLIC $ $ PRIVATE ${MBEDTLS_DIR}/library/ # Needed to include psa_crypto_driver_wrappers.h ${CMAKE_CURRENT_BINARY_DIR}) # Pass-through MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE if(MBEDTLS_CONFIG_FILE) target_compile_definitions(${target} PUBLIC MBEDTLS_CONFIG_FILE="${MBEDTLS_CONFIG_FILE}") endif() if(MBEDTLS_USER_CONFIG_FILE) target_compile_definitions(${target} PUBLIC MBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}") endif() install( TARGETS ${target} EXPORT MbedTLSTargets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) endforeach(target) set(lib_target "${MBEDTLS_TARGET_PREFIX}lib") add_custom_target(${lib_target} DEPENDS ${mbedcrypto_target} ${mbedx509_target} ${mbedtls_target}) if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) add_dependencies(${lib_target} ${mbedcrypto_static_target} ${mbedx509_static_target} ${mbedtls_static_target}) endif() webfakes/src/mbedtls/library/ssl_msg.c0000644000176200001440000067402014740737024017562 0ustar liggesusers/* * Generic SSL/TLS messaging layer functions * (record layer + retransmission state machine) * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * http://www.ietf.org/rfc/rfc2246.txt * http://www.ietf.org/rfc/rfc4346.txt */ #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "ssl_misc.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/version.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa_util_internal.h" #include "psa/crypto.h" #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #include "mbedtls/oid.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(PSA_WANT_ALG_SHA_384) #define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384) #elif defined(PSA_WANT_ALG_SHA_256) #define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256) #else /* See check_config.h */ #define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1) #endif MBEDTLS_STATIC_TESTABLE int mbedtls_ct_hmac(mbedtls_svc_key_id_t key, psa_algorithm_t mac_alg, const unsigned char *add_data, size_t add_data_len, const unsigned char *data, size_t data_len_secret, size_t min_data_len, size_t max_data_len, unsigned char *output) { /* * This function breaks the HMAC abstraction and uses psa_hash_clone() * extension in order to get constant-flow behaviour. * * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means * concatenation, and okey/ikey are the XOR of the key with some fixed bit * patterns (see RFC 2104, sec. 2). * * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by * hashing up to minlen, then cloning the context, and for each byte up * to maxlen finishing up the hash computation, keeping only the * correct result. * * Then we only need to compute HASH(okey + inner_hash) and we're done. */ psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg); const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); unsigned char key_buf[MAX_HASH_BLOCK_LENGTH]; const size_t hash_size = PSA_HASH_LENGTH(hash_alg); psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; size_t hash_length; unsigned char aux_out[PSA_HASH_MAX_SIZE]; psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT; size_t offset; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t mac_key_length; size_t i; #define PSA_CHK(func_call) \ do { \ status = (func_call); \ if (status != PSA_SUCCESS) \ goto cleanup; \ } while (0) /* Export MAC key * We assume key length is always exactly the output size * which is never more than the block size, thus we use block_size * as the key buffer size. */ PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length)); /* Calculate ikey */ for (i = 0; i < mac_key_length; i++) { key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36); } for (; i < block_size; ++i) { key_buf[i] = 0x36; } PSA_CHK(psa_hash_setup(&operation, hash_alg)); /* Now compute inner_hash = HASH(ikey + msg) */ PSA_CHK(psa_hash_update(&operation, key_buf, block_size)); PSA_CHK(psa_hash_update(&operation, add_data, add_data_len)); PSA_CHK(psa_hash_update(&operation, data, min_data_len)); /* Fill the hash buffer in advance with something that is * not a valid hash (barring an attack on the hash and * deliberately-crafted input), in case the caller doesn't * check the return status properly. */ memset(output, '!', hash_size); /* For each possible length, compute the hash up to that point */ for (offset = min_data_len; offset <= max_data_len; offset++) { PSA_CHK(psa_hash_clone(&operation, &aux_operation)); PSA_CHK(psa_hash_finish(&aux_operation, aux_out, PSA_HASH_MAX_SIZE, &hash_length)); /* Keep only the correct inner_hash in the output buffer */ mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret), output, aux_out, NULL, hash_size); if (offset < max_data_len) { PSA_CHK(psa_hash_update(&operation, data + offset, 1)); } } /* Abort current operation to prepare for final operation */ PSA_CHK(psa_hash_abort(&operation)); /* Calculate okey */ for (i = 0; i < mac_key_length; i++) { key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C); } for (; i < block_size; ++i) { key_buf[i] = 0x5C; } /* Now compute HASH(okey + inner_hash) */ PSA_CHK(psa_hash_setup(&operation, hash_alg)); PSA_CHK(psa_hash_update(&operation, key_buf, block_size)); PSA_CHK(psa_hash_update(&operation, output, hash_size)); PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length)); #undef PSA_CHK cleanup: mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH); mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE); psa_hash_abort(&operation); psa_hash_abort(&aux_operation); return PSA_TO_MBEDTLS_ERR(status); } #undef MAX_HASH_BLOCK_LENGTH #else MBEDTLS_STATIC_TESTABLE int mbedtls_ct_hmac(mbedtls_md_context_t *ctx, const unsigned char *add_data, size_t add_data_len, const unsigned char *data, size_t data_len_secret, size_t min_data_len, size_t max_data_len, unsigned char *output) { /* * This function breaks the HMAC abstraction and uses the md_clone() * extension to the MD API in order to get constant-flow behaviour. * * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means * concatenation, and okey/ikey are the XOR of the key with some fixed bit * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. * * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to * minlen, then cloning the context, and for each byte up to maxlen * finishing up the hash computation, keeping only the correct result. * * Then we only need to compute HASH(okey + inner_hash) and we're done. */ const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info); /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5, * all of which have the same block size except SHA-384. */ const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; const unsigned char * const ikey = ctx->hmac_ctx; const unsigned char * const okey = ikey + block_size; const size_t hash_size = mbedtls_md_get_size(ctx->md_info); unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; mbedtls_md_context_t aux; size_t offset; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_init(&aux); #define MD_CHK(func_call) \ do { \ ret = (func_call); \ if (ret != 0) \ goto cleanup; \ } while (0) MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0)); /* After hmac_start() of hmac_reset(), ikey has already been hashed, * so we can start directly with the message */ MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len)); MD_CHK(mbedtls_md_update(ctx, data, min_data_len)); /* Fill the hash buffer in advance with something that is * not a valid hash (barring an attack on the hash and * deliberately-crafted input), in case the caller doesn't * check the return status properly. */ memset(output, '!', hash_size); /* For each possible length, compute the hash up to that point */ for (offset = min_data_len; offset <= max_data_len; offset++) { MD_CHK(mbedtls_md_clone(&aux, ctx)); MD_CHK(mbedtls_md_finish(&aux, aux_out)); /* Keep only the correct inner_hash in the output buffer */ mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret), output, aux_out, NULL, hash_size); if (offset < max_data_len) { MD_CHK(mbedtls_md_update(ctx, data + offset, 1)); } } /* The context needs to finish() before it starts() again */ MD_CHK(mbedtls_md_finish(ctx, aux_out)); /* Now compute HASH(okey + inner_hash) */ MD_CHK(mbedtls_md_starts(ctx)); MD_CHK(mbedtls_md_update(ctx, okey, block_size)); MD_CHK(mbedtls_md_update(ctx, output, hash_size)); MD_CHK(mbedtls_md_finish(ctx, output)); /* Done, get ready for next time */ MD_CHK(mbedtls_md_hmac_reset(ctx)); #undef MD_CHK cleanup: mbedtls_md_free(&aux); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl); /* * Start a timer. * Passing millisecs = 0 cancels a running timer. */ void mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs) { if (ssl->f_set_timer == NULL) { return; } MBEDTLS_SSL_DEBUG_MSG(3, ("set_timer to %d ms", (int) millisecs)); ssl->f_set_timer(ssl->p_timer, millisecs / 4, millisecs); } /* * Return -1 is timer is expired, 0 if it isn't. */ int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl) { if (ssl->f_get_timer == NULL) { return 0; } if (ssl->f_get_timer(ssl->p_timer) == 2) { MBEDTLS_SSL_DEBUG_MSG(3, ("timer expired")); return -1; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, unsigned char *buf, size_t len, mbedtls_record *rec); int mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl, unsigned char *buf, size_t buflen) { int ret = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("=> mbedtls_ssl_check_record")); MBEDTLS_SSL_DEBUG_BUF(3, "record buffer", buf, buflen); /* We don't support record checking in TLS because * there doesn't seem to be a usecase for it. */ if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM) { ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; goto exit; } #if defined(MBEDTLS_SSL_PROTO_DTLS) else { mbedtls_record rec; ret = ssl_parse_record_header(ssl, buf, buflen, &rec); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(3, "ssl_parse_record_header", ret); goto exit; } if (ssl->transform_in != NULL) { ret = mbedtls_ssl_decrypt_buf(ssl, ssl->transform_in, &rec); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(3, "mbedtls_ssl_decrypt_buf", ret); goto exit; } } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ exit: /* On success, we have decrypted the buffer in-place, so make * sure we don't leak any plaintext data. */ mbedtls_platform_zeroize(buf, buflen); /* For the purpose of this API, treat messages with unexpected CID * as well as such from future epochs as unexpected. */ if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID || ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) { ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } MBEDTLS_SSL_DEBUG_MSG(1, ("<= mbedtls_ssl_check_record")); return ret; } #define SSL_DONT_FORCE_FLUSH 0 #define SSL_FORCE_FLUSH 1 #if defined(MBEDTLS_SSL_PROTO_DTLS) /* Forward declarations for functions related to message buffering. */ static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl, uint8_t slot); static void ssl_free_buffered_record(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_message(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_record(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_message(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_future_record(mbedtls_ssl_context *ssl, mbedtls_record const *rec); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl); static size_t ssl_get_maximum_datagram_size(mbedtls_ssl_context const *ssl) { size_t mtu = mbedtls_ssl_get_current_mtu(ssl); #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len; #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #endif if (mtu != 0 && mtu < out_buf_len) { return mtu; } return out_buf_len; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_remaining_space_in_datagram(mbedtls_ssl_context const *ssl) { size_t const bytes_written = ssl->out_left; size_t const mtu = ssl_get_maximum_datagram_size(ssl); /* Double-check that the write-index hasn't gone * past what we can transmit in a single datagram. */ if (bytes_written > mtu) { /* Should never happen... */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return (int) (mtu - bytes_written); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_remaining_payload_in_datagram(mbedtls_ssl_context const *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t remaining, expansion; size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl); if (max_len > mfl) { max_len = mfl; } /* By the standard (RFC 6066 Sect. 4), the MFL extension * only limits the maximum record payload size, so in theory * we would be allowed to pack multiple records of payload size * MFL into a single datagram. However, this would mean that there's * no way to explicitly communicate MTU restrictions to the peer. * * The following reduction of max_len makes sure that we never * write datagrams larger than MFL + Record Expansion Overhead. */ if (max_len <= ssl->out_left) { return 0; } max_len -= ssl->out_left; #endif ret = ssl_get_remaining_space_in_datagram(ssl); if (ret < 0) { return ret; } remaining = (size_t) ret; ret = mbedtls_ssl_get_record_expansion(ssl); if (ret < 0) { return ret; } expansion = (size_t) ret; if (remaining <= expansion) { return 0; } remaining -= expansion; if (remaining >= max_len) { remaining = max_len; } return (int) remaining; } /* * Double the retransmit timeout value, within the allowed range, * returning -1 if the maximum value has already been reached. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_double_retransmit_timeout(mbedtls_ssl_context *ssl) { uint32_t new_timeout; if (ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max) { return -1; } /* Implement the final paragraph of RFC 6347 section 4.1.1.1 * in the following way: after the initial transmission and a first * retransmission, back off to a temporary estimated MTU of 508 bytes. * This value is guaranteed to be deliverable (if not guaranteed to be * delivered) of any compliant IPv4 (and IPv6) network, and should work * on most non-IP stacks too. */ if (ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min) { ssl->handshake->mtu = 508; MBEDTLS_SSL_DEBUG_MSG(2, ("mtu autoreduction to %d bytes", ssl->handshake->mtu)); } new_timeout = 2 * ssl->handshake->retransmit_timeout; /* Avoid arithmetic overflow and range overflow */ if (new_timeout < ssl->handshake->retransmit_timeout || new_timeout > ssl->conf->hs_timeout_max) { new_timeout = ssl->conf->hs_timeout_max; } ssl->handshake->retransmit_timeout = new_timeout; MBEDTLS_SSL_DEBUG_MSG(3, ("update timeout value to %lu millisecs", (unsigned long) ssl->handshake->retransmit_timeout)); return 0; } static void ssl_reset_retransmit_timeout(mbedtls_ssl_context *ssl) { ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; MBEDTLS_SSL_DEBUG_MSG(3, ("update timeout value to %lu millisecs", (unsigned long) ssl->handshake->retransmit_timeout)); } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Encryption/decryption functions */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || defined(MBEDTLS_SSL_PROTO_TLS1_3) static size_t ssl_compute_padding_length(size_t len, size_t granularity) { return (granularity - (len + 1) % granularity) % granularity; } /* This functions transforms a (D)TLS plaintext fragment and a record content * type into an instance of the (D)TLSInnerPlaintext structure. This is used * in DTLS 1.2 + CID and within TLS 1.3 to allow flexible padding and to protect * a record's content type. * * struct { * opaque content[DTLSPlaintext.length]; * ContentType real_type; * uint8 zeros[length_of_padding]; * } (D)TLSInnerPlaintext; * * Input: * - `content`: The beginning of the buffer holding the * plaintext to be wrapped. * - `*content_size`: The length of the plaintext in Bytes. * - `max_len`: The number of Bytes available starting from * `content`. This must be `>= *content_size`. * - `rec_type`: The desired record content type. * * Output: * - `content`: The beginning of the resulting (D)TLSInnerPlaintext structure. * - `*content_size`: The length of the resulting (D)TLSInnerPlaintext structure. * * Returns: * - `0` on success. * - A negative error code if `max_len` didn't offer enough space * for the expansion. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_build_inner_plaintext(unsigned char *content, size_t *content_size, size_t remaining, uint8_t rec_type, size_t pad) { size_t len = *content_size; /* Write real content type */ if (remaining == 0) { return -1; } content[len] = rec_type; len++; remaining--; if (remaining < pad) { return -1; } memset(content + len, 0, pad); len += pad; remaining -= pad; *content_size = len; return 0; } /* This function parses a (D)TLSInnerPlaintext structure. * See ssl_build_inner_plaintext() for details. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_inner_plaintext(unsigned char const *content, size_t *content_size, uint8_t *rec_type) { size_t remaining = *content_size; /* Determine length of padding by skipping zeroes from the back. */ do { if (remaining == 0) { return -1; } remaining--; } while (content[remaining] == 0); *content_size = remaining; *rec_type = content[remaining]; return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || MBEDTLS_SSL_PROTO_TLS1_3 */ /* The size of the `add_data` structure depends on various * factors, namely * * 1) CID functionality disabled * * additional_data = * 8: seq_num + * 1: type + * 2: version + * 2: length of inner plaintext + * * size = 13 bytes * * 2) CID functionality based on RFC 9146 enabled * * size = 8 + 1 + 1 + 1 + 2 + 2 + 6 + 2 + CID-length * = 23 + CID-length * * 3) CID functionality based on legacy CID version according to draft-ietf-tls-dtls-connection-id-05 * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 * * size = 13 + 1 + CID-length * * More information about the CID usage: * * Per Section 5.3 of draft-ietf-tls-dtls-connection-id-05 the * size of the additional data structure is calculated as: * * additional_data = * 8: seq_num + * 1: tls12_cid + * 2: DTLSCipherText.version + * n: cid + * 1: cid_length + * 2: length_of_DTLSInnerPlaintext * * Per RFC 9146 the size of the add_data structure is calculated as: * * additional_data = * 8: seq_num_placeholder + * 1: tls12_cid + * 1: cid_length + * 1: tls12_cid + * 2: DTLSCiphertext.version + * 2: epoch + * 6: sequence_number + * n: cid + * 2: length_of_DTLSInnerPlaintext * */ static void ssl_extract_add_data_from_record(unsigned char *add_data, size_t *add_data_len, mbedtls_record *rec, mbedtls_ssl_protocol_version tls_version, size_t taglen) { /* Several types of ciphers have been defined for use with TLS and DTLS, * and the MAC calculations for those ciphers differ slightly. Further * variants were added when the CID functionality was added with RFC 9146. * This implementations also considers the use of a legacy version of the * CID specification published in draft-ietf-tls-dtls-connection-id-05, * which is used in deployments. * * We will distinguish between the non-CID and the CID cases below. * * --- Non-CID cases --- * * Quoting RFC 5246 (TLS 1.2): * * additional_data = seq_num + TLSCompressed.type + * TLSCompressed.version + TLSCompressed.length; * * For TLS 1.3, the record sequence number is dropped from the AAD * and encoded within the nonce of the AEAD operation instead. * Moreover, the additional data involves the length of the TLS * ciphertext, not the TLS plaintext as in earlier versions. * Quoting RFC 8446 (TLS 1.3): * * additional_data = TLSCiphertext.opaque_type || * TLSCiphertext.legacy_record_version || * TLSCiphertext.length * * We pass the tag length to this function in order to compute the * ciphertext length from the inner plaintext length rec->data_len via * * TLSCiphertext.length = TLSInnerPlaintext.length + taglen. * * --- CID cases --- * * RFC 9146 uses a common pattern when constructing the data * passed into a MAC / AEAD cipher. * * Data concatenation for MACs used with block ciphers with * Encrypt-then-MAC Processing (with CID): * * data = seq_num_placeholder + * tls12_cid + * cid_length + * tls12_cid + * DTLSCiphertext.version + * epoch + * sequence_number + * cid + * DTLSCiphertext.length + * IV + * ENC(content + padding + padding_length) * * Data concatenation for MACs used with block ciphers (with CID): * * data = seq_num_placeholder + * tls12_cid + * cid_length + * tls12_cid + * DTLSCiphertext.version + * epoch + * sequence_number + * cid + * length_of_DTLSInnerPlaintext + * DTLSInnerPlaintext.content + * DTLSInnerPlaintext.real_type + * DTLSInnerPlaintext.zeros * * AEAD ciphers use the following additional data calculation (with CIDs): * * additional_data = seq_num_placeholder + * tls12_cid + * cid_length + * tls12_cid + * DTLSCiphertext.version + * epoch + * sequence_number + * cid + * length_of_DTLSInnerPlaintext * * Section 5.3 of draft-ietf-tls-dtls-connection-id-05 (for legacy CID use) * defines the additional data calculation as follows: * * additional_data = seq_num + * tls12_cid + * DTLSCipherText.version + * cid + * cid_length + * length_of_DTLSInnerPlaintext */ unsigned char *cur = add_data; size_t ad_len_field = rec->data_len; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 const unsigned char seq_num_placeholder[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* In TLS 1.3, the AAD contains the length of the TLSCiphertext, * which differs from the length of the TLSInnerPlaintext * by the length of the authentication tag. */ ad_len_field += taglen; } else #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ { ((void) tls_version); ((void) taglen); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 if (rec->cid_len != 0) { // seq_num_placeholder memcpy(cur, seq_num_placeholder, sizeof(seq_num_placeholder)); cur += sizeof(seq_num_placeholder); // tls12_cid type *cur = rec->type; cur++; // cid_length *cur = rec->cid_len; cur++; } else #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ { // epoch + sequence number memcpy(cur, rec->ctr, sizeof(rec->ctr)); cur += sizeof(rec->ctr); } } // type *cur = rec->type; cur++; // version memcpy(cur, rec->ver, sizeof(rec->ver)); cur += sizeof(rec->ver); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 1 if (rec->cid_len != 0) { // CID memcpy(cur, rec->cid, rec->cid_len); cur += rec->cid_len; // cid_length *cur = rec->cid_len; cur++; // length of inner plaintext MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); cur += 2; } else #elif defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 if (rec->cid_len != 0) { // epoch + sequence number memcpy(cur, rec->ctr, sizeof(rec->ctr)); cur += sizeof(rec->ctr); // CID memcpy(cur, rec->cid, rec->cid_len); cur += rec->cid_len; // length of inner plaintext MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); cur += 2; } else #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ { MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); cur += 2; } *add_data_len = (size_t) (cur - add_data); } #if defined(MBEDTLS_SSL_HAVE_AEAD) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_transform_aead_dynamic_iv_is_explicit( mbedtls_ssl_transform const *transform) { return transform->ivlen != transform->fixed_ivlen; } /* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV ) * * Concretely, this occurs in two variants: * * a) Fixed and dynamic IV lengths add up to total IV length, giving * IV = fixed_iv || dynamic_iv * * This variant is used in TLS 1.2 when used with GCM or CCM. * * b) Fixed IV lengths matches total IV length, giving * IV = fixed_iv XOR ( 0 || dynamic_iv ) * * This variant occurs in TLS 1.3 and for TLS 1.2 when using ChaChaPoly. * * See also the documentation of mbedtls_ssl_transform. * * This function has the precondition that * * dst_iv_len >= max( fixed_iv_len, dynamic_iv_len ) * * which has to be ensured by the caller. If this precondition * violated, the behavior of this function is undefined. */ static void ssl_build_record_nonce(unsigned char *dst_iv, size_t dst_iv_len, unsigned char const *fixed_iv, size_t fixed_iv_len, unsigned char const *dynamic_iv, size_t dynamic_iv_len) { /* Start with Fixed IV || 0 */ memset(dst_iv, 0, dst_iv_len); memcpy(dst_iv, fixed_iv, fixed_iv_len); dst_iv += dst_iv_len - dynamic_iv_len; mbedtls_xor(dst_iv, dst_iv, dynamic_iv, dynamic_iv_len); } #endif /* MBEDTLS_SSL_HAVE_AEAD */ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_ssl_mode_t ssl_mode; int auth_done = 0; unsigned char *data; /* For an explanation of the additional data length see * the description of ssl_extract_add_data_from_record(). */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) unsigned char add_data[23 + MBEDTLS_SSL_CID_OUT_LEN_MAX]; #else unsigned char add_data[13]; #endif size_t add_data_len; size_t post_avail; /* The SSL context is only used for debugging purposes! */ #if !defined(MBEDTLS_DEBUG_C) ssl = NULL; /* make sure we don't use it except for debug */ ((void) ssl); #endif /* The PRNG is used for dynamic IV generation that's used * for CBC transformations in TLS 1.2. */ #if !(defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2)) ((void) f_rng); ((void) p_rng); #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> encrypt buf")); if (transform == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("no transform provided to encrypt_buf")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (rec == NULL || rec->buf == NULL || rec->buf_len < rec->data_offset || rec->buf_len - rec->data_offset < rec->data_len #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || rec->cid_len != 0 #endif ) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad record structure provided to encrypt_buf")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl_mode = mbedtls_ssl_get_mode_from_transform(transform); data = rec->buf + rec->data_offset; post_avail = rec->buf_len - (rec->data_len + rec->data_offset); MBEDTLS_SSL_DEBUG_BUF(4, "before encrypt: output payload", data, rec->data_len); if (rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("Record content %" MBEDTLS_PRINTF_SIZET " too large, maximum %" MBEDTLS_PRINTF_SIZET, rec->data_len, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* The following two code paths implement the (D)TLSInnerPlaintext * structure present in TLS 1.3 and DTLS 1.2 + CID. * * See ssl_build_inner_plaintext() for more information. * * Note that this changes `rec->data_len`, and hence * `post_avail` needs to be recalculated afterwards. * * Note also that the two code paths cannot occur simultaneously * since they apply to different versions of the protocol. There * is hence no risk of double-addition of the inner plaintext. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { size_t padding = ssl_compute_padding_length(rec->data_len, MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY); if (ssl_build_inner_plaintext(data, &rec->data_len, post_avail, rec->type, padding) != 0) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* * Add CID information */ rec->cid_len = transform->out_cid_len; memcpy(rec->cid, transform->out_cid, transform->out_cid_len); MBEDTLS_SSL_DEBUG_BUF(3, "CID", rec->cid, rec->cid_len); if (rec->cid_len != 0) { size_t padding = ssl_compute_padding_length(rec->data_len, MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY); /* * Wrap plaintext into DTLSInnerPlaintext structure. * See ssl_build_inner_plaintext() for more information. * * Note that this changes `rec->data_len`, and hence * `post_avail` needs to be recalculated afterwards. */ if (ssl_build_inner_plaintext(data, &rec->data_len, post_avail, rec->type, padding) != 0) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } rec->type = MBEDTLS_SSL_MSG_CID; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ post_avail = rec->buf_len - (rec->data_len + rec->data_offset); /* * Add MAC before if needed */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (ssl_mode == MBEDTLS_SSL_MODE_STREAM || ssl_mode == MBEDTLS_SSL_MODE_CBC) { if (post_avail < transform->maclen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) unsigned char mac[MBEDTLS_SSL_MAC_ADD]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t sign_mac_length = 0; #endif /* MBEDTLS_USE_PSA_CRYPTO */ ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_sign_setup(&operation, transform->psa_mac_enc, transform->psa_mac_alg); if (status != PSA_SUCCESS) { goto hmac_failed_etm_disabled; } status = psa_mac_update(&operation, add_data, add_data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_disabled; } status = psa_mac_update(&operation, data, rec->data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_disabled; } status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD, &sign_mac_length); if (status != PSA_SUCCESS) { goto hmac_failed_etm_disabled; } #else ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data, add_data_len); if (ret != 0) { goto hmac_failed_etm_disabled; } ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, data, rec->data_len); if (ret != 0) { goto hmac_failed_etm_disabled; } ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac); if (ret != 0) { goto hmac_failed_etm_disabled; } ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc); if (ret != 0) { goto hmac_failed_etm_disabled; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ memcpy(data + rec->data_len, mac, transform->maclen); #endif MBEDTLS_SSL_DEBUG_BUF(4, "computed mac", data + rec->data_len, transform->maclen); rec->data_len += transform->maclen; post_avail -= transform->maclen; auth_done++; hmac_failed_etm_disabled: mbedtls_platform_zeroize(mac, transform->maclen); #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = PSA_TO_MBEDTLS_ERR(status); status = psa_mac_abort(&operation); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_hmac_xxx", ret); return ret; } } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ /* * Encrypt */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " "including %d bytes of padding", rec->data_len, 0)); /* The only supported stream cipher is "NULL", * so there's nothing to do here.*/ } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ #if defined(MBEDTLS_SSL_HAVE_AEAD) if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { unsigned char iv[12]; unsigned char *dynamic_iv; size_t dynamic_iv_len; int dynamic_iv_is_explicit = ssl_transform_aead_dynamic_iv_is_explicit(transform); #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif /* MBEDTLS_USE_PSA_CRYPTO */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Check that there's space for the authentication tag. */ if (post_avail < transform->taglen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } /* * Build nonce for AEAD encryption. * * Note: In the case of CCM and GCM in TLS 1.2, the dynamic * part of the IV is prepended to the ciphertext and * can be chosen freely - in particular, it need not * agree with the record sequence number. * However, since ChaChaPoly as well as all AEAD modes * in TLS 1.3 use the record sequence number as the * dynamic part of the nonce, we uniformly use the * record sequence number here in all cases. */ dynamic_iv = rec->ctr; dynamic_iv_len = sizeof(rec->ctr); ssl_build_record_nonce(iv, sizeof(iv), transform->iv_enc, transform->fixed_ivlen, dynamic_iv, dynamic_iv_len); /* * Build additional data for AEAD encryption. * This depends on the TLS version. */ ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); MBEDTLS_SSL_DEBUG_BUF(4, "IV used (internal)", iv, transform->ivlen); MBEDTLS_SSL_DEBUG_BUF(4, "IV used (transmitted)", dynamic_iv, dynamic_iv_is_explicit ? dynamic_iv_len : 0); MBEDTLS_SSL_DEBUG_BUF(4, "additional data used for AEAD", add_data, add_data_len); MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " "including 0 bytes of padding", rec->data_len)); /* * Encrypt and authenticate */ #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_aead_encrypt(transform->psa_key_enc, transform->psa_alg, iv, transform->ivlen, add_data, add_data_len, data, rec->data_len, data, rec->buf_len - (data - rec->buf), &rec->data_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_encrypt_buf", ret); return ret; } #else if ((ret = mbedtls_cipher_auth_encrypt_ext(&transform->cipher_ctx_enc, iv, transform->ivlen, add_data, add_data_len, data, rec->data_len, /* src */ data, rec->buf_len - (size_t) (data - rec->buf), /* dst */ &rec->data_len, transform->taglen)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_encrypt_ext", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_BUF(4, "after encrypt: tag", data + rec->data_len - transform->taglen, transform->taglen); /* Account for authentication tag. */ post_avail -= transform->taglen; /* * Prefix record content with dynamic IV in case it is explicit. */ if (dynamic_iv_is_explicit != 0) { if (rec->data_offset < dynamic_iv_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } memcpy(data - dynamic_iv_len, dynamic_iv, dynamic_iv_len); rec->data_offset -= dynamic_iv_len; rec->data_len += dynamic_iv_len; } auth_done++; } else #endif /* MBEDTLS_SSL_HAVE_AEAD */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) if (ssl_mode == MBEDTLS_SSL_MODE_CBC || ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t padlen, i; size_t olen; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t part_len; psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Currently we're always using minimal padding * (up to 255 bytes would be allowed). */ padlen = transform->ivlen - (rec->data_len + 1) % transform->ivlen; if (padlen == transform->ivlen) { padlen = 0; } /* Check there's enough space in the buffer for the padding. */ if (post_avail < padlen + 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } for (i = 0; i <= padlen; i++) { data[rec->data_len + i] = (unsigned char) padlen; } rec->data_len += padlen + 1; post_avail -= padlen + 1; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * Prepend per-record IV for block cipher in TLS v1.2 as per * Method 1 (6.2.3.2. in RFC4346 and RFC5246) */ if (f_rng == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("No PRNG provided to encrypt_record routine")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (rec->data_offset < transform->ivlen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } /* * Generate IV */ ret = f_rng(p_rng, transform->iv_enc, transform->ivlen); if (ret != 0) { return ret; } memcpy(data - transform->ivlen, transform->iv_enc, transform->ivlen); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " "including %" MBEDTLS_PRINTF_SIZET " bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding", rec->data_len, transform->ivlen, padlen + 1)); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_cipher_encrypt_setup(&cipher_op, transform->psa_key_enc, transform->psa_alg); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_encrypt_setup", ret); return ret; } status = psa_cipher_set_iv(&cipher_op, transform->iv_enc, transform->ivlen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret); return ret; } status = psa_cipher_update(&cipher_op, data, rec->data_len, data, rec->data_len, &olen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret); return ret; } status = psa_cipher_finish(&cipher_op, data + olen, rec->data_len - olen, &part_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret); return ret; } olen += part_len; #else if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_enc, transform->iv_enc, transform->ivlen, data, rec->data_len, data, &olen)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (rec->data_len != olen) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } data -= transform->ivlen; rec->data_offset -= transform->ivlen; rec->data_len += transform->ivlen; #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if (auth_done == 0) { unsigned char mac[MBEDTLS_SSL_MAC_ADD]; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; size_t sign_mac_length = 0; #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* MAC(MAC_write_key, add_data, IV, ENC(content + padding + padding_length)) */ if (post_avail < transform->maclen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); MBEDTLS_SSL_DEBUG_MSG(3, ("using encrypt then mac")); MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data, add_data_len); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_sign_setup(&operation, transform->psa_mac_enc, transform->psa_mac_alg); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_update(&operation, add_data, add_data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_update(&operation, data, rec->data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD, &sign_mac_length); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } #else ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data, add_data_len); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, data, rec->data_len); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc); if (ret != 0) { goto hmac_failed_etm_enabled; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ memcpy(data + rec->data_len, mac, transform->maclen); rec->data_len += transform->maclen; post_avail -= transform->maclen; auth_done++; hmac_failed_etm_enabled: mbedtls_platform_zeroize(mac, transform->maclen); #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = PSA_TO_MBEDTLS_ERR(status); status = psa_mac_abort(&operation); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "HMAC calculation failed", ret); return ret; } } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Make extra sure authentication was performed, exactly once */ if (auth_done != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= encrypt buf")); return 0; } int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) || defined(MBEDTLS_SSL_HAVE_AEAD) size_t olen; #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC || MBEDTLS_SSL_HAVE_AEAD */ mbedtls_ssl_mode_t ssl_mode; int ret; int auth_done = 0; #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) size_t padlen = 0; mbedtls_ct_condition_t correct = MBEDTLS_CT_TRUE; #endif unsigned char *data; /* For an explanation of the additional data length see * the description of ssl_extract_add_data_from_record(). */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) unsigned char add_data[23 + MBEDTLS_SSL_CID_IN_LEN_MAX]; #else unsigned char add_data[13]; #endif size_t add_data_len; #if !defined(MBEDTLS_DEBUG_C) ssl = NULL; /* make sure we don't use it except for debug */ ((void) ssl); #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> decrypt buf")); if (rec == NULL || rec->buf == NULL || rec->buf_len < rec->data_offset || rec->buf_len - rec->data_offset < rec->data_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad record structure provided to decrypt_buf")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } data = rec->buf + rec->data_offset; ssl_mode = mbedtls_ssl_get_mode_from_transform(transform); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* * Match record's CID with incoming CID. */ if (rec->cid_len != transform->in_cid_len || memcmp(rec->cid, transform->in_cid, rec->cid_len) != 0) { return MBEDTLS_ERR_SSL_UNEXPECTED_CID; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { if (rec->data_len < transform->maclen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Record too short for MAC:" " %" MBEDTLS_PRINTF_SIZET " < %" MBEDTLS_PRINTF_SIZET, rec->data_len, transform->maclen)); return MBEDTLS_ERR_SSL_INVALID_MAC; } /* The only supported stream cipher is "NULL", * so there's no encryption to do here.*/ } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ #if defined(MBEDTLS_SSL_HAVE_AEAD) if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { unsigned char iv[12]; unsigned char *dynamic_iv; size_t dynamic_iv_len; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Extract dynamic part of nonce for AEAD decryption. * * Note: In the case of CCM and GCM in TLS 1.2, the dynamic * part of the IV is prepended to the ciphertext and * can be chosen freely - in particular, it need not * agree with the record sequence number. */ dynamic_iv_len = sizeof(rec->ctr); if (ssl_transform_aead_dynamic_iv_is_explicit(transform) == 1) { if (rec->data_len < dynamic_iv_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET " ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ", rec->data_len, dynamic_iv_len)); return MBEDTLS_ERR_SSL_INVALID_MAC; } dynamic_iv = data; data += dynamic_iv_len; rec->data_offset += dynamic_iv_len; rec->data_len -= dynamic_iv_len; } else { dynamic_iv = rec->ctr; } /* Check that there's space for the authentication tag. */ if (rec->data_len < transform->taglen) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET ") < taglen (%" MBEDTLS_PRINTF_SIZET ") ", rec->data_len, transform->taglen)); return MBEDTLS_ERR_SSL_INVALID_MAC; } rec->data_len -= transform->taglen; /* * Prepare nonce from dynamic and static parts. */ ssl_build_record_nonce(iv, sizeof(iv), transform->iv_dec, transform->fixed_ivlen, dynamic_iv, dynamic_iv_len); /* * Build additional data for AEAD encryption. * This depends on the TLS version. */ ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); MBEDTLS_SSL_DEBUG_BUF(4, "additional data used for AEAD", add_data, add_data_len); /* Because of the check above, we know that there are * explicit_iv_len Bytes preceding data, and taglen * bytes following data + data_len. This justifies * the debug message and the invocation of * mbedtls_cipher_auth_decrypt_ext() below. */ MBEDTLS_SSL_DEBUG_BUF(4, "IV used", iv, transform->ivlen); MBEDTLS_SSL_DEBUG_BUF(4, "TAG used", data + rec->data_len, transform->taglen); /* * Decrypt and authenticate */ #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_aead_decrypt(transform->psa_key_dec, transform->psa_alg, iv, transform->ivlen, add_data, add_data_len, data, rec->data_len + transform->taglen, data, rec->buf_len - (data - rec->buf), &olen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_aead_decrypt", ret); return ret; } #else if ((ret = mbedtls_cipher_auth_decrypt_ext (&transform->cipher_ctx_dec, iv, transform->ivlen, add_data, add_data_len, data, rec->data_len + transform->taglen, /* src */ data, rec->buf_len - (size_t) (data - rec->buf), &olen, /* dst */ transform->taglen)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_decrypt_ext", ret); if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) { return MBEDTLS_ERR_SSL_INVALID_MAC; } return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ auth_done++; /* Double-check that AEAD decryption doesn't change content length. */ if (olen != rec->data_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } else #endif /* MBEDTLS_SSL_HAVE_AEAD */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) if (ssl_mode == MBEDTLS_SSL_MODE_CBC || ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { size_t minlen = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t part_len; psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Check immediate ciphertext sanity */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* The ciphertext is prefixed with the CBC IV. */ minlen += transform->ivlen; #endif /* Size considerations: * * - The CBC cipher text must not be empty and hence * at least of size transform->ivlen. * * Together with the potential IV-prefix, this explains * the first of the two checks below. * * - The record must contain a MAC, either in plain or * encrypted, depending on whether Encrypt-then-MAC * is used or not. * - If it is, the message contains the IV-prefix, * the CBC ciphertext, and the MAC. * - If it is not, the padded plaintext, and hence * the CBC ciphertext, has at least length maclen + 1 * because there is at least the padding length byte. * * As the CBC ciphertext is not empty, both cases give the * lower bound minlen + maclen + 1 on the record size, which * we test for in the second check below. */ if (rec->data_len < minlen + transform->ivlen || rec->data_len < minlen + transform->maclen + 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET ") < max( ivlen(%" MBEDTLS_PRINTF_SIZET "), maclen (%" MBEDTLS_PRINTF_SIZET ") " "+ 1 ) ( + expl IV )", rec->data_len, transform->ivlen, transform->maclen)); return MBEDTLS_ERR_SSL_INVALID_MAC; } /* * Authenticate before decrypt if enabled */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; #else unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_MSG(3, ("using encrypt then mac")); /* Update data_len in tandem with add_data. * * The subtraction is safe because of the previous check * data_len >= minlen + maclen + 1. * * Afterwards, we know that data + data_len is followed by at * least maclen Bytes, which justifies the call to * mbedtls_ct_memcmp() below. * * Further, we still know that data_len > minlen */ rec->data_len -= transform->maclen; ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); /* Calculate expected MAC. */ MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data, add_data_len); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_verify_setup(&operation, transform->psa_mac_dec, transform->psa_mac_alg); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_update(&operation, add_data, add_data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_update(&operation, data, rec->data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } /* Compare expected MAC with MAC at the end of the record. */ status = psa_mac_verify_finish(&operation, data + rec->data_len, transform->maclen); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } #else ret = mbedtls_md_hmac_update(&transform->md_ctx_dec, add_data, add_data_len); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_update(&transform->md_ctx_dec, data, rec->data_len); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_finish(&transform->md_ctx_dec, mac_expect); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_reset(&transform->md_ctx_dec); if (ret != 0) { goto hmac_failed_etm_enabled; } MBEDTLS_SSL_DEBUG_BUF(4, "message mac", data + rec->data_len, transform->maclen); MBEDTLS_SSL_DEBUG_BUF(4, "expected mac", mac_expect, transform->maclen); /* Compare expected MAC with MAC at the end of the record. */ if (mbedtls_ct_memcmp(data + rec->data_len, mac_expect, transform->maclen) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("message mac does not match")); ret = MBEDTLS_ERR_SSL_INVALID_MAC; goto hmac_failed_etm_enabled; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ auth_done++; hmac_failed_etm_enabled: #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = PSA_TO_MBEDTLS_ERR(status); status = psa_mac_abort(&operation); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #else mbedtls_platform_zeroize(mac_expect, transform->maclen); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { if (ret != MBEDTLS_ERR_SSL_INVALID_MAC) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_hmac_xxx", ret); } return ret; } } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ /* * Check length sanity */ /* We know from above that data_len > minlen >= 0, * so the following check in particular implies that * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */ if (rec->data_len % transform->ivlen != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET ") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0", rec->data_len, transform->ivlen)); return MBEDTLS_ERR_SSL_INVALID_MAC; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * Initialize for prepended IV for block cipher in TLS v1.2 */ /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */ memcpy(transform->iv_dec, data, transform->ivlen); data += transform->ivlen; rec->data_offset += transform->ivlen; rec->data_len -= transform->ivlen; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_cipher_decrypt_setup(&cipher_op, transform->psa_key_dec, transform->psa_alg); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_decrypt_setup", ret); return ret; } status = psa_cipher_set_iv(&cipher_op, transform->iv_dec, transform->ivlen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret); return ret; } status = psa_cipher_update(&cipher_op, data, rec->data_len, data, rec->data_len, &olen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret); return ret; } status = psa_cipher_finish(&cipher_op, data + olen, rec->data_len - olen, &part_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret); return ret; } olen += part_len; #else if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_dec, transform->iv_dec, transform->ivlen, data, rec->data_len, data, &olen)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Double-check that length hasn't changed during decryption. */ if (rec->data_len != olen) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Safe since data_len >= minlen + maclen + 1, so after having * subtracted at most minlen and maclen up to this point, * data_len > 0 (because of data_len % ivlen == 0, it's actually * >= ivlen ). */ padlen = data[rec->data_len - 1]; if (auth_done == 1) { const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge( rec->data_len, padlen + 1); correct = mbedtls_ct_bool_and(ge, correct); padlen = mbedtls_ct_size_if_else_0(ge, padlen); } else { #if defined(MBEDTLS_SSL_DEBUG_ALL) if (rec->data_len < transform->maclen + padlen + 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET ") < maclen (%" MBEDTLS_PRINTF_SIZET ") + padlen (%" MBEDTLS_PRINTF_SIZET ")", rec->data_len, transform->maclen, padlen + 1)); } #endif const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge( rec->data_len, transform->maclen + padlen + 1); correct = mbedtls_ct_bool_and(ge, correct); padlen = mbedtls_ct_size_if_else_0(ge, padlen); } padlen++; /* Regardless of the validity of the padding, * we have data_len >= padlen here. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* The padding check involves a series of up to 256 * consecutive memory reads at the end of the record * plaintext buffer. In order to hide the length and * validity of the padding, always perform exactly * `min(256,plaintext_len)` reads (but take into account * only the last `padlen` bytes for the padding check). */ size_t pad_count = 0; volatile unsigned char * const check = data; /* Index of first padding byte; it has been ensured above * that the subtraction is safe. */ size_t const padding_idx = rec->data_len - padlen; size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256; size_t const start_idx = rec->data_len - num_checks; size_t idx; for (idx = start_idx; idx < rec->data_len; idx++) { /* pad_count += (idx >= padding_idx) && * (check[idx] == padlen - 1); */ const mbedtls_ct_condition_t a = mbedtls_ct_uint_ge(idx, padding_idx); size_t increment = mbedtls_ct_size_if_else_0(a, 1); const mbedtls_ct_condition_t b = mbedtls_ct_uint_eq(check[idx], padlen - 1); increment = mbedtls_ct_size_if_else_0(b, increment); pad_count += increment; } correct = mbedtls_ct_bool_and(mbedtls_ct_uint_eq(pad_count, padlen), correct); #if defined(MBEDTLS_SSL_DEBUG_ALL) if (padlen > 0 && correct == MBEDTLS_CT_FALSE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad padding byte detected")); } #endif padlen = mbedtls_ct_size_if_else_0(correct, padlen); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* If the padding was found to be invalid, padlen == 0 * and the subtraction is safe. If the padding was found valid, * padlen hasn't been changed and the previous assertion * data_len >= padlen still holds. */ rec->data_len -= padlen; } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF(4, "raw buffer after decryption", data, rec->data_len); #endif /* * Authenticate if not done yet. * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (auth_done == 0) { unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 }; unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 }; /* For CBC+MAC, If the initial value of padlen was such that * data_len < maclen + padlen + 1, then padlen * got reset to 1, and the initial check * data_len >= minlen + maclen + 1 * guarantees that at this point we still * have at least data_len >= maclen. * * If the initial value of padlen was such that * data_len >= maclen + padlen + 1, then we have * subtracted either padlen + 1 (if the padding was correct) * or 0 (if the padding was incorrect) since then, * hence data_len >= maclen in any case. * * For stream ciphers, we checked above that * data_len >= maclen. */ rec->data_len -= transform->maclen; ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * The next two sizes are the minimum and maximum values of * data_len over all padlen values. * * They're independent of padlen, since we previously did * data_len -= padlen. * * Note that max_len + maclen is never more than the buffer * length, as we previously did in_msglen -= maclen too. */ const size_t max_len = rec->data_len + padlen; const size_t min_len = (max_len > 256) ? max_len - 256 : 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = mbedtls_ct_hmac(transform->psa_mac_dec, transform->psa_mac_alg, add_data, add_data_len, data, rec->data_len, min_len, max_len, mac_expect); #else ret = mbedtls_ct_hmac(&transform->md_ctx_dec, add_data, add_data_len, data, rec->data_len, min_len, max_len, mac_expect); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ct_hmac", ret); goto hmac_failed_etm_disabled; } mbedtls_ct_memcpy_offset(mac_peer, data, rec->data_len, min_len, max_len, transform->maclen); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF(4, "expected mac", mac_expect, transform->maclen); MBEDTLS_SSL_DEBUG_BUF(4, "message mac", mac_peer, transform->maclen); #endif if (mbedtls_ct_memcmp(mac_peer, mac_expect, transform->maclen) != 0) { #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_MSG(1, ("message mac does not match")); #endif correct = MBEDTLS_CT_FALSE; } auth_done++; hmac_failed_etm_disabled: mbedtls_platform_zeroize(mac_peer, transform->maclen); mbedtls_platform_zeroize(mac_expect, transform->maclen); if (ret != 0) { return ret; } } /* * Finally check the correct flag */ if (correct == MBEDTLS_CT_FALSE) { return MBEDTLS_ERR_SSL_INVALID_MAC; } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ /* Make extra sure authentication was performed, exactly once */ if (auth_done != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* Remove inner padding and infer true content type. */ ret = ssl_parse_inner_plaintext(data, &rec->data_len, &rec->type); if (ret != 0) { return MBEDTLS_ERR_SSL_INVALID_RECORD; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (rec->cid_len != 0) { ret = ssl_parse_inner_plaintext(data, &rec->data_len, &rec->type); if (ret != 0) { return MBEDTLS_ERR_SSL_INVALID_RECORD; } } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= decrypt buf")); return 0; } #undef MAC_NONE #undef MAC_PLAINTEXT #undef MAC_CIPHERTEXT /* * Fill the input message buffer by appending data to it. * The amount of data already fetched is in ssl->in_left. * * If we return 0, is it guaranteed that (at least) nb_want bytes are * available (from this read and/or a previous one). Otherwise, an error code * is returned (possibly EOF or WANT_READ). * * With stream transport (TLS) on success ssl->in_left == nb_want, but * with datagram transport (DTLS) on success ssl->in_left >= nb_want, * since we always read a whole datagram at once. * * For DTLS, it is up to the caller to set ssl->next_record_offset when * they're done reading a record. */ int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t in_buf_len = ssl->in_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> fetch input")); if (ssl->f_recv == NULL && ssl->f_recv_timeout == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("Bad usage of mbedtls_ssl_set_bio() ")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (nb_want > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) { MBEDTLS_SSL_DEBUG_MSG(1, ("requesting more data than fits")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { uint32_t timeout; /* * The point is, we need to always read a full datagram at once, so we * sometimes read more then requested, and handle the additional data. * It could be the rest of the current record (while fetching the * header) and/or some other records in the same datagram. */ /* * Move to the next record in the already read datagram if applicable */ if (ssl->next_record_offset != 0) { if (ssl->in_left < ssl->next_record_offset) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->in_left -= ssl->next_record_offset; if (ssl->in_left != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("next record in same datagram, offset: %" MBEDTLS_PRINTF_SIZET, ssl->next_record_offset)); memmove(ssl->in_hdr, ssl->in_hdr + ssl->next_record_offset, ssl->in_left); } ssl->next_record_offset = 0; } MBEDTLS_SSL_DEBUG_MSG(2, ("in_left: %" MBEDTLS_PRINTF_SIZET ", nb_want: %" MBEDTLS_PRINTF_SIZET, ssl->in_left, nb_want)); /* * Done if we already have enough data. */ if (nb_want <= ssl->in_left) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= fetch input")); return 0; } /* * A record can't be split across datagrams. If we need to read but * are not at the beginning of a new record, the caller did something * wrong. */ if (ssl->in_left != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * Don't even try to read if time's out already. * This avoids by-passing the timer when repeatedly receiving messages * that will end up being dropped. */ if (mbedtls_ssl_check_timer(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("timer has expired")); ret = MBEDTLS_ERR_SSL_TIMEOUT; } else { len = in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf); if (mbedtls_ssl_is_handshake_over(ssl) == 0) { timeout = ssl->handshake->retransmit_timeout; } else { timeout = ssl->conf->read_timeout; } MBEDTLS_SSL_DEBUG_MSG(3, ("f_recv_timeout: %lu ms", (unsigned long) timeout)); if (ssl->f_recv_timeout != NULL) { ret = ssl->f_recv_timeout(ssl->p_bio, ssl->in_hdr, len, timeout); } else { ret = ssl->f_recv(ssl->p_bio, ssl->in_hdr, len); } MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_recv(_timeout)", ret); if (ret == 0) { return MBEDTLS_ERR_SSL_CONN_EOF; } } if (ret == MBEDTLS_ERR_SSL_TIMEOUT) { MBEDTLS_SSL_DEBUG_MSG(2, ("timeout")); mbedtls_ssl_set_timer(ssl, 0); if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { if (ssl_double_retransmit_timeout(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("handshake timeout")); return MBEDTLS_ERR_SSL_TIMEOUT; } if ((ret = mbedtls_ssl_resend(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend", ret); return ret; } return MBEDTLS_ERR_SSL_WANT_READ; } #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) else if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { if ((ret = mbedtls_ssl_resend_hello_request(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend_hello_request", ret); return ret; } return MBEDTLS_ERR_SSL_WANT_READ; } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ } if (ret < 0) { return ret; } ssl->in_left = ret; } else #endif { MBEDTLS_SSL_DEBUG_MSG(2, ("in_left: %" MBEDTLS_PRINTF_SIZET ", nb_want: %" MBEDTLS_PRINTF_SIZET, ssl->in_left, nb_want)); while (ssl->in_left < nb_want) { len = nb_want - ssl->in_left; if (mbedtls_ssl_check_timer(ssl) != 0) { ret = MBEDTLS_ERR_SSL_TIMEOUT; } else { if (ssl->f_recv_timeout != NULL) { ret = ssl->f_recv_timeout(ssl->p_bio, ssl->in_hdr + ssl->in_left, len, ssl->conf->read_timeout); } else { ret = ssl->f_recv(ssl->p_bio, ssl->in_hdr + ssl->in_left, len); } } MBEDTLS_SSL_DEBUG_MSG(2, ("in_left: %" MBEDTLS_PRINTF_SIZET ", nb_want: %" MBEDTLS_PRINTF_SIZET, ssl->in_left, nb_want)); MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_recv(_timeout)", ret); if (ret == 0) { return MBEDTLS_ERR_SSL_CONN_EOF; } if (ret < 0) { return ret; } if ((size_t) ret > len) { MBEDTLS_SSL_DEBUG_MSG(1, ("f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested", ret, len)); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->in_left += ret; } } MBEDTLS_SSL_DEBUG_MSG(2, ("<= fetch input")); return 0; } /* * Flush any data not yet written */ int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; MBEDTLS_SSL_DEBUG_MSG(2, ("=> flush output")); if (ssl->f_send == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("Bad usage of mbedtls_ssl_set_bio() ")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Avoid incrementing counter if data is flushed */ if (ssl->out_left == 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= flush output")); return 0; } while (ssl->out_left > 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("message length: %" MBEDTLS_PRINTF_SIZET ", out_left: %" MBEDTLS_PRINTF_SIZET, mbedtls_ssl_out_hdr_len(ssl) + ssl->out_msglen, ssl->out_left)); buf = ssl->out_hdr - ssl->out_left; ret = ssl->f_send(ssl->p_bio, buf, ssl->out_left); MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_send", ret); if (ret <= 0) { return ret; } if ((size_t) ret > ssl->out_left) { MBEDTLS_SSL_DEBUG_MSG(1, ("f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent", ret, ssl->out_left)); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->out_left -= ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->out_hdr = ssl->out_buf; } else #endif { ssl->out_hdr = ssl->out_buf + 8; } mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out); MBEDTLS_SSL_DEBUG_MSG(2, ("<= flush output")); return 0; } /* * Functions to handle the DTLS retransmission state machine */ #if defined(MBEDTLS_SSL_PROTO_DTLS) /* * Append current handshake message to current outgoing flight */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_flight_append(mbedtls_ssl_context *ssl) { mbedtls_ssl_flight_item *msg; MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_flight_append")); MBEDTLS_SSL_DEBUG_BUF(4, "message appended to flight", ssl->out_msg, ssl->out_msglen); /* Allocate space for current message */ if ((msg = mbedtls_calloc(1, sizeof(mbedtls_ssl_flight_item))) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc %" MBEDTLS_PRINTF_SIZET " bytes failed", sizeof(mbedtls_ssl_flight_item))); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } if ((msg->p = mbedtls_calloc(1, ssl->out_msglen)) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc %" MBEDTLS_PRINTF_SIZET " bytes failed", ssl->out_msglen)); mbedtls_free(msg); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } /* Copy current handshake message with headers */ memcpy(msg->p, ssl->out_msg, ssl->out_msglen); msg->len = ssl->out_msglen; msg->type = ssl->out_msgtype; msg->next = NULL; /* Append to the current flight */ if (ssl->handshake->flight == NULL) { ssl->handshake->flight = msg; } else { mbedtls_ssl_flight_item *cur = ssl->handshake->flight; while (cur->next != NULL) { cur = cur->next; } cur->next = msg; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_flight_append")); return 0; } /* * Free the current flight of handshake messages */ void mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight) { mbedtls_ssl_flight_item *cur = flight; mbedtls_ssl_flight_item *next; while (cur != NULL) { next = cur->next; mbedtls_free(cur->p); mbedtls_free(cur); cur = next; } } /* * Swap transform_out and out_ctr with the alternative ones */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_swap_epochs(mbedtls_ssl_context *ssl) { mbedtls_ssl_transform *tmp_transform; unsigned char tmp_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; if (ssl->transform_out == ssl->handshake->alt_transform_out) { MBEDTLS_SSL_DEBUG_MSG(3, ("skip swap epochs")); return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("swap epochs")); /* Swap transforms */ tmp_transform = ssl->transform_out; ssl->transform_out = ssl->handshake->alt_transform_out; ssl->handshake->alt_transform_out = tmp_transform; /* Swap epoch + sequence_number */ memcpy(tmp_out_ctr, ssl->cur_out_ctr, sizeof(tmp_out_ctr)); memcpy(ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, sizeof(ssl->cur_out_ctr)); memcpy(ssl->handshake->alt_out_ctr, tmp_out_ctr, sizeof(ssl->handshake->alt_out_ctr)); /* Adjust to the newly activated transform */ mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out); return 0; } /* * Retransmit the current flight of messages. */ int mbedtls_ssl_resend(mbedtls_ssl_context *ssl) { int ret = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_resend")); ret = mbedtls_ssl_flight_transmit(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_resend")); return ret; } /* * Transmit or retransmit the current flight of messages. * * Need to remember the current message in case flush_output returns * WANT_WRITE, causing us to exit this function and come back later. * This function must be called until state is no longer SENDING. */ int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_flight_transmit")); if (ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING) { MBEDTLS_SSL_DEBUG_MSG(2, ("initialise flight transmission")); ssl->handshake->cur_msg = ssl->handshake->flight; ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; ret = ssl_swap_epochs(ssl); if (ret != 0) { return ret; } ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; } while (ssl->handshake->cur_msg != NULL) { size_t max_frag_len; const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; int const is_finished = (cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && cur->p[0] == MBEDTLS_SSL_HS_FINISHED); int const force_flush = ssl->disable_datagram_packing == 1 ? SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; /* Swap epochs before sending Finished: we can't do it after * sending ChangeCipherSpec, in case write returns WANT_READ. * Must be done before copying, may change out_msg pointer */ if (is_finished && ssl->handshake->cur_msg_p == (cur->p + 12)) { MBEDTLS_SSL_DEBUG_MSG(2, ("swap epochs to send finished message")); ret = ssl_swap_epochs(ssl); if (ret != 0) { return ret; } } ret = ssl_get_remaining_payload_in_datagram(ssl); if (ret < 0) { return ret; } max_frag_len = (size_t) ret; /* CCS is copied as is, while HS messages may need fragmentation */ if (cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { if (max_frag_len == 0) { if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } continue; } memcpy(ssl->out_msg, cur->p, cur->len); ssl->out_msglen = cur->len; ssl->out_msgtype = cur->type; /* Update position inside current message */ ssl->handshake->cur_msg_p += cur->len; } else { const unsigned char * const p = ssl->handshake->cur_msg_p; const size_t hs_len = cur->len - 12; const size_t frag_off = (size_t) (p - (cur->p + 12)); const size_t rem_len = hs_len - frag_off; size_t cur_hs_frag_len, max_hs_frag_len; if ((max_frag_len < 12) || (max_frag_len == 12 && hs_len != 0)) { if (is_finished) { ret = ssl_swap_epochs(ssl); if (ret != 0) { return ret; } } if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } continue; } max_hs_frag_len = max_frag_len - 12; cur_hs_frag_len = rem_len > max_hs_frag_len ? max_hs_frag_len : rem_len; if (frag_off == 0 && cur_hs_frag_len != hs_len) { MBEDTLS_SSL_DEBUG_MSG(2, ("fragmenting handshake message (%u > %u)", (unsigned) cur_hs_frag_len, (unsigned) max_hs_frag_len)); } /* Messages are stored with handshake headers as if not fragmented, * copy beginning of headers then fill fragmentation fields. * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ memcpy(ssl->out_msg, cur->p, 6); ssl->out_msg[6] = MBEDTLS_BYTE_2(frag_off); ssl->out_msg[7] = MBEDTLS_BYTE_1(frag_off); ssl->out_msg[8] = MBEDTLS_BYTE_0(frag_off); ssl->out_msg[9] = MBEDTLS_BYTE_2(cur_hs_frag_len); ssl->out_msg[10] = MBEDTLS_BYTE_1(cur_hs_frag_len); ssl->out_msg[11] = MBEDTLS_BYTE_0(cur_hs_frag_len); MBEDTLS_SSL_DEBUG_BUF(3, "handshake header", ssl->out_msg, 12); /* Copy the handshake message content and set records fields */ memcpy(ssl->out_msg + 12, p, cur_hs_frag_len); ssl->out_msglen = cur_hs_frag_len + 12; ssl->out_msgtype = cur->type; /* Update position inside current message */ ssl->handshake->cur_msg_p += cur_hs_frag_len; } /* If done with the current message move to the next one if any */ if (ssl->handshake->cur_msg_p >= cur->p + cur->len) { if (cur->next != NULL) { ssl->handshake->cur_msg = cur->next; ssl->handshake->cur_msg_p = cur->next->p + 12; } else { ssl->handshake->cur_msg = NULL; ssl->handshake->cur_msg_p = NULL; } } /* Actually send the message out */ if ((ret = mbedtls_ssl_write_record(ssl, force_flush)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret); return ret; } } if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } /* Update state and set timer */ if (mbedtls_ssl_is_handshake_over(ssl) == 1) { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; } else { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; mbedtls_ssl_set_timer(ssl, ssl->handshake->retransmit_timeout); } MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_flight_transmit")); return 0; } /* * To be called when the last message of an incoming flight is received. */ void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl) { /* We won't need to resend that one any more */ mbedtls_ssl_flight_free(ssl->handshake->flight); ssl->handshake->flight = NULL; ssl->handshake->cur_msg = NULL; /* The next incoming flight will start with this msg_seq */ ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; /* We don't want to remember CCS's across flight boundaries. */ ssl->handshake->buffering.seen_ccs = 0; /* Clear future message buffering structure. */ mbedtls_ssl_buffering_free(ssl); /* Cancel timer */ mbedtls_ssl_set_timer(ssl, 0); if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED) { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; } else { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; } } /* * To be called when the last message of an outgoing flight is send. */ void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl) { ssl_reset_retransmit_timeout(ssl); mbedtls_ssl_set_timer(ssl, ssl->handshake->retransmit_timeout); if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED) { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; } else { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Handshake layer functions */ int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type, unsigned char **buf, size_t *buf_len) { /* * Reserve 4 bytes for handshake header. ( Section 4,RFC 8446 ) * ... * HandshakeType msg_type; * uint24 length; * ... */ *buf = ssl->out_msg + 4; *buf_len = MBEDTLS_SSL_OUT_CONTENT_LEN - 4; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = hs_type; return 0; } /* * Write (DTLS: or queue) current handshake (including CCS) message. * * - fill in handshake headers * - update handshake checksum * - DTLS: save message for resending * - then pass to the record layer * * DTLS: except for HelloRequest, messages are only queued, and will only be * actually sent when calling flight_transmit() or resend(). * * Inputs: * - ssl->out_msglen: 4 + actual handshake message len * (4 is the size of handshake headers for TLS) * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) * - ssl->out_msg + 4: the handshake message body * * Outputs, ie state before passing to flight_append() or write_record(): * - ssl->out_msglen: the length of the record contents * (including handshake headers but excluding record headers) * - ssl->out_msg: the record contents (handshake headers + content) */ int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl, int update_checksum, int force_flush) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t hs_len = ssl->out_msglen - 4; const unsigned char hs_type = ssl->out_msg[0]; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write handshake message")); /* * Sanity checks */ if (ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Whenever we send anything different from a * HelloRequest we should be in a handshake - double check. */ if (!(ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST) && ssl->handshake == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif /* Double-check that we did not exceed the bounds * of the outgoing record buffer. * This should never fail as the various message * writing functions must obey the bounds of the * outgoing record buffer, but better be safe. * * Note: We deliberately do not check for the MTU or MFL here. */ if (ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("Record too large: " "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET, ssl->out_msglen, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN)); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * Fill handshake headers */ if (ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) { ssl->out_msg[1] = MBEDTLS_BYTE_2(hs_len); ssl->out_msg[2] = MBEDTLS_BYTE_1(hs_len); ssl->out_msg[3] = MBEDTLS_BYTE_0(hs_len); /* * DTLS has additional fields in the Handshake layer, * between the length field and the actual payload: * uint16 message_seq; * uint24 fragment_offset; * uint24 fragment_length; */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Make room for the additional DTLS fields */ if (MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS handshake message too large: " "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET, hs_len, (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN - 12))); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memmove(ssl->out_msg + 12, ssl->out_msg + 4, hs_len); ssl->out_msglen += 8; /* Write message_seq and update it, except for HelloRequest */ if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST) { MBEDTLS_PUT_UINT16_BE(ssl->handshake->out_msg_seq, ssl->out_msg, 4); ++(ssl->handshake->out_msg_seq); } else { ssl->out_msg[4] = 0; ssl->out_msg[5] = 0; } /* Handshake hashes are computed without fragmentation, * so set frag_offset = 0 and frag_len = hs_len for now */ memset(ssl->out_msg + 6, 0x00, 3); memcpy(ssl->out_msg + 9, ssl->out_msg + 1, 3); } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* Update running hashes of handshake messages seen */ if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST && update_checksum != 0) { ret = ssl->handshake->update_checksum(ssl, ssl->out_msg, ssl->out_msglen); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } } } /* Either send now, or just save to be sent (and resent) later */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && !(ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST)) { if ((ret = ssl_flight_append(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_flight_append", ret); return ret; } } else #endif { if ((ret = mbedtls_ssl_write_record(ssl, force_flush)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_record", ret); return ret; } } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write handshake message")); return 0; } int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl, size_t buf_len, size_t msg_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t msg_with_header_len; ((void) buf_len); /* Add reserved 4 bytes for handshake header */ msg_with_header_len = msg_len + 4; ssl->out_msglen = msg_with_header_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_handshake_msg_ext(ssl, 0, 0)); cleanup: return ret; } /* * Record layer functions */ /* * Write current record. * * Uses: * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) * - ssl->out_msglen: length of the record content (excl headers) * - ssl->out_msg: record content */ int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush) { int ret, done = 0; size_t len = ssl->out_msglen; int flush = force_flush; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write record")); if (!done) { unsigned i; size_t protected_record_size; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len; #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #endif /* Skip writing the record content type to after the encryption, * as it may change when using the CID extension. */ mbedtls_ssl_protocol_version tls_ver = ssl->tls_version; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* TLS 1.3 still uses the TLS 1.2 version identifier * for backwards compatibility. */ if (tls_ver == MBEDTLS_SSL_VERSION_TLS1_3) { tls_ver = MBEDTLS_SSL_VERSION_TLS1_2; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ mbedtls_ssl_write_version(ssl->out_hdr + 1, ssl->conf->transport, tls_ver); memcpy(ssl->out_ctr, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); MBEDTLS_PUT_UINT16_BE(len, ssl->out_len, 0); if (ssl->transform_out != NULL) { mbedtls_record rec; rec.buf = ssl->out_iv; rec.buf_len = out_buf_len - (size_t) (ssl->out_iv - ssl->out_buf); rec.data_len = ssl->out_msglen; rec.data_offset = (size_t) (ssl->out_msg - rec.buf); memcpy(&rec.ctr[0], ssl->out_ctr, sizeof(rec.ctr)); mbedtls_ssl_write_version(rec.ver, ssl->conf->transport, tls_ver); rec.type = ssl->out_msgtype; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* The CID is set by mbedtls_ssl_encrypt_buf(). */ rec.cid_len = 0; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ if ((ret = mbedtls_ssl_encrypt_buf(ssl, ssl->transform_out, &rec, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_encrypt_buf", ret); return ret; } if (rec.data_offset != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Update the record content type and CID. */ ssl->out_msgtype = rec.type; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) memcpy(ssl->out_cid, rec.cid, rec.cid_len); #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->out_msglen = len = rec.data_len; MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->out_len, 0); } protected_record_size = len + mbedtls_ssl_out_hdr_len(ssl); #if defined(MBEDTLS_SSL_PROTO_DTLS) /* In case of DTLS, double-check that we don't exceed * the remaining space in the datagram. */ if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ret = ssl_get_remaining_space_in_datagram(ssl); if (ret < 0) { return ret; } if (protected_record_size > (size_t) ret) { /* Should never happen */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* Now write the potentially updated record content type. */ ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; MBEDTLS_SSL_DEBUG_MSG(3, ("output record: msgtype = %u, " "version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET, ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], len)); MBEDTLS_SSL_DEBUG_BUF(4, "output record sent to network", ssl->out_hdr, protected_record_size); ssl->out_left += protected_record_size; ssl->out_hdr += protected_record_size; mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out); for (i = 8; i > mbedtls_ssl_ep_len(ssl); i--) { if (++ssl->cur_out_ctr[i - 1] != 0) { break; } } /* The loop goes to its end if the counter is wrapping */ if (i == mbedtls_ssl_ep_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("outgoing message counter would wrap")); return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; } } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && flush == SSL_DONT_FORCE_FLUSH) { size_t remaining; ret = ssl_get_remaining_payload_in_datagram(ssl); if (ret < 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_get_remaining_payload_in_datagram", ret); return ret; } remaining = (size_t) ret; if (remaining == 0) { flush = SSL_FORCE_FLUSH; } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Still %u bytes available in current datagram", (unsigned) remaining)); } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ if ((flush == SSL_FORCE_FLUSH) && (ret = mbedtls_ssl_flush_output(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write record")); return 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_hs_is_proper_fragment(mbedtls_ssl_context *ssl) { if (ssl->in_msglen < ssl->in_hslen || memcmp(ssl->in_msg + 6, "\0\0\0", 3) != 0 || memcmp(ssl->in_msg + 9, ssl->in_msg + 1, 3) != 0) { return 1; } return 0; } static uint32_t ssl_get_hs_frag_len(mbedtls_ssl_context const *ssl) { return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9); } static uint32_t ssl_get_hs_frag_off(mbedtls_ssl_context const *ssl) { return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_hs_header(mbedtls_ssl_context const *ssl) { uint32_t msg_len, frag_off, frag_len; msg_len = ssl_get_hs_total_len(ssl); frag_off = ssl_get_hs_frag_off(ssl); frag_len = ssl_get_hs_frag_len(ssl); if (frag_off > msg_len) { return -1; } if (frag_len > msg_len - frag_off) { return -1; } if (frag_len + 12 > ssl->in_msglen) { return -1; } return 0; } /* * Mark bits in bitmask (used for DTLS HS reassembly) */ static void ssl_bitmask_set(unsigned char *mask, size_t offset, size_t len) { unsigned int start_bits, end_bits; start_bits = 8 - (offset % 8); if (start_bits != 8) { size_t first_byte_idx = offset / 8; /* Special case */ if (len <= start_bits) { for (; len != 0; len--) { mask[first_byte_idx] |= 1 << (start_bits - len); } /* Avoid potential issues with offset or len becoming invalid */ return; } offset += start_bits; /* Now offset % 8 == 0 */ len -= start_bits; for (; start_bits != 0; start_bits--) { mask[first_byte_idx] |= 1 << (start_bits - 1); } } end_bits = len % 8; if (end_bits != 0) { size_t last_byte_idx = (offset + len) / 8; len -= end_bits; /* Now len % 8 == 0 */ for (; end_bits != 0; end_bits--) { mask[last_byte_idx] |= 1 << (8 - end_bits); } } memset(mask + offset / 8, 0xFF, len / 8); } /* * Check that bitmask is full */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_bitmask_check(unsigned char *mask, size_t len) { size_t i; for (i = 0; i < len / 8; i++) { if (mask[i] != 0xFF) { return -1; } } for (i = 0; i < len % 8; i++) { if ((mask[len / 8] & (1 << (7 - i))) == 0) { return -1; } } return 0; } /* msg_len does not include the handshake header */ static size_t ssl_get_reassembly_buffer_size(size_t msg_len, unsigned add_bitmap) { size_t alloc_len; alloc_len = 12; /* Handshake header */ alloc_len += msg_len; /* Content buffer */ if (add_bitmap) { alloc_len += msg_len / 8 + (msg_len % 8 != 0); /* Bitmap */ } return alloc_len; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl) { return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1); } int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) { if (ssl->in_msglen < mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("handshake message too short: %" MBEDTLS_PRINTF_SIZET, ssl->in_msglen)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } ssl->in_hslen = mbedtls_ssl_hs_hdr_len(ssl) + ssl_get_hs_total_len(ssl); MBEDTLS_SSL_DEBUG_MSG(3, ("handshake message: msglen =" " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %" MBEDTLS_PRINTF_SIZET, ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen)); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned int recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); if (ssl_check_hs_header(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid handshake header")); return MBEDTLS_ERR_SSL_INVALID_RECORD; } if (ssl->handshake != NULL && ((mbedtls_ssl_is_handshake_over(ssl) == 0 && recv_msg_seq != ssl->handshake->in_msg_seq) || (mbedtls_ssl_is_handshake_over(ssl) == 1 && ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO))) { if (recv_msg_seq > ssl->handshake->in_msg_seq) { MBEDTLS_SSL_DEBUG_MSG(2, ( "received future handshake message of sequence number %u (next %u)", recv_msg_seq, ssl->handshake->in_msg_seq)); return MBEDTLS_ERR_SSL_EARLY_MESSAGE; } /* Retransmit only on last message from previous flight, to avoid * too many retransmissions. * Besides, No sane server ever retransmits HelloVerifyRequest */ if (recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST) { MBEDTLS_SSL_DEBUG_MSG(2, ("received message from last flight, " "message_seq = %u, start_of_flight = %u", recv_msg_seq, ssl->handshake->in_flight_start_seq)); if ((ret = mbedtls_ssl_resend(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend", ret); return ret; } } else { MBEDTLS_SSL_DEBUG_MSG(2, ("dropping out-of-sequence message: " "message_seq = %u, expected = %u", recv_msg_seq, ssl->handshake->in_msg_seq)); } return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } /* Wait until message completion to increment in_msg_seq */ /* Message reassembly is handled alongside buffering of future * messages; the commonality is that both handshake fragments and * future messages cannot be forwarded immediately to the * handshake logic layer. */ if (ssl_hs_is_proper_fragment(ssl) == 1) { MBEDTLS_SSL_DEBUG_MSG(2, ("found fragmented DTLS handshake message")); return MBEDTLS_ERR_SSL_EARLY_MESSAGE; } } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* With TLS we don't handle fragmentation (for now) */ if (ssl->in_msglen < ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("TLS handshake fragmentation not supported")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } return 0; } int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params * const hs = ssl->handshake; if (mbedtls_ssl_is_handshake_over(ssl) == 0 && hs != NULL) { ret = ssl->handshake->update_checksum(ssl, ssl->in_msg, ssl->in_hslen); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } } /* Handshake message is complete, increment counter */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL) { unsigned offset; mbedtls_ssl_hs_buffer *hs_buf; /* Increment handshake sequence number */ hs->in_msg_seq++; /* * Clear up handshake buffering and reassembly structure. */ /* Free first entry */ ssl_buffering_free_slot(ssl, 0); /* Shift all other entries */ for (offset = 0, hs_buf = &hs->buffering.hs[0]; offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++, hs_buf++) { *hs_buf = *(hs_buf + 1); } /* Create a fresh last entry */ memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer)); } #endif return 0; } /* * DTLS anti-replay: RFC 6347 4.1.2.6 * * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). * Bit n is set iff record number in_window_top - n has been seen. * * Usually, in_window_top is the last record number seen and the lsb of * in_window is set. The only exception is the initial state (record number 0 * not seen yet). */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) void mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl) { ssl->in_window_top = 0; ssl->in_window = 0; } static inline uint64_t ssl_load_six_bytes(unsigned char *buf) { return ((uint64_t) buf[0] << 40) | ((uint64_t) buf[1] << 32) | ((uint64_t) buf[2] << 24) | ((uint64_t) buf[3] << 16) | ((uint64_t) buf[4] << 8) | ((uint64_t) buf[5]); } MBEDTLS_CHECK_RETURN_CRITICAL static int mbedtls_ssl_dtls_record_replay_check(mbedtls_ssl_context *ssl, uint8_t *record_in_ctr) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *original_in_ctr; // save original in_ctr original_in_ctr = ssl->in_ctr; // use counter from record ssl->in_ctr = record_in_ctr; ret = mbedtls_ssl_dtls_replay_check((mbedtls_ssl_context const *) ssl); // restore the counter ssl->in_ctr = original_in_ctr; return ret; } /* * Return 0 if sequence number is acceptable, -1 otherwise */ int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl) { uint64_t rec_seqnum = ssl_load_six_bytes(ssl->in_ctr + 2); uint64_t bit; if (ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED) { return 0; } if (rec_seqnum > ssl->in_window_top) { return 0; } bit = ssl->in_window_top - rec_seqnum; if (bit >= 64) { return -1; } if ((ssl->in_window & ((uint64_t) 1 << bit)) != 0) { return -1; } return 0; } /* * Update replay window on new validated record */ void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl) { uint64_t rec_seqnum = ssl_load_six_bytes(ssl->in_ctr + 2); if (ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED) { return; } if (rec_seqnum > ssl->in_window_top) { /* Update window_top and the contents of the window */ uint64_t shift = rec_seqnum - ssl->in_window_top; if (shift >= 64) { ssl->in_window = 1; } else { ssl->in_window <<= shift; ssl->in_window |= 1; } ssl->in_window_top = rec_seqnum; } else { /* Mark that number as seen in the current window */ uint64_t bit = ssl->in_window_top - rec_seqnum; if (bit < 64) { /* Always true, but be extra sure */ ssl->in_window |= (uint64_t) 1 << bit; } } } #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) /* * Check if a datagram looks like a ClientHello with a valid cookie, * and if it doesn't, generate a HelloVerifyRequest message. * Both input and output include full DTLS headers. * * - if cookie is valid, return 0 * - if ClientHello looks superficially valid but cookie is not, * fill obuf and set olen, then * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED * - otherwise return a specific error code */ MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_STATIC_TESTABLE int mbedtls_ssl_check_dtls_clihlo_cookie( mbedtls_ssl_context *ssl, const unsigned char *cli_id, size_t cli_id_len, const unsigned char *in, size_t in_len, unsigned char *obuf, size_t buf_len, size_t *olen) { size_t sid_len, cookie_len, epoch, fragment_offset; unsigned char *p; /* * Structure of ClientHello with record and handshake headers, * and expected values. We don't need to check a lot, more checks will be * done when actually parsing the ClientHello - skipping those checks * avoids code duplication and does not make cookie forging any easier. * * 0-0 ContentType type; copied, must be handshake * 1-2 ProtocolVersion version; copied * 3-4 uint16 epoch; copied, must be 0 * 5-10 uint48 sequence_number; copied * 11-12 uint16 length; (ignored) * * 13-13 HandshakeType msg_type; (ignored) * 14-16 uint24 length; (ignored) * 17-18 uint16 message_seq; copied * 19-21 uint24 fragment_offset; copied, must be 0 * 22-24 uint24 fragment_length; (ignored) * * 25-26 ProtocolVersion client_version; (ignored) * 27-58 Random random; (ignored) * 59-xx SessionID session_id; 1 byte len + sid_len content * 60+ opaque cookie<0..2^8-1>; 1 byte len + content * ... * * Minimum length is 61 bytes. */ MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: in_len=%u", (unsigned) in_len)); MBEDTLS_SSL_DEBUG_BUF(4, "cli_id", cli_id, cli_id_len); if (in_len < 61) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: record too short")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } epoch = MBEDTLS_GET_UINT16_BE(in, 3); fragment_offset = MBEDTLS_GET_UINT24_BE(in, 19); if (in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || epoch != 0 || fragment_offset != 0) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: not a good ClientHello")); MBEDTLS_SSL_DEBUG_MSG(4, (" type=%u epoch=%u fragment_offset=%u", in[0], (unsigned) epoch, (unsigned) fragment_offset)); return MBEDTLS_ERR_SSL_DECODE_ERROR; } sid_len = in[59]; if (59 + 1 + sid_len + 1 > in_len) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: sid_len=%u > %u", (unsigned) sid_len, (unsigned) in_len - 61)); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(4, "sid received from network", in + 60, sid_len); cookie_len = in[60 + sid_len]; if (59 + 1 + sid_len + 1 + cookie_len > in_len) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: cookie_len=%u > %u", (unsigned) cookie_len, (unsigned) (in_len - sid_len - 61))); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(4, "cookie received from network", in + sid_len + 61, cookie_len); if (ssl->conf->f_cookie_check(ssl->conf->p_cookie, in + sid_len + 61, cookie_len, cli_id, cli_id_len) == 0) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: valid")); return 0; } /* * If we get here, we've got an invalid cookie, let's prepare HVR. * * 0-0 ContentType type; copied * 1-2 ProtocolVersion version; copied * 3-4 uint16 epoch; copied * 5-10 uint48 sequence_number; copied * 11-12 uint16 length; olen - 13 * * 13-13 HandshakeType msg_type; hello_verify_request * 14-16 uint24 length; olen - 25 * 17-18 uint16 message_seq; copied * 19-21 uint24 fragment_offset; copied * 22-24 uint24 fragment_length; olen - 25 * * 25-26 ProtocolVersion server_version; 0xfe 0xff * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie * * Minimum length is 28. */ if (buf_len < 28) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } /* Copy most fields and adapt others */ memcpy(obuf, in, 25); obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; obuf[25] = 0xfe; obuf[26] = 0xff; /* Generate and write actual cookie */ p = obuf + 28; if (ssl->conf->f_cookie_write(ssl->conf->p_cookie, &p, obuf + buf_len, cli_id, cli_id_len) != 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } *olen = (size_t) (p - obuf); /* Go back and fill length fields */ obuf[27] = (unsigned char) (*olen - 28); obuf[14] = obuf[22] = MBEDTLS_BYTE_2(*olen - 25); obuf[15] = obuf[23] = MBEDTLS_BYTE_1(*olen - 25); obuf[16] = obuf[24] = MBEDTLS_BYTE_0(*olen - 25); MBEDTLS_PUT_UINT16_BE(*olen - 13, obuf, 11); return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED; } /* * Handle possible client reconnect with the same UDP quadruplet * (RFC 6347 Section 4.2.8). * * Called by ssl_parse_record_header() in case we receive an epoch 0 record * that looks like a ClientHello. * * - if the input looks like a ClientHello without cookies, * send back HelloVerifyRequest, then return 0 * - if the input looks like a ClientHello with a valid cookie, * reset the session of the current context, and * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT * - if anything goes wrong, return a specific error code * * This function is called (through ssl_check_client_reconnect()) when an * unexpected record is found in ssl_get_next_record(), which will discard the * record if we return 0, and bubble up the return value otherwise (this * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected * errors, and is the right thing to do in both cases). */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_handle_possible_reconnect(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; if (ssl->conf->f_cookie_write == NULL || ssl->conf->f_cookie_check == NULL) { /* If we can't use cookies to verify reachability of the peer, * drop the record. */ MBEDTLS_SSL_DEBUG_MSG(1, ("no cookie callbacks, " "can't check reconnect validity")); return 0; } ret = mbedtls_ssl_check_dtls_clihlo_cookie( ssl, ssl->cli_id, ssl->cli_id_len, ssl->in_buf, ssl->in_left, ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len); MBEDTLS_SSL_DEBUG_RET(2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret); if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) { int send_ret; MBEDTLS_SSL_DEBUG_MSG(1, ("sending HelloVerifyRequest")); MBEDTLS_SSL_DEBUG_BUF(4, "output record sent to network", ssl->out_buf, len); /* Don't check write errors as we can't do anything here. * If the error is permanent we'll catch it later, * if it's not, then hopefully it'll work next time. */ send_ret = ssl->f_send(ssl->p_bio, ssl->out_buf, len); MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_send", send_ret); (void) send_ret; return 0; } if (ret == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("cookie is valid, resetting context")); if ((ret = mbedtls_ssl_session_reset_int(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "reset", ret); return ret; } return MBEDTLS_ERR_SSL_CLIENT_RECONNECT; } return ret; } #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_record_type(uint8_t record_type) { if (record_type != MBEDTLS_SSL_MSG_HANDSHAKE && record_type != MBEDTLS_SSL_MSG_ALERT && record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA) { return MBEDTLS_ERR_SSL_INVALID_RECORD; } return 0; } /* * ContentType type; * ProtocolVersion version; * uint16 epoch; // DTLS only * uint48 sequence_number; // DTLS only * uint16 length; * * Return 0 if header looks sane (and, for DTLS, the record is expected) * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. * * With DTLS, mbedtls_ssl_read_record() will: * 1. proceed with the record if this function returns 0 * 2. drop only the current record if this function returns UNEXPECTED_RECORD * 3. return CLIENT_RECONNECT if this function return that value * 4. drop the whole datagram if this function returns anything else. * Point 2 is needed when the peer is resending, and we have already received * the first record from a datagram but are still waiting for the others. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, unsigned char *buf, size_t len, mbedtls_record *rec) { mbedtls_ssl_protocol_version tls_version; size_t const rec_hdr_type_offset = 0; size_t const rec_hdr_type_len = 1; size_t const rec_hdr_version_offset = rec_hdr_type_offset + rec_hdr_type_len; size_t const rec_hdr_version_len = 2; size_t const rec_hdr_ctr_len = 8; #if defined(MBEDTLS_SSL_PROTO_DTLS) uint32_t rec_epoch; size_t const rec_hdr_ctr_offset = rec_hdr_version_offset + rec_hdr_version_len; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len; size_t rec_hdr_cid_len = 0; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ size_t rec_hdr_len_offset; /* To be determined */ size_t const rec_hdr_len_len = 2; /* * Check minimum lengths for record header. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len; } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len; } if (len < rec_hdr_len_offset + rec_hdr_len_len) { MBEDTLS_SSL_DEBUG_MSG(1, ( "datagram of length %u too small to hold DTLS record header of length %u", (unsigned) len, (unsigned) (rec_hdr_len_len + rec_hdr_len_len))); return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* * Parse and validate record content type */ rec->type = buf[rec_hdr_type_offset]; /* Check record content type */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) rec->cid_len = 0; if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->conf->cid_len != 0 && rec->type == MBEDTLS_SSL_MSG_CID) { /* Shift pointers to account for record header including CID * struct { * ContentType outer_type = tls12_cid; * ProtocolVersion version; * uint16 epoch; * uint48 sequence_number; * opaque cid[cid_length]; // Additional field compared to * // default DTLS record format * uint16 length; * opaque enc_content[DTLSCiphertext.length]; * } DTLSCiphertext; */ /* So far, we only support static CID lengths * fixed in the configuration. */ rec_hdr_cid_len = ssl->conf->cid_len; rec_hdr_len_offset += rec_hdr_cid_len; if (len < rec_hdr_len_offset + rec_hdr_len_len) { MBEDTLS_SSL_DEBUG_MSG(1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u", (unsigned) len, (unsigned) (rec_hdr_len_offset + rec_hdr_len_len))); return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* configured CID len is guaranteed at most 255, see * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */ rec->cid_len = (uint8_t) rec_hdr_cid_len; memcpy(rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len); } else #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ { if (ssl_check_record_type(rec->type)) { MBEDTLS_SSL_DEBUG_MSG(1, ("unknown record type %u", (unsigned) rec->type)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } } /* * Parse and validate record version */ rec->ver[0] = buf[rec_hdr_version_offset + 0]; rec->ver[1] = buf[rec_hdr_version_offset + 1]; tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version( buf + rec_hdr_version_offset, ssl->conf->transport); if (tls_version > ssl->conf->max_tls_version) { MBEDTLS_SSL_DEBUG_MSG(1, ("TLS version mismatch: got %u, expected max %u", (unsigned) tls_version, (unsigned) ssl->conf->max_tls_version)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* * Parse/Copy record sequence number. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Copy explicit record sequence number from input buffer. */ memcpy(&rec->ctr[0], buf + rec_hdr_ctr_offset, rec_hdr_ctr_len); } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { /* Copy implicit record sequence number from SSL context structure. */ memcpy(&rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len); } /* * Parse record length. */ rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len; rec->data_len = MBEDTLS_GET_UINT16_BE(buf, rec_hdr_len_offset); MBEDTLS_SSL_DEBUG_BUF(4, "input record header", buf, rec->data_offset); MBEDTLS_SSL_DEBUG_MSG(3, ("input record: msgtype = %u, " "version = [0x%x], msglen = %" MBEDTLS_PRINTF_SIZET, rec->type, (unsigned) tls_version, rec->data_len)); rec->buf = buf; rec->buf_len = rec->data_offset + rec->data_len; if (rec->data_len == 0) { return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* * DTLS-related tests. * Check epoch before checking length constraint because * the latter varies with the epoch. E.g., if a ChangeCipherSpec * message gets duplicated before the corresponding Finished message, * the second ChangeCipherSpec should be discarded because it belongs * to an old epoch, but not because its length is shorter than * the minimum record length for packets using the new record transform. * Note that these two kinds of failures are handled differently, * as an unexpected record is silently skipped but an invalid * record leads to the entire datagram being dropped. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { rec_epoch = MBEDTLS_GET_UINT16_BE(rec->ctr, 0); /* Check that the datagram is large enough to contain a record * of the advertised length. */ if (len < rec->data_offset + rec->data_len) { MBEDTLS_SSL_DEBUG_MSG(1, ( "Datagram of length %u too small to contain record of advertised length %u.", (unsigned) len, (unsigned) (rec->data_offset + rec->data_len))); return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* Records from other, non-matching epochs are silently discarded. * (The case of same-port Client reconnects must be considered in * the caller). */ if (rec_epoch != ssl->in_epoch) { MBEDTLS_SSL_DEBUG_MSG(1, ("record from another epoch: " "expected %u, received %lu", ssl->in_epoch, (unsigned long) rec_epoch)); /* Records from the next epoch are considered for buffering * (concretely: early Finished messages). */ if (rec_epoch == (unsigned) ssl->in_epoch + 1) { MBEDTLS_SSL_DEBUG_MSG(2, ("Consider record for buffering")); return MBEDTLS_ERR_SSL_EARLY_MESSAGE; } return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) /* For records from the correct epoch, check whether their * sequence number has been seen before. */ else if (mbedtls_ssl_dtls_record_replay_check((mbedtls_ssl_context *) ssl, &rec->ctr[0]) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("replayed record")); return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } #endif } #endif /* MBEDTLS_SSL_PROTO_DTLS */ return 0; } #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_client_reconnect(mbedtls_ssl_context *ssl) { unsigned int rec_epoch = MBEDTLS_GET_UINT16_BE(ssl->in_ctr, 0); /* * Check for an epoch 0 ClientHello. We can't use in_msg here to * access the first byte of record content (handshake type), as we * have an active transform (possibly iv_len != 0), so use the * fact that the record header len is 13 instead. */ if (rec_epoch == 0 && ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && mbedtls_ssl_is_handshake_over(ssl) == 1 && ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_left > 13 && ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO) { MBEDTLS_SSL_DEBUG_MSG(1, ("possible client reconnect " "from the same port")); return ssl_handle_possible_reconnect(ssl); } return 0; } #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ /* * If applicable, decrypt record content */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_record_content(mbedtls_ssl_context *ssl, mbedtls_record *rec) { int ret, done = 0; MBEDTLS_SSL_DEBUG_BUF(4, "input record from network", rec->buf, rec->buf_len); /* * In TLS 1.3, always treat ChangeCipherSpec records * as unencrypted. The only thing we do with them is * check the length and content and ignore them. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->transform_in != NULL && ssl->transform_in->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { if (rec->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { done = 1; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ if (!done && ssl->transform_in != NULL) { unsigned char const old_msg_type = rec->type; if ((ret = mbedtls_ssl_decrypt_buf(ssl, ssl->transform_in, rec)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_decrypt_buf", ret); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) /* * Although the server rejected early data, it might receive early * data as long as it has not received the client Finished message. * It is encrypted with early keys and should be ignored as stated * in section 4.2.10 of RFC 8446: * * "Ignore the extension and return a regular 1-RTT response. The * server then skips past early data by attempting to deprotect * received records using the handshake traffic key, discarding * records which fail deprotection (up to the configured * max_early_data_size). Once a record is deprotected successfully, * it is treated as the start of the client's second flight and the * server proceeds as with an ordinary 1-RTT handshake." */ if ((old_msg_type == MBEDTLS_SSL_MSG_APPLICATION_DATA) && (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD)) { MBEDTLS_SSL_DEBUG_MSG( 3, ("EarlyData: deprotect and discard app data records.")); ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len); if (ret != 0) { return ret; } ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID && ssl->conf->ignore_unexpected_cid == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE) { MBEDTLS_SSL_DEBUG_MSG(3, ("ignoring unexpected CID")); ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /* * The decryption of the record failed, no reason to ignore it, * return in error with the decryption error code. */ return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) /* * If the server were discarding protected records that it fails to * deprotect because it has rejected early data, as we have just * deprotected successfully a record, the server has to resume normal * operation and fail the connection if the deprotection of a record * fails. */ if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD) { ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ if (old_msg_type != rec->type) { MBEDTLS_SSL_DEBUG_MSG(4, ("record type after decrypt (before %d): %d", old_msg_type, rec->type)); } MBEDTLS_SSL_DEBUG_BUF(4, "input payload after decrypt", rec->buf + rec->data_offset, rec->data_len); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* We have already checked the record content type * in ssl_parse_record_header(), failing or silently * dropping the record in the case of an unknown type. * * Since with the use of CIDs, the record content type * might change during decryption, re-check the record * content type, but treat a failure as fatal this time. */ if (ssl_check_record_type(rec->type)) { MBEDTLS_SSL_DEBUG_MSG(1, ("unknown record type")); return MBEDTLS_ERR_SSL_INVALID_RECORD; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ if (rec->data_len == 0) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA) { /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ MBEDTLS_SSL_DEBUG_MSG(1, ("invalid zero-length message type: %d", ssl->in_msgtype)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ ssl->nb_zero++; /* * Three or more empty messages may be a DoS attack * (excessive CPU consumption). */ if (ssl->nb_zero > 3) { MBEDTLS_SSL_DEBUG_MSG(1, ("received four consecutive empty " "messages, possible DoS attack")); /* Treat the records as if they were not properly authenticated, * thereby failing the connection if we see more than allowed * by the configured bad MAC threshold. */ return MBEDTLS_ERR_SSL_INVALID_MAC; } } else { ssl->nb_zero = 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ; /* in_ctr read from peer, not maintained internally */ } else #endif { unsigned i; for (i = MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; i > mbedtls_ssl_ep_len(ssl); i--) { if (++ssl->in_ctr[i - 1] != 0) { break; } } /* The loop goes to its end iff the counter is wrapping */ if (i == mbedtls_ssl_ep_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("incoming message counter would wrap")); return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; } } } #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) /* * Although the server rejected early data because it needed to send an * HelloRetryRequest message, it might receive early data as long as it has * not received the client Finished message. * The early data is encrypted with early keys and should be ignored as * stated in section 4.2.10 of RFC 8446 (second case): * * "The server then ignores early data by skipping all records with an * external content type of "application_data" (indicating that they are * encrypted), up to the configured max_early_data_size. Ignore application * data message before 2nd ClientHello when early_data was received in 1st * ClientHello." */ if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_DISCARD) { if (rec->type == MBEDTLS_SSL_MSG_APPLICATION_DATA) { ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len); if (ret != 0) { return ret; } MBEDTLS_SSL_DEBUG_MSG( 3, ("EarlyData: Ignore application message before 2nd ClientHello")); return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } else if (rec->type == MBEDTLS_SSL_MSG_HANDSHAKE) { ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; } } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_dtls_replay_update(ssl); } #endif /* Check actual (decrypted) record content length against * configured maximum. */ if (rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad message length")); return MBEDTLS_ERR_SSL_INVALID_RECORD; } return 0; } /* * Read a record. * * Silently ignore non-fatal alert (and for DTLS, invalid records as well, * RFC 6347 4.1.2.7) and continue reading until a valid record is found. * */ /* Helper functions for mbedtls_ssl_read_record(). */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_consume_current_message(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_next_record(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_record_is_in_progress(mbedtls_ssl_context *ssl); int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl, unsigned update_hs_digest) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> read record")); if (ssl->keep_current_message == 0) { do { ret = ssl_consume_current_message(ssl); if (ret != 0) { return ret; } if (ssl_record_is_in_progress(ssl) == 0) { int dtls_have_buffered = 0; #if defined(MBEDTLS_SSL_PROTO_DTLS) /* We only check for buffered messages if the * current datagram is fully consumed. */ if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl_next_record_is_in_datagram(ssl) == 0) { if (ssl_load_buffered_message(ssl) == 0) { dtls_have_buffered = 1; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ if (dtls_have_buffered == 0) { ret = ssl_get_next_record(ssl); if (ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) { continue; } if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_get_next_record"), ret); return ret; } } } ret = mbedtls_ssl_handle_message_type(ssl); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) { /* Buffer future message */ ret = ssl_buffer_message(ssl); if (ret != 0) { return ret; } ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ } while (MBEDTLS_ERR_SSL_NON_FATAL == ret || MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_handle_message_type"), ret); return ret; } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && update_hs_digest == 1) { ret = mbedtls_ssl_update_handshake_status(ssl); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret); return ret; } } } else { MBEDTLS_SSL_DEBUG_MSG(2, ("reuse previously read message")); ssl->keep_current_message = 0; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= read record")); return 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl) { if (ssl->in_left > ssl->next_record_offset) { return 1; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_message(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; mbedtls_ssl_hs_buffer *hs_buf; int ret = 0; if (hs == NULL) { return -1; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_load_buffered_message")); if (ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC) { /* Check if we have seen a ChangeCipherSpec before. * If yes, synthesize a CCS record. */ if (!hs->buffering.seen_ccs) { MBEDTLS_SSL_DEBUG_MSG(2, ("CCS not seen in the current flight")); ret = -1; goto exit; } MBEDTLS_SSL_DEBUG_MSG(2, ("Injecting buffered CCS message")); ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; ssl->in_msglen = 1; ssl->in_msg[0] = 1; /* As long as they are equal, the exact value doesn't matter. */ ssl->in_left = 0; ssl->next_record_offset = 0; hs->buffering.seen_ccs = 0; goto exit; } #if defined(MBEDTLS_DEBUG_C) /* Debug only */ { unsigned offset; for (offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) { hs_buf = &hs->buffering.hs[offset]; if (hs_buf->is_valid == 1) { MBEDTLS_SSL_DEBUG_MSG(2, ("Future message with sequence number %u %s buffered.", hs->in_msg_seq + offset, hs_buf->is_complete ? "fully" : "partially")); } } } #endif /* MBEDTLS_DEBUG_C */ /* Check if we have buffered and/or fully reassembled the * next handshake message. */ hs_buf = &hs->buffering.hs[0]; if ((hs_buf->is_valid == 1) && (hs_buf->is_complete == 1)) { /* Synthesize a record containing the buffered HS message. */ size_t msg_len = MBEDTLS_GET_UINT24_BE(hs_buf->data, 1); /* Double-check that we haven't accidentally buffered * a message that doesn't fit into the input buffer. */ if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(2, ("Next handshake message has been buffered - load")); MBEDTLS_SSL_DEBUG_BUF(3, "Buffered handshake message (incl. header)", hs_buf->data, msg_len + 12); ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->in_hslen = msg_len + 12; ssl->in_msglen = msg_len + 12; memcpy(ssl->in_msg, hs_buf->data, ssl->in_hslen); ret = 0; goto exit; } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Next handshake message %u not or only partially bufffered", hs->in_msg_seq)); } ret = -1; exit: MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_load_buffered_message")); return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_make_space(mbedtls_ssl_context *ssl, size_t desired) { int offset; mbedtls_ssl_handshake_params * const hs = ssl->handshake; MBEDTLS_SSL_DEBUG_MSG(2, ("Attempt to free buffered messages to have %u bytes available", (unsigned) desired)); /* Get rid of future records epoch first, if such exist. */ ssl_free_buffered_record(ssl); /* Check if we have enough space available now. */ if (desired <= (MBEDTLS_SSL_DTLS_MAX_BUFFERING - hs->buffering.total_bytes_buffered)) { MBEDTLS_SSL_DEBUG_MSG(2, ("Enough space available after freeing future epoch record")); return 0; } /* We don't have enough space to buffer the next expected handshake * message. Remove buffers used for future messages to gain space, * starting with the most distant one. */ for (offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; offset >= 0; offset--) { MBEDTLS_SSL_DEBUG_MSG(2, ( "Free buffering slot %d to make space for reassembly of next handshake message", offset)); ssl_buffering_free_slot(ssl, (uint8_t) offset); /* Check if we have enough space available now. */ if (desired <= (MBEDTLS_SSL_DTLS_MAX_BUFFERING - hs->buffering.total_bytes_buffered)) { MBEDTLS_SSL_DEBUG_MSG(2, ("Enough space available after freeing buffered HS messages")); return 0; } } return -1; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_message(mbedtls_ssl_context *ssl) { int ret = 0; mbedtls_ssl_handshake_params * const hs = ssl->handshake; if (hs == NULL) { return 0; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_buffer_message")); switch (ssl->in_msgtype) { case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: MBEDTLS_SSL_DEBUG_MSG(2, ("Remember CCS message")); hs->buffering.seen_ccs = 1; break; case MBEDTLS_SSL_MSG_HANDSHAKE: { unsigned recv_msg_seq_offset; unsigned recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); mbedtls_ssl_hs_buffer *hs_buf; size_t msg_len = ssl->in_hslen - 12; /* We should never receive an old handshake * message - double-check nonetheless. */ if (recv_msg_seq < ssl->handshake->in_msg_seq) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; if (recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS) { /* Silently ignore -- message too far in the future */ MBEDTLS_SSL_DEBUG_MSG(2, ("Ignore future HS message with sequence number %u, " "buffering window %u - %u", recv_msg_seq, ssl->handshake->in_msg_seq, ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1)); goto exit; } MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering HS message with sequence number %u, offset %u ", recv_msg_seq, recv_msg_seq_offset)); hs_buf = &hs->buffering.hs[recv_msg_seq_offset]; /* Check if the buffering for this seq nr has already commenced. */ if (!hs_buf->is_valid) { size_t reassembly_buf_sz; hs_buf->is_fragmented = (ssl_hs_is_proper_fragment(ssl) == 1); /* We copy the message back into the input buffer * after reassembly, so check that it's not too large. * This is an implementation-specific limitation * and not one from the standard, hence it is not * checked in ssl_check_hs_header(). */ if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) { /* Ignore message */ goto exit; } /* Check if we have enough space to buffer the message. */ if (hs->buffering.total_bytes_buffered > MBEDTLS_SSL_DTLS_MAX_BUFFERING) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } reassembly_buf_sz = ssl_get_reassembly_buffer_size(msg_len, hs_buf->is_fragmented); if (reassembly_buf_sz > (MBEDTLS_SSL_DTLS_MAX_BUFFERING - hs->buffering.total_bytes_buffered)) { if (recv_msg_seq_offset > 0) { /* If we can't buffer a future message because * of space limitations -- ignore. */ MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering of future message of size %" MBEDTLS_PRINTF_SIZET " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET " (already %" MBEDTLS_PRINTF_SIZET " bytes buffered) -- ignore\n", msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, hs->buffering.total_bytes_buffered)); goto exit; } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering of future message of size %" MBEDTLS_PRINTF_SIZET " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET " (already %" MBEDTLS_PRINTF_SIZET " bytes buffered) -- attempt to make space by freeing buffered future messages\n", msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, hs->buffering.total_bytes_buffered)); } if (ssl_buffer_make_space(ssl, reassembly_buf_sz) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("Reassembly of next message of size %" MBEDTLS_PRINTF_SIZET " (%" MBEDTLS_PRINTF_SIZET " with bitmap) would exceed" " the compile-time limit %" MBEDTLS_PRINTF_SIZET " (already %" MBEDTLS_PRINTF_SIZET " bytes buffered) -- fail\n", msg_len, reassembly_buf_sz, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, hs->buffering.total_bytes_buffered)); ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; goto exit; } } MBEDTLS_SSL_DEBUG_MSG(2, ("initialize reassembly, total length = %" MBEDTLS_PRINTF_SIZET, msg_len)); hs_buf->data = mbedtls_calloc(1, reassembly_buf_sz); if (hs_buf->data == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } hs_buf->data_len = reassembly_buf_sz; /* Prepare final header: copy msg_type, length and message_seq, * then add standardised fragment_offset and fragment_length */ memcpy(hs_buf->data, ssl->in_msg, 6); memset(hs_buf->data + 6, 0, 3); memcpy(hs_buf->data + 9, hs_buf->data + 1, 3); hs_buf->is_valid = 1; hs->buffering.total_bytes_buffered += reassembly_buf_sz; } else { /* Make sure msg_type and length are consistent */ if (memcmp(hs_buf->data, ssl->in_msg, 4) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("Fragment header mismatch - ignore")); /* Ignore */ goto exit; } } if (!hs_buf->is_complete) { size_t frag_len, frag_off; unsigned char * const msg = hs_buf->data + 12; /* * Check and copy current fragment */ /* Validation of header fields already done in * mbedtls_ssl_prepare_handshake_record(). */ frag_off = ssl_get_hs_frag_off(ssl); frag_len = ssl_get_hs_frag_len(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("adding fragment, offset = %" MBEDTLS_PRINTF_SIZET ", length = %" MBEDTLS_PRINTF_SIZET, frag_off, frag_len)); memcpy(msg + frag_off, ssl->in_msg + 12, frag_len); if (hs_buf->is_fragmented) { unsigned char * const bitmask = msg + msg_len; ssl_bitmask_set(bitmask, frag_off, frag_len); hs_buf->is_complete = (ssl_bitmask_check(bitmask, msg_len) == 0); } else { hs_buf->is_complete = 1; } MBEDTLS_SSL_DEBUG_MSG(2, ("message %scomplete", hs_buf->is_complete ? "" : "not yet ")); } break; } default: /* We don't buffer other types of messages. */ break; } exit: MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_buffer_message")); return ret; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_consume_current_message(mbedtls_ssl_context *ssl) { /* * Consume last content-layer message and potentially * update in_msglen which keeps track of the contents' * consumption state. * * (1) Handshake messages: * Remove last handshake message, move content * and adapt in_msglen. * * (2) Alert messages: * Consume whole record content, in_msglen = 0. * * (3) Change cipher spec: * Consume whole record content, in_msglen = 0. * * (4) Application data: * Don't do anything - the record layer provides * the application data as a stream transport * and consumes through mbedtls_ssl_read only. * */ /* Case (1): Handshake messages */ if (ssl->in_hslen != 0) { /* Hard assertion to be sure that no application data * is in flight, as corrupting ssl->in_msglen during * ssl->in_offt != NULL is fatal. */ if (ssl->in_offt != NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * Get next Handshake message in the current record */ /* Notes: * (1) in_hslen is not necessarily the size of the * current handshake content: If DTLS handshake * fragmentation is used, that's the fragment * size instead. Using the total handshake message * size here is faulty and should be changed at * some point. * (2) While it doesn't seem to cause problems, one * has to be very careful not to assume that in_hslen * is always <= in_msglen in a sensible communication. * Again, it's wrong for DTLS handshake fragmentation. * The following check is therefore mandatory, and * should not be treated as a silently corrected assertion. * Additionally, ssl->in_hslen might be arbitrarily out of * bounds after handling a DTLS message with an unexpected * sequence number, see mbedtls_ssl_prepare_handshake_record. */ if (ssl->in_hslen < ssl->in_msglen) { ssl->in_msglen -= ssl->in_hslen; memmove(ssl->in_msg, ssl->in_msg + ssl->in_hslen, ssl->in_msglen); MBEDTLS_SSL_DEBUG_BUF(4, "remaining content in record", ssl->in_msg, ssl->in_msglen); } else { ssl->in_msglen = 0; } ssl->in_hslen = 0; } /* Case (4): Application data */ else if (ssl->in_offt != NULL) { return 0; } /* Everything else (CCS & Alerts) */ else { ssl->in_msglen = 0; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_record_is_in_progress(mbedtls_ssl_context *ssl) { if (ssl->in_msglen > 0) { return 1; } return 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) static void ssl_free_buffered_record(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; if (hs == NULL) { return; } if (hs->buffering.future_record.data != NULL) { hs->buffering.total_bytes_buffered -= hs->buffering.future_record.len; mbedtls_free(hs->buffering.future_record.data); hs->buffering.future_record.data = NULL; } } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_record(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; unsigned char *rec; size_t rec_len; unsigned rec_epoch; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t in_buf_len = ssl->in_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; #endif if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 0; } if (hs == NULL) { return 0; } rec = hs->buffering.future_record.data; rec_len = hs->buffering.future_record.len; rec_epoch = hs->buffering.future_record.epoch; if (rec == NULL) { return 0; } /* Only consider loading future records if the * input buffer is empty. */ if (ssl_next_record_is_in_datagram(ssl) == 1) { return 0; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_load_buffered_record")); if (rec_epoch != ssl->in_epoch) { MBEDTLS_SSL_DEBUG_MSG(2, ("Buffered record not from current epoch.")); goto exit; } MBEDTLS_SSL_DEBUG_MSG(2, ("Found buffered record from current epoch - load")); /* Double-check that the record is not too large */ if (rec_len > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(ssl->in_hdr, rec, rec_len); ssl->in_left = rec_len; ssl->next_record_offset = 0; ssl_free_buffered_record(ssl); exit: MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_load_buffered_record")); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_future_record(mbedtls_ssl_context *ssl, mbedtls_record const *rec) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; /* Don't buffer future records outside handshakes. */ if (hs == NULL) { return 0; } /* Only buffer handshake records (we are only interested * in Finished messages). */ if (rec->type != MBEDTLS_SSL_MSG_HANDSHAKE) { return 0; } /* Don't buffer more than one future epoch record. */ if (hs->buffering.future_record.data != NULL) { return 0; } /* Don't buffer record if there's not enough buffering space remaining. */ if (rec->buf_len > (MBEDTLS_SSL_DTLS_MAX_BUFFERING - hs->buffering.total_bytes_buffered)) { MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET " (already %" MBEDTLS_PRINTF_SIZET " bytes buffered) -- ignore\n", rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, hs->buffering.total_bytes_buffered)); return 0; } /* Buffer record */ MBEDTLS_SSL_DEBUG_MSG(2, ("Buffer record from epoch %u", ssl->in_epoch + 1U)); MBEDTLS_SSL_DEBUG_BUF(3, "Buffered record", rec->buf, rec->buf_len); /* ssl_parse_record_header() only considers records * of the next epoch as candidates for buffering. */ hs->buffering.future_record.epoch = ssl->in_epoch + 1; hs->buffering.future_record.len = rec->buf_len; hs->buffering.future_record.data = mbedtls_calloc(1, hs->buffering.future_record.len); if (hs->buffering.future_record.data == NULL) { /* If we run out of RAM trying to buffer a * record from the next epoch, just ignore. */ return 0; } memcpy(hs->buffering.future_record.data, rec->buf, rec->buf_len); hs->buffering.total_bytes_buffered += rec->buf_len; return 0; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_next_record(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_record rec; #if defined(MBEDTLS_SSL_PROTO_DTLS) /* We might have buffered a future record; if so, * and if the epoch matches now, load it. * On success, this call will set ssl->in_left to * the length of the buffered record, so that * the calls to ssl_fetch_input() below will * essentially be no-ops. */ ret = ssl_load_buffered_record(ssl); if (ret != 0) { return ret; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* Ensure that we have enough space available for the default form * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS, * with no space for CIDs counted in). */ ret = mbedtls_ssl_fetch_input(ssl, mbedtls_ssl_in_hdr_len(ssl)); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); return ret; } ret = ssl_parse_record_header(ssl, ssl->in_hdr, ssl->in_left, &rec); if (ret != 0) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { if (ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) { ret = ssl_buffer_future_record(ssl, &rec); if (ret != 0) { return ret; } /* Fall through to handling of unexpected records */ ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) { #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) /* Reset in pointers to default state for TLS/DTLS records, * assuming no CID and no offset between record content and * record plaintext. */ mbedtls_ssl_update_in_pointers(ssl); /* Setup internal message pointers from record structure. */ ssl->in_msgtype = rec.type; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->in_len = ssl->in_cid + rec.cid_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->in_iv = ssl->in_msg = ssl->in_len + 2; ssl->in_msglen = rec.data_len; ret = ssl_check_client_reconnect(ssl); MBEDTLS_SSL_DEBUG_RET(2, "ssl_check_client_reconnect", ret); if (ret != 0) { return ret; } #endif /* Skip unexpected record (but not whole datagram) */ ssl->next_record_offset = rec.buf_len; MBEDTLS_SSL_DEBUG_MSG(1, ("discarding unexpected record " "(header)")); } else { /* Skip invalid record and the rest of the datagram */ ssl->next_record_offset = 0; ssl->in_left = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("discarding invalid record " "(header)")); } /* Get next record */ return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } else #endif { return ret; } } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Remember offset of next record within datagram. */ ssl->next_record_offset = rec.buf_len; if (ssl->next_record_offset < ssl->in_left) { MBEDTLS_SSL_DEBUG_MSG(3, ("more than one record within datagram")); } } else #endif { /* * Fetch record contents from underlying transport. */ ret = mbedtls_ssl_fetch_input(ssl, rec.buf_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); return ret; } ssl->in_left = 0; } /* * Decrypt record contents. */ if ((ret = ssl_prepare_record_content(ssl, &rec)) != 0) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Silently discard invalid records */ if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) { /* Except when waiting for Finished as a bad mac here * probably means something went wrong in the handshake * (eg wrong psk used, mitm downgrade attempt, etc.) */ if (ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || ssl->state == MBEDTLS_SSL_SERVER_FINISHED) { #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC); } #endif return ret; } if (ssl->conf->badmac_limit != 0 && ++ssl->badmac_seen >= ssl->conf->badmac_limit) { MBEDTLS_SSL_DEBUG_MSG(1, ("too many records with bad MAC")); return MBEDTLS_ERR_SSL_INVALID_MAC; } /* As above, invalid records cause * dismissal of the whole datagram. */ ssl->next_record_offset = 0; ssl->in_left = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("discarding invalid record (mac)")); return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } return ret; } else #endif { /* Error out (and send alert) on invalid records */ #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC); } #endif return ret; } } /* Reset in pointers to default state for TLS/DTLS records, * assuming no CID and no offset between record content and * record plaintext. */ mbedtls_ssl_update_in_pointers(ssl); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->in_len = ssl->in_cid + rec.cid_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->in_iv = ssl->in_len + 2; /* The record content type may change during decryption, * so re-read it. */ ssl->in_msgtype = rec.type; /* Also update the input buffer, because unfortunately * the server-side ssl_parse_client_hello() reparses the * record header when receiving a ClientHello initiating * a renegotiation. */ ssl->in_hdr[0] = rec.type; ssl->in_msg = rec.buf + rec.data_offset; ssl->in_msglen = rec.data_len; MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->in_len, 0); return 0; } int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * Handle particular types of records */ if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) { if ((ret = mbedtls_ssl_prepare_handshake_record(ssl)) != 0) { return ret; } } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { if (ssl->in_msglen != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET, ssl->in_msglen)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } if (ssl->in_msg[0] != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid CCS message, content: %02x", ssl->in_msg[0])); return MBEDTLS_ERR_SSL_INVALID_RECORD; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC) { if (ssl->handshake == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("dropping ChangeCipherSpec outside handshake")); return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } MBEDTLS_SSL_DEBUG_MSG(1, ("received out-of-order ChangeCipherSpec - remember")); return MBEDTLS_ERR_SSL_EARLY_MESSAGE; } #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) MBEDTLS_SSL_DEBUG_MSG(1, ("Ignore ChangeCipherSpec in TLS 1.3 compatibility mode")); return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; #else MBEDTLS_SSL_DEBUG_MSG(1, ("ChangeCipherSpec invalid in TLS 1.3 without compatibility mode")); return MBEDTLS_ERR_SSL_INVALID_RECORD; #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT) { if (ssl->in_msglen != 2) { /* Note: Standard allows for more than one 2 byte alert to be packed in a single message, but Mbed TLS doesn't currently support this. */ MBEDTLS_SSL_DEBUG_MSG(1, ("invalid alert message, len: %" MBEDTLS_PRINTF_SIZET, ssl->in_msglen)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } MBEDTLS_SSL_DEBUG_MSG(2, ("got an alert message, type: [%u:%u]", ssl->in_msg[0], ssl->in_msg[1])); /* * Ignore non-fatal alerts, except close_notify and no_renegotiation */ if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL) { MBEDTLS_SSL_DEBUG_MSG(1, ("is a fatal alert message (msg %d)", ssl->in_msg[1])); return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE; } if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY) { MBEDTLS_SSL_DEBUG_MSG(2, ("is a close notify message")); return MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY; } #if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION) { MBEDTLS_SSL_DEBUG_MSG(2, ("is a no renegotiation alert")); /* Will be handled when trying to parse ServerHello */ return 0; } #endif /* Silently ignore: fetch new message */ return MBEDTLS_ERR_SSL_NON_FATAL; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Drop unexpected ApplicationData records, * except at the beginning of renegotiations */ if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && mbedtls_ssl_is_handshake_over(ssl) == 0 #if defined(MBEDTLS_SSL_RENEGOTIATION) && !(ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->state == MBEDTLS_SSL_SERVER_HELLO) #endif ) { MBEDTLS_SSL_DEBUG_MSG(1, ("dropping unexpected ApplicationData")); return MBEDTLS_ERR_SSL_NON_FATAL; } if (ssl->handshake != NULL && mbedtls_ssl_is_handshake_over(ssl) == 1) { mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl); } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ return 0; } int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl) { return mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); } int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, unsigned char level, unsigned char message) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->out_left != 0) { return mbedtls_ssl_flush_output(ssl); } MBEDTLS_SSL_DEBUG_MSG(2, ("=> send alert message")); MBEDTLS_SSL_DEBUG_MSG(3, ("send alert level=%u message=%u", level, message)); ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; ssl->out_msglen = 2; ssl->out_msg[0] = level; ssl->out_msg[1] = message; if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= send alert message")); return 0; } int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec")); ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; ssl->out_msglen = 1; ssl->out_msg[0] = 1; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec")); return 0; } int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse change cipher spec")); if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad change cipher spec message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* CCS records are only accepted if they have length 1 and content '1', * so we don't need to check this here. */ /* * Switch to our negotiated transform and session parameters for inbound * data. */ MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for inbound data")); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) ssl->transform_in = ssl->transform_negotiate; #endif ssl->session_in = ssl->session_negotiate; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) mbedtls_ssl_dtls_replay_reset(ssl); #endif /* Increment epoch */ if (++ssl->in_epoch == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap")); /* This is highly unlikely to happen for legitimate reasons, so treat it as an attack and don't send an alert. */ return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; } } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); mbedtls_ssl_update_in_pointers(ssl); ssl->state++; MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse change cipher spec")); return 0; } /* Once ssl->out_hdr as the address of the beginning of the * next outgoing record is set, deduce the other pointers. * * Note: For TLS, we save the implicit record sequence number * (entering MAC computation) in the 8 bytes before ssl->out_hdr, * and the caller has to make sure there's space for this. */ static size_t ssl_transform_get_explicit_iv_len( mbedtls_ssl_transform const *transform) { return transform->ivlen - transform->fixed_ivlen; } void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->out_ctr = ssl->out_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->out_cid = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; ssl->out_len = ssl->out_cid; if (transform != NULL) { ssl->out_len += transform->out_cid_len; } #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->out_len = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->out_iv = ssl->out_len + 2; } else #endif { ssl->out_len = ssl->out_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->out_cid = ssl->out_len; #endif ssl->out_iv = ssl->out_hdr + 5; } ssl->out_msg = ssl->out_iv; /* Adjust out_msg to make space for explicit IV, if used. */ if (transform != NULL) { ssl->out_msg += ssl_transform_get_explicit_iv_len(transform); } } /* Once ssl->in_hdr as the address of the beginning of the * next incoming record is set, deduce the other pointers. * * Note: For TLS, we save the implicit record sequence number * (entering MAC computation) in the 8 bytes before ssl->in_hdr, * and the caller has to make sure there's space for this. */ void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl) { /* This function sets the pointers to match the case * of unprotected TLS/DTLS records, with both ssl->in_iv * and ssl->in_msg pointing to the beginning of the record * content. * * When decrypting a protected record, ssl->in_msg * will be shifted to point to the beginning of the * record plaintext. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* This sets the header pointers to match records * without CID. When we receive a record containing * a CID, the fields are shifted accordingly in * ssl_parse_record_header(). */ ssl->in_ctr = ssl->in_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->in_cid = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; ssl->in_len = ssl->in_cid; /* Default: no CID */ #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->in_len = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->in_iv = ssl->in_len + 2; } else #endif { ssl->in_ctr = ssl->in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; ssl->in_len = ssl->in_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->in_cid = ssl->in_len; #endif ssl->in_iv = ssl->in_hdr + 5; } /* This will be adjusted at record decryption time. */ ssl->in_msg = ssl->in_iv; } /* * Setup an SSL context */ void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl) { /* Set the incoming and outgoing record pointers. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->out_hdr = ssl->out_buf; ssl->in_hdr = ssl->in_buf; } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { ssl->out_ctr = ssl->out_buf; ssl->out_hdr = ssl->out_buf + 8; ssl->in_hdr = ssl->in_buf + 8; } /* Derive other internal pointers. */ mbedtls_ssl_update_out_pointers(ssl, NULL /* no transform enabled */); mbedtls_ssl_update_in_pointers(ssl); } /* * SSL get accessors */ size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl) { return ssl->in_offt == NULL ? 0 : ssl->in_msglen; } int mbedtls_ssl_check_pending(const mbedtls_ssl_context *ssl) { /* * Case A: We're currently holding back * a message for further processing. */ if (ssl->keep_current_message == 1) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: record held back for processing")); return 1; } /* * Case B: Further records are pending in the current datagram. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->in_left > ssl->next_record_offset) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: more records within current datagram")); return 1; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Case C: A handshake message is being processed. */ if (ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: more handshake messages within current record")); return 1; } /* * Case D: An application data message is being processed */ if (ssl->in_offt != NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: application data record is being processed")); return 1; } /* * In all other cases, the rest of the message can be dropped. * As in ssl_get_next_record, this needs to be adapted if * we implement support for multiple alerts in single records. */ MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: nothing pending")); return 0; } int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl) { size_t transform_expansion = 0; const mbedtls_ssl_transform *transform = ssl->transform_out; unsigned block_size; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t key_type; #endif /* MBEDTLS_USE_PSA_CRYPTO */ size_t out_hdr_len = mbedtls_ssl_out_hdr_len(ssl); if (transform == NULL) { return (int) out_hdr_len; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if (transform->psa_alg == PSA_ALG_GCM || transform->psa_alg == PSA_ALG_CCM || transform->psa_alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8) || transform->psa_alg == PSA_ALG_CHACHA20_POLY1305 || transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) { transform_expansion = transform->minlen; } else if (transform->psa_alg == PSA_ALG_CBC_NO_PADDING) { (void) psa_get_key_attributes(transform->psa_key_enc, &attr); key_type = psa_get_key_type(&attr); block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type); /* Expansion due to the addition of the MAC. */ transform_expansion += transform->maclen; /* Expansion due to the addition of CBC padding; * Theoretically up to 256 bytes, but we never use * more than the block size of the underlying cipher. */ transform_expansion += block_size; /* For TLS 1.2 or higher, an explicit IV is added * after the record header. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) transform_expansion += block_size; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ } else { MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported psa_alg spotted in mbedtls_ssl_get_record_expansion()")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else switch (mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc)) { case MBEDTLS_MODE_GCM: case MBEDTLS_MODE_CCM: case MBEDTLS_MODE_CHACHAPOLY: case MBEDTLS_MODE_STREAM: transform_expansion = transform->minlen; break; case MBEDTLS_MODE_CBC: block_size = mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc); /* Expansion due to the addition of the MAC. */ transform_expansion += transform->maclen; /* Expansion due to the addition of CBC padding; * Theoretically up to 256 bytes, but we never use * more than the block size of the underlying cipher. */ transform_expansion += block_size; /* For TLS 1.2 or higher, an explicit IV is added * after the record header. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) transform_expansion += block_size; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ break; default: MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (transform->out_cid_len != 0) { transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ return (int) (out_hdr_len + transform_expansion); } #if defined(MBEDTLS_SSL_RENEGOTIATION) /* * Check record counters and renegotiate if they're above the limit. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_ctr_renegotiate(mbedtls_ssl_context *ssl) { size_t ep_len = mbedtls_ssl_ep_len(ssl); int in_ctr_cmp; int out_ctr_cmp; if (mbedtls_ssl_is_handshake_over(ssl) == 0 || ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED) { return 0; } in_ctr_cmp = memcmp(ssl->in_ctr + ep_len, &ssl->conf->renego_period[ep_len], MBEDTLS_SSL_SEQUENCE_NUMBER_LEN - ep_len); out_ctr_cmp = memcmp(&ssl->cur_out_ctr[ep_len], &ssl->conf->renego_period[ep_len], sizeof(ssl->cur_out_ctr) - ep_len); if (in_ctr_cmp <= 0 && out_ctr_cmp <= 0) { return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("record counter limit reached: renegotiate")); return mbedtls_ssl_renegotiate(ssl); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(MBEDTLS_SSL_CLI_C) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_is_new_session_ticket(mbedtls_ssl_context *ssl) { if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) || (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET)) { return 0; } return 1; } #endif /* MBEDTLS_SSL_CLI_C */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(3, ("received post-handshake message")); #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { if (ssl_tls13_is_new_session_ticket(ssl)) { #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received")); if (mbedtls_ssl_conf_is_signal_new_session_tickets_enabled(ssl->conf) == MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED) { ssl->keep_current_message = 1; mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); return MBEDTLS_ERR_SSL_WANT_READ; } else { MBEDTLS_SSL_DEBUG_MSG(3, ("Ignoring NewSessionTicket, handling disabled.")); return 0; } #else MBEDTLS_SSL_DEBUG_MSG(3, ("Ignoring NewSessionTicket, not supported.")); return 0; #endif } } #endif /* MBEDTLS_SSL_CLI_C */ /* Fail in all other cases. */ return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* This function is called from mbedtls_ssl_read() when a handshake message is * received after the initial handshake. In this context, handshake messages * may only be sent for the purpose of initiating renegotiations. * * This function is introduced as a separate helper since the handling * of post-handshake handshake messages changes significantly in TLS 1.3, * and having a helper function allows to distinguish between TLS <= 1.2 and * TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read(). */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * - For client-side, expect SERVER_HELLO_REQUEST. * - For server-side, expect CLIENT_HELLO. * - Fail (TLS) or silently drop record (DTLS) in other cases. */ #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && (ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl))) { MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not HelloRequest)")); /* With DTLS, drop the packet (probably from last handshake) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 0; } #endif return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) { MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not ClientHello)")); /* With DTLS, drop the packet (probably from last handshake) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 0; } #endif return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_RENEGOTIATION) /* Determine whether renegotiation attempt should be accepted */ if (!(ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION))) { /* * Accept renegotiation request */ /* DTLS clients need to know renego is server-initiated */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; } #endif ret = mbedtls_ssl_start_renegotiation(ssl); if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", ret); return ret; } } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ { /* * Refuse renegotiation */ MBEDTLS_SSL_DEBUG_MSG(3, ("refusing renegotiation, sending alert")); if ((ret = mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_WARNING, MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION)) != 0) { return ret; } } return 0; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) { /* Check protocol version and dispatch accordingly. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { return ssl_tls13_handle_hs_message_post_handshake(ssl); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) { return ssl_tls12_handle_hs_message_post_handshake(ssl); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* Should never happen */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * brief Read at most 'len' application data bytes from the input * buffer. * * param ssl SSL context: * - First byte of application data not read yet in the input * buffer located at address `in_offt`. * - The number of bytes of data not read yet is `in_msglen`. * param buf buffer that will hold the data * param len maximum number of bytes to read * * note The function updates the fields `in_offt` and `in_msglen` * according to the number of bytes read. * * return The number of bytes read. */ static int ssl_read_application_data( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) { size_t n = (len < ssl->in_msglen) ? len : ssl->in_msglen; if (len != 0) { memcpy(buf, ssl->in_offt, n); ssl->in_msglen -= n; } /* Zeroising the plaintext buffer to erase unused application data from the memory. */ mbedtls_platform_zeroize(ssl->in_offt, n); if (ssl->in_msglen == 0) { /* all bytes consumed */ ssl->in_offt = NULL; ssl->keep_current_message = 0; } else { /* more data available */ ssl->in_offt += n; } return (int) n; } /* * Receive application data decrypted from the SSL layer */ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> read")); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } if (ssl->handshake != NULL && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { return ret; } } } #endif /* * Check if renegotiation is necessary and/or handshake is * in process. If yes, perform/continue, and fall through * if an unexpected packet is received while the client * is waiting for the ServerHello. * * (There is no equivalent to the last condition on * the server-side as it is not treated as within * a handshake while waiting for the ClientHello * after a renegotiation request.) */ #if defined(MBEDTLS_SSL_RENEGOTIATION) ret = ssl_check_ctr_renegotiate(ssl); if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_check_ctr_renegotiate", ret); return ret; } #endif if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { ret = mbedtls_ssl_handshake(ssl); if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } } /* Loop as long as no application data record is available */ while (ssl->in_offt == NULL) { /* Start timer if not already running */ if (ssl->f_get_timer != NULL && ssl->f_get_timer(ssl->p_timer) == -1) { mbedtls_ssl_set_timer(ssl, ssl->conf->read_timeout); } if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { if (ret == MBEDTLS_ERR_SSL_CONN_EOF) { return 0; } MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msglen == 0 && ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) { /* * OpenSSL sends empty messages to randomize the IV */ if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { if (ret == MBEDTLS_ERR_SSL_CONN_EOF) { return 0; } MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) { ret = ssl_handle_hs_message_post_handshake(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_handle_hs_message_post_handshake", ret); return ret; } /* At this point, we don't know whether the renegotiation triggered * by the post-handshake message has been completed or not. The cases * to consider are the following: * 1) The renegotiation is complete. In this case, no new record * has been read yet. * 2) The renegotiation is incomplete because the client received * an application data record while awaiting the ServerHello. * 3) The renegotiation is incomplete because the client received * a non-handshake, non-application data message while awaiting * the ServerHello. * * In each of these cases, looping will be the proper action: * - For 1), the next iteration will read a new record and check * if it's application data. * - For 2), the loop condition isn't satisfied as application data * is present, hence continue is the same as break * - For 3), the loop condition is satisfied and read_record * will re-deliver the message that was held back by the client * when expecting the ServerHello. */ continue; } #if defined(MBEDTLS_SSL_RENEGOTIATION) else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { if (ssl->conf->renego_max_records >= 0) { if (++ssl->renego_records_seen > ssl->conf->renego_max_records) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation requested, " "but not honored by client")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } } } #endif /* MBEDTLS_SSL_RENEGOTIATION */ /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ if (ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT) { MBEDTLS_SSL_DEBUG_MSG(2, ("ignoring non-fatal non-closure alert")); return MBEDTLS_ERR_SSL_WANT_READ; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad application data message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } ssl->in_offt = ssl->in_msg; /* We're going to return something now, cancel timer, * except if handshake (renegotiation) is in progress */ if (mbedtls_ssl_is_handshake_over(ssl) == 1) { mbedtls_ssl_set_timer(ssl, 0); } #if defined(MBEDTLS_SSL_PROTO_DTLS) /* If we requested renego but received AppData, resend HelloRequest. * Do it now, after setting in_offt, to avoid taking this branch * again if ssl_write_hello_request() returns WANT_WRITE */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { if ((ret = mbedtls_ssl_resend_hello_request(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend_hello_request", ret); return ret; } } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ } ret = ssl_read_application_data(ssl, buf, len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= read")); return ret; } #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) { if (ssl == NULL || (ssl->conf == NULL)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * The server may receive early data only while waiting for the End of * Early Data handshake message. */ if ((ssl->state != MBEDTLS_SSL_END_OF_EARLY_DATA) || (ssl->in_offt == NULL)) { return MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA; } return ssl_read_application_data(ssl, buf, len); } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA */ /* * Send application data to be encrypted by the SSL layer, taking care of max * fragment length and buffer size. * * According to RFC 5246 Section 6.2.1: * * Zero-length fragments of Application data MAY be sent as they are * potentially useful as a traffic analysis countermeasure. * * Therefore, it is possible that the input message length is 0 and the * corresponding return code is 0 on success. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_real(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = mbedtls_ssl_get_max_out_record_payload(ssl); const size_t max_len = (size_t) ret; if (ret < 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_max_out_record_payload", ret); return ret; } if (len > max_len) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("fragment larger than the (negotiated) " "maximum fragment length: %" MBEDTLS_PRINTF_SIZET " > %" MBEDTLS_PRINTF_SIZET, len, max_len)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } else #endif len = max_len; } if (ssl->out_left != 0) { /* * The user has previously tried to send the data and * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially * written. In this case, we expect the high-level write function * (e.g. mbedtls_ssl_write()) to be called with the same parameters */ if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret); return ret; } } else { /* * The user is trying to send a message the first time, so we need to * copy the data into the internal buffers and setup the data structure * to keep track of partial writes */ ssl->out_msglen = len; ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; if (len > 0) { memcpy(ssl->out_msg, buf, len); } if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret); return ret; } } return (int) len; } /* * Write application data (public-facing wrapper) */ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write")); if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_SSL_RENEGOTIATION) if ((ret = ssl_check_ctr_renegotiate(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_check_ctr_renegotiate", ret); return ret; } #endif if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } } ret = ssl_write_real(ssl, buf, len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write")); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const struct mbedtls_ssl_config *conf; uint32_t remaining; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data")); if (ssl == NULL || (conf = ssl->conf) == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) || (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } /* * If we are at the beginning of the handshake, the early data state being * equal to MBEDTLS_SSL_EARLY_DATA_STATE_IDLE or * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT advance the handshake just * enough to be able to send early data if possible. That way, we can * guarantee that when starting the handshake with this function we will * send at least one record of early data. Note that when the state is * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT and not yet * MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, we cannot send early data * as the early data outbound transform has not been set as we may have to * first send a dummy CCS in clear. */ if ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) || (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) { while ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) || (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) { ret = mbedtls_ssl_handshake_step(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret); return ret; } ret = mbedtls_ssl_flush_output(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret); return ret; } } remaining = ssl->session_negotiate->max_early_data_size; } else { /* * If we are past the point where we can send early data or we have * already reached the maximum early data size, return immediatly. * Otherwise, progress the handshake as much as possible to not delay * it too much. If we reach a point where we can still send early data, * then we will send some. */ if ((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) && (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } remaining = ssl->session_negotiate->max_early_data_size - ssl->total_early_data_size; if (remaining == 0) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } ret = mbedtls_ssl_handshake(ssl); if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } } if (((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) && (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) || (remaining == 0)) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } if (len > remaining) { len = remaining; } ret = ssl_write_real(ssl, buf, len); if (ret >= 0) { ssl->total_early_data_size += ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, ret=%d", ret)); return ret; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ /* * Notify the peer that the connection is being closed */ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> write close notify")); if (mbedtls_ssl_is_handshake_over(ssl) == 1) { if ((ret = mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_WARNING, MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_send_alert_message", ret); return ret; } } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write close notify")); return 0; } void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform) { if (transform == NULL) { return; } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_destroy_key(transform->psa_key_enc); psa_destroy_key(transform->psa_key_dec); #else mbedtls_cipher_free(&transform->cipher_ctx_enc); mbedtls_cipher_free(&transform->cipher_ctx_dec); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_destroy_key(transform->psa_mac_enc); psa_destroy_key(transform->psa_mac_dec); #else mbedtls_md_free(&transform->md_ctx_enc); mbedtls_md_free(&transform->md_ctx_dec); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif mbedtls_platform_zeroize(transform, sizeof(mbedtls_ssl_transform)); } void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform) { ssl->transform_in = transform; memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); } void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform) { ssl->transform_out = transform; memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); } #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl) { unsigned offset; mbedtls_ssl_handshake_params * const hs = ssl->handshake; if (hs == NULL) { return; } ssl_free_buffered_record(ssl); for (offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) { ssl_buffering_free_slot(ssl, offset); } } static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl, uint8_t slot) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; if (slot >= MBEDTLS_SSL_MAX_BUFFERED_HS) { return; } if (hs_buf->is_valid == 1) { hs->buffering.total_bytes_buffered -= hs_buf->data_len; mbedtls_zeroize_and_free(hs_buf->data, hs_buf->data_len); memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer)); } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Convert version numbers to/from wire format * and, for DTLS, to/from TLS equivalent. * * For TLS this is the identity. * For DTLS, map as follows, then use 1's complement (v -> ~v): * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) * DTLS 1.0 is stored as TLS 1.1 internally */ void mbedtls_ssl_write_version(unsigned char version[2], int transport, mbedtls_ssl_protocol_version tls_version) { uint16_t tls_version_formatted; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { tls_version_formatted = ~(tls_version - (tls_version == 0x0302 ? 0x0202 : 0x0201)); } else #else ((void) transport); #endif { tls_version_formatted = (uint16_t) tls_version; } MBEDTLS_PUT_UINT16_BE(tls_version_formatted, version, 0); } uint16_t mbedtls_ssl_read_version(const unsigned char version[2], int transport) { uint16_t tls_version = MBEDTLS_GET_UINT16_BE(version, 0); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { tls_version = ~(tls_version - (tls_version == 0xfeff ? 0x0202 : 0x0201)); } #else ((void) transport); #endif return tls_version; } /* * Send pending fatal alert. * 0, No alert message. * !0, if mbedtls_ssl_send_alert_message() returned in error, the error code it * returned, ssl->alert_reason otherwise. */ int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl) { int ret; /* No pending alert, return success*/ if (ssl->send_alert == 0) { return 0; } ret = mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, ssl->alert_type); /* If mbedtls_ssl_send_alert_message() returned with MBEDTLS_ERR_SSL_WANT_WRITE, * do not clear the alert to be able to send it later. */ if (ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ssl->send_alert = 0; } if (ret != 0) { return ret; } return ssl->alert_reason; } /* * Set pending fatal alert flag. */ void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl, unsigned char alert_type, int alert_reason) { ssl->send_alert = 1; ssl->alert_type = alert_type; ssl->alert_reason = alert_reason; } #endif /* MBEDTLS_SSL_TLS_C */ webfakes/src/mbedtls/library/debug.c0000644000176200001440000003435414740737024017201 0ustar liggesusers/* * Debugging routines * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_DEBUG_C) #include "mbedtls/platform.h" #include "debug_internal.h" #include "mbedtls/error.h" #include #include #include /* DEBUG_BUF_SIZE must be at least 2 */ #define DEBUG_BUF_SIZE 512 static int debug_threshold = 0; void mbedtls_debug_set_threshold(int threshold) { debug_threshold = threshold; } /* * All calls to f_dbg must be made via this function */ static inline void debug_send_line(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *str) { /* * If in a threaded environment, we need a thread identifier. * Since there is no portable way to get one, use the address of the ssl * context instead, as it shouldn't be shared between threads. */ #if defined(MBEDTLS_THREADING_C) char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ mbedtls_snprintf(idstr, sizeof(idstr), "%p: %s", (void *) ssl, str); ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, idstr); #else ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, str); #endif } MBEDTLS_PRINTF_ATTRIBUTE(5, 6) void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *format, ...) { va_list argp; char str[DEBUG_BUF_SIZE]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_STATIC_ASSERT(DEBUG_BUF_SIZE >= 2, "DEBUG_BUF_SIZE too small"); if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } va_start(argp, format); ret = mbedtls_vsnprintf(str, DEBUG_BUF_SIZE, format, argp); va_end(argp); if (ret < 0) { ret = 0; } else { if (ret >= DEBUG_BUF_SIZE - 1) { ret = DEBUG_BUF_SIZE - 2; } } str[ret] = '\n'; str[ret + 1] = '\0'; debug_send_line(ssl, level, file, line, str); } void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, int ret) { char str[DEBUG_BUF_SIZE]; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } /* * With non-blocking I/O and examples that just retry immediately, * the logs would be quickly flooded with WANT_READ, so ignore that. * Don't ignore WANT_WRITE however, since it is usually rare. */ if (ret == MBEDTLS_ERR_SSL_WANT_READ) { return; } mbedtls_snprintf(str, sizeof(str), "%s() returned %d (-0x%04x)\n", text, ret, (unsigned int) -ret); debug_send_line(ssl, level, file, line, str); } void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const unsigned char *buf, size_t len) { char str[DEBUG_BUF_SIZE]; char txt[17]; size_t i, idx = 0; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } mbedtls_snprintf(str + idx, sizeof(str) - idx, "dumping '%s' (%u bytes)\n", text, (unsigned int) len); debug_send_line(ssl, level, file, line, str); memset(txt, 0, sizeof(txt)); for (i = 0; i < len; i++) { if (i >= 4096) { break; } if (i % 16 == 0) { if (i > 0) { mbedtls_snprintf(str + idx, sizeof(str) - idx, " %s\n", txt); debug_send_line(ssl, level, file, line, str); idx = 0; memset(txt, 0, sizeof(txt)); } idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "%04x: ", (unsigned int) i); } idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", (unsigned int) buf[i]); txt[i % 16] = (buf[i] > 31 && buf[i] < 127) ? buf[i] : '.'; } if (len > 0) { for (/* i = i */; i % 16 != 0; i++) { idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " "); } mbedtls_snprintf(str + idx, sizeof(str) - idx, " %s\n", txt); debug_send_line(ssl, level, file, line, str); } } #if defined(MBEDTLS_ECP_LIGHT) void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_ecp_point *X) { char str[DEBUG_BUF_SIZE]; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } mbedtls_snprintf(str, sizeof(str), "%s(X)", text); mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->X); mbedtls_snprintf(str, sizeof(str), "%s(Y)", text); mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->Y); } #endif /* MBEDTLS_ECP_LIGHT */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static void mbedtls_debug_print_ec_coord(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const unsigned char *buf, size_t len) { char str[DEBUG_BUF_SIZE]; size_t i, idx = 0; mbedtls_snprintf(str + idx, sizeof(str) - idx, "value of '%s' (%u bits) is:\n", text, (unsigned int) len * 8); debug_send_line(ssl, level, file, line, str); for (i = 0; i < len; i++) { if (i >= 4096) { break; } if (i % 16 == 0) { if (i > 0) { mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); debug_send_line(ssl, level, file, line, str); idx = 0; } } idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", (unsigned int) buf[i]); } if (len > 0) { for (/* i = i */; i % 16 != 0; i++) { idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " "); } mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); debug_send_line(ssl, level, file, line, str); } } void mbedtls_debug_print_psa_ec(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_pk_context *pk) { char str[DEBUG_BUF_SIZE]; const uint8_t *coord_start; size_t coord_len; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } /* For the description of pk->pk_raw content please refer to the description * psa_export_public_key() function. */ coord_len = (pk->pub_raw_len - 1)/2; /* X coordinate */ coord_start = pk->pub_raw + 1; mbedtls_snprintf(str, sizeof(str), "%s(X)", text); mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len); /* Y coordinate */ coord_start = coord_start + coord_len; mbedtls_snprintf(str, sizeof(str), "%s(Y)", text); mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #if defined(MBEDTLS_BIGNUM_C) void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_mpi *X) { char str[DEBUG_BUF_SIZE]; size_t bitlen; size_t idx = 0; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || NULL == X || level > debug_threshold) { return; } bitlen = mbedtls_mpi_bitlen(X); mbedtls_snprintf(str, sizeof(str), "value of '%s' (%u bits) is:\n", text, (unsigned) bitlen); debug_send_line(ssl, level, file, line, str); if (bitlen == 0) { str[0] = ' '; str[1] = '0'; str[2] = '0'; idx = 3; } else { int n; for (n = (int) ((bitlen - 1) / 8); n >= 0; n--) { size_t limb_offset = n / sizeof(mbedtls_mpi_uint); size_t offset_in_limb = n % sizeof(mbedtls_mpi_uint); unsigned char octet = (X->p[limb_offset] >> (offset_in_limb * 8)) & 0xff; mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", octet); idx += 3; /* Wrap lines after 16 octets that each take 3 columns */ if (idx >= 3 * 16) { mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); debug_send_line(ssl, level, file, line, str); idx = 0; } } } if (idx != 0) { mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); debug_send_line(ssl, level, file, line, str); } } #endif /* MBEDTLS_BIGNUM_C */ #if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO) static void debug_print_pk(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_pk_context *pk) { size_t i; mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; char name[16]; memset(items, 0, sizeof(items)); if (mbedtls_pk_debug(pk, items) != 0) { debug_send_line(ssl, level, file, line, "invalid PK context\n"); return; } for (i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++) { if (items[i].type == MBEDTLS_PK_DEBUG_NONE) { return; } mbedtls_snprintf(name, sizeof(name), "%s%s", text, items[i].name); name[sizeof(name) - 1] = '\0'; #if defined(MBEDTLS_RSA_C) if (items[i].type == MBEDTLS_PK_DEBUG_MPI) { mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value); } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_LIGHT) if (items[i].type == MBEDTLS_PK_DEBUG_ECP) { mbedtls_debug_print_ecp(ssl, level, file, line, name, items[i].value); } else #endif /* MBEDTLS_ECP_LIGHT */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) if (items[i].type == MBEDTLS_PK_DEBUG_PSA_EC) { mbedtls_debug_print_psa_ec(ssl, level, file, line, name, items[i].value); } else #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ { debug_send_line(ssl, level, file, line, "should not happen\n"); } } } static void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text) { char str[DEBUG_BUF_SIZE]; const char *start, *cur; start = text; for (cur = text; *cur != '\0'; cur++) { if (*cur == '\n') { size_t len = (size_t) (cur - start) + 1; if (len > DEBUG_BUF_SIZE - 1) { len = DEBUG_BUF_SIZE - 1; } memcpy(str, start, len); str[len] = '\0'; debug_send_line(ssl, level, file, line, str); start = cur + 1; } } } void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_x509_crt *crt) { char str[DEBUG_BUF_SIZE]; int i = 0; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || NULL == crt || level > debug_threshold) { return; } while (crt != NULL) { char buf[1024]; mbedtls_snprintf(str, sizeof(str), "%s #%d:\n", text, ++i); debug_send_line(ssl, level, file, line, str); mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); debug_print_line_by_line(ssl, level, file, line, buf); debug_print_pk(ssl, level, file, line, "crt->", &crt->pk); crt = crt->next; } } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \ defined(MBEDTLS_ECDH_C) static void mbedtls_debug_printf_ecdh_internal(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const mbedtls_ecdh_context *ecdh, mbedtls_debug_ecdh_attr attr) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) const mbedtls_ecdh_context *ctx = ecdh; #else const mbedtls_ecdh_context_mbed *ctx = &ecdh->ctx.mbed_ecdh; #endif switch (attr) { case MBEDTLS_DEBUG_ECDH_Q: mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Q", &ctx->Q); break; case MBEDTLS_DEBUG_ECDH_QP: mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Qp", &ctx->Qp); break; case MBEDTLS_DEBUG_ECDH_Z: mbedtls_debug_print_mpi(ssl, level, file, line, "ECDH: z", &ctx->z); break; default: break; } } void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const mbedtls_ecdh_context *ecdh, mbedtls_debug_ecdh_attr attr) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh, attr); #else switch (ecdh->var) { default: mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh, attr); } #endif } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED && MBEDTLS_ECDH_C */ #endif /* MBEDTLS_DEBUG_C */ webfakes/src/mbedtls/library/psa_crypto_driver_wrappers.h0000644000176200001440000032305614740737024023601 0ustar liggesusers/* * Functions to delegate cryptographic operations to an available * and appropriate accelerator. * Warning: This file is now auto-generated. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* BEGIN-common headers */ #include "common.h" #include "psa_crypto_aead.h" #include "psa_crypto_cipher.h" #include "psa_crypto_core.h" #include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_hash.h" #include "psa_crypto_mac.h" #include "psa_crypto_pake.h" #include "psa_crypto_rsa.h" #include "mbedtls/platform.h" #include "mbedtls/constant_time.h" /* END-common headers */ #if defined(MBEDTLS_PSA_CRYPTO_C) /* BEGIN-driver headers */ /* Headers for mbedtls_test opaque driver */ #if defined(PSA_CRYPTO_DRIVER_TEST) #include "test/drivers/test_driver.h" #endif /* Headers for mbedtls_test transparent driver */ #if defined(PSA_CRYPTO_DRIVER_TEST) #include "test/drivers/test_driver.h" #endif /* Headers for p256 transparent driver */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) #include "../3rdparty/p256-m/p256-m_driver_entrypoints.h" #endif /* END-driver headers */ /* Auto-generated values depending on which drivers are registered. * ID 0 is reserved for unallocated operations. * ID 1 is reserved for the Mbed TLS software driver. */ /* BEGIN-driver id definition */ #define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1) #define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2) #define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3) #define P256_TRANSPARENT_DRIVER_ID (4) /* END-driver id */ /* BEGIN-Common Macro definitions */ /* END-Common Macro definitions */ /* Support the 'old' SE interface when asked to */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style * SE driver is present, to avoid unused argument errors at compile time. */ #ifndef PSA_CRYPTO_DRIVER_PRESENT #define PSA_CRYPTO_DRIVER_PRESENT #endif #include "psa_crypto_se.h" #endif static inline psa_status_t psa_driver_wrapper_init( void ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) status = psa_init_all_se_drivers( ); if( status != PSA_SUCCESS ) return( status ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_init( ); if( status != PSA_SUCCESS ) return( status ); status = mbedtls_test_opaque_init( ); if( status != PSA_SUCCESS ) return( status ); #endif (void) status; return( PSA_SUCCESS ); } static inline void psa_driver_wrapper_free( void ) { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Unregister all secure element drivers, so that we restart from * a pristine state. */ psa_unregister_all_se_drivers( ); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_test_transparent_free( ); mbedtls_test_opaque_free( ); #endif } /* Start delegation functions */ static inline psa_status_t psa_driver_wrapper_sign_message( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_signature_sign_message( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_size, signature_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ break; /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_signature_sign_message( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_size, signature_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); break; #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; break; } return( psa_sign_message_builtin( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_size, signature_length ) ); } static inline psa_status_t psa_driver_wrapper_verify_message( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_signature_verify_message( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ break; /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_signature_verify_message( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_length ) ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); break; #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; break; } return( psa_verify_message_builtin( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_length ) ); } static inline psa_status_t psa_driver_wrapper_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length ) { /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( drv->asymmetric == NULL || drv->asymmetric->p_sign == NULL ) { /* Key is defined in SE, but we have no way to exercise it */ return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->asymmetric->p_sign( drv_context, *( (psa_key_slot_number_t *)key_buffer ), alg, hash, hash_length, signature, signature_size, signature_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_signature_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED) if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) && PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 && psa_get_key_bits(attributes) == 256 ) { status = p256_transparent_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); } #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( psa_sign_hash_builtin( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_signature_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length ) { /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( drv->asymmetric == NULL || drv->asymmetric->p_verify == NULL ) { /* Key is defined in SE, but we have no way to exercise it */ return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->asymmetric->p_verify( drv_context, *( (psa_key_slot_number_t *)key_buffer ), alg, hash, hash_length, signature, signature_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_signature_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED) if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) && PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 && psa_get_key_bits(attributes) == 256 ) { status = p256_transparent_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); } #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ return( psa_verify_hash_builtin( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_signature_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline uint32_t psa_driver_wrapper_sign_hash_get_num_ops( psa_sign_hash_interruptible_operation_t *operation ) { switch( operation->id ) { /* If uninitialised, return 0, as no work can have been done. */ case 0: return 0; case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return(mbedtls_psa_sign_hash_get_num_ops(&operation->ctx.mbedtls_ctx)); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } /* Can't happen (see discussion in #8271) */ return 0; } static inline uint32_t psa_driver_wrapper_verify_hash_get_num_ops( psa_verify_hash_interruptible_operation_t *operation ) { switch( operation->id ) { /* If uninitialised, return 0, as no work can have been done. */ case 0: return 0; case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return (mbedtls_psa_verify_hash_get_num_ops(&operation->ctx.mbedtls_ctx)); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } /* Can't happen (see discussion in #8271) */ return 0; } static inline psa_status_t psa_driver_wrapper_sign_hash_start( psa_sign_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ /* Declared with fallback == true */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; status = mbedtls_psa_sign_hash_start( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg, hash, hash_length ); break; /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ status = PSA_ERROR_INVALID_ARGUMENT; break; } return( status ); } static inline psa_status_t psa_driver_wrapper_sign_hash_complete( psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature, size_t signature_size, size_t *signature_length ) { switch( operation->id ) { case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_sign_hash_complete( &operation->ctx.mbedtls_ctx, signature, signature_size, signature_length ) ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } ( void ) signature; ( void ) signature_size; ( void ) signature_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_sign_hash_abort( psa_sign_hash_interruptible_operation_t *operation ) { switch( operation->id ) { case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_sign_hash_abort( &operation->ctx.mbedtls_ctx ) ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_verify_hash_start( psa_verify_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ /* Declared with fallback == true */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; status = mbedtls_psa_verify_hash_start( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ); break; /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ status = PSA_ERROR_INVALID_ARGUMENT; break; } return( status ); } static inline psa_status_t psa_driver_wrapper_verify_hash_complete( psa_verify_hash_interruptible_operation_t *operation ) { switch( operation->id ) { case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_verify_hash_complete( &operation->ctx.mbedtls_ctx ) ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_verify_hash_abort( psa_verify_hash_interruptible_operation_t *operation ) { switch( operation->id ) { case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_verify_hash_abort( &operation->ctx.mbedtls_ctx ) ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } return( PSA_ERROR_INVALID_ARGUMENT ); } /** Calculate the key buffer size required to store the key material of a key * associated with an opaque driver from input key data. * * \param[in] attributes The key attributes * \param[in] data The input key data. * \param[in] data_length The input data length. * \param[out] key_buffer_size Minimum buffer size to contain the key material. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription */ static inline psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, size_t *key_buffer_size ) { psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); psa_key_type_t key_type = psa_get_key_type(attributes); *key_buffer_size = 0; switch( location ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: *key_buffer_size = mbedtls_test_opaque_size_function( key_type, PSA_BYTES_TO_BITS( data_length ) ); return( ( *key_buffer_size != 0 ) ? PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_TEST */ default: (void)key_type; (void)data; (void)data_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, const psa_custom_key_parameters_t *custom, const uint8_t *custom_data, size_t custom_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) int is_default_production = psa_custom_key_parameters_are_default(custom, custom_data_length); if( location != PSA_KEY_LOCATION_LOCAL_STORAGE && !is_default_production ) { /* We don't support passing custom production parameters * to drivers yet. */ return PSA_ERROR_NOT_SUPPORTED; } #else int is_default_production = 1; (void) is_default_production; #endif /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { size_t pubkey_length = 0; /* We don't support this feature yet */ if( drv->key_management == NULL || drv->key_management->p_generate == NULL ) { /* Key is defined as being in SE, but we have no way to generate it */ return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->key_management->p_generate( drv_context, *( (psa_key_slot_number_t *)key_buffer ), attributes, NULL, 0, &pubkey_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Transparent drivers are limited to generating asymmetric keys. */ /* We don't support passing custom production parameters * to drivers yet. */ if( PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type(attributes) ) && is_default_production ) { /* Cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_generate_key( attributes, key_buffer, key_buffer_size, key_buffer_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) break; #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && psa_get_key_type(attributes) == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) && psa_get_key_bits(attributes) == 256 ) { status = p256_transparent_generate_key( attributes, key_buffer, key_buffer_size, key_buffer_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) break; } #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ } #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Software fallback */ status = psa_generate_key_internal( attributes, custom, custom_data, custom_data_length, key_buffer, key_buffer_size, key_buffer_length ); break; /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_generate_key( attributes, key_buffer, key_buffer_size, key_buffer_length ); break; #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ status = PSA_ERROR_INVALID_ARGUMENT; break; } return( status ); } static inline psa_status_t psa_driver_wrapper_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( drv->key_management == NULL || drv->key_management->p_import == NULL ) return( PSA_ERROR_NOT_SUPPORTED ); /* The driver should set the number of key bits, however in * case it doesn't, we initialize bits to an invalid value. */ *bits = PSA_MAX_KEY_BITS + 1; status = drv->key_management->p_import( drv_context, *( (psa_key_slot_number_t *)key_buffer ), attributes, data, data_length, bits ); if( status != PSA_SUCCESS ) return( status ); if( (*bits) > PSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); return( PSA_SUCCESS ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) status = mbedtls_test_transparent_import_key (attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif #if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) ) status = p256_transparent_import_key (attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( psa_import_key_into_slot( attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_import_key (attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_export_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) { psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( ( drv->key_management == NULL ) || ( drv->key_management->p_export == NULL ) ) { return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->key_management->p_export( drv_context, *( (psa_key_slot_number_t *)key_buffer ), data, data_size, data_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: return( psa_export_key_internal( attributes, key_buffer, key_buffer_size, data, data_size, data_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_export_key (attributes, key_buffer, key_buffer_size, data, data_size, data_length )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ return( status ); } } static inline psa_status_t psa_driver_wrapper_copy_key( psa_key_attributes_t *attributes, const uint8_t *source_key, size_t source_key_length, uint8_t *target_key_buffer, size_t target_key_buffer_size, size_t *target_key_buffer_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { /* Copying to a secure element is not implemented yet. */ return( PSA_ERROR_NOT_SUPPORTED ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_copy_key (attributes, source_key, source_key_length, target_key_buffer, target_key_buffer_size, target_key_buffer_length )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void)source_key; (void)source_key_length; (void)target_key_buffer; (void)target_key_buffer_size; (void)target_key_buffer_length; status = PSA_ERROR_INVALID_ARGUMENT; } return( status ); } /* * Cipher functions */ static inline psa_status_t psa_driver_wrapper_cipher_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *iv, size_t iv_length, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_cipher_encrypt( attributes, key_buffer, key_buffer_size, alg, iv, iv_length, input, input_length, output, output_size, output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) return( mbedtls_psa_cipher_encrypt( attributes, key_buffer, key_buffer_size, alg, iv, iv_length, input, input_length, output, output_size, output_length ) ); #else return( PSA_ERROR_NOT_SUPPORTED ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_cipher_encrypt( attributes, key_buffer, key_buffer_size, alg, iv, iv_length, input, input_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)key_buffer; (void)key_buffer_size; (void)alg; (void)iv; (void)iv_length; (void)input; (void)input_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_cipher_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_cipher_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, output, output_size, output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) return( mbedtls_psa_cipher_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, output, output_size, output_length ) ); #else return( PSA_ERROR_NOT_SUPPORTED ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_cipher_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)key_buffer; (void)key_buffer_size; (void)alg; (void)input; (void)input_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_cipher_encrypt_setup( psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_cipher_encrypt_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_cipher_encrypt_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_cipher_encrypt_setup( &operation->ctx.opaque_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)operation; (void)key_buffer; (void)key_buffer_size; (void)alg; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_cipher_decrypt_setup( psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_cipher_decrypt_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_cipher_decrypt_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; return( status ); #else /* MBEDTLS_PSA_BUILTIN_CIPHER */ return( PSA_ERROR_NOT_SUPPORTED ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_cipher_decrypt_setup( &operation->ctx.opaque_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)operation; (void)key_buffer; (void)key_buffer_size; (void)alg; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_cipher_set_iv( psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_cipher_set_iv( &operation->ctx.mbedtls_ctx, iv, iv_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_cipher_set_iv( &operation->ctx.transparent_test_driver_ctx, iv, iv_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_cipher_set_iv( &operation->ctx.opaque_test_driver_ctx, iv, iv_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)iv; (void)iv_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_cipher_update( psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_cipher_update( &operation->ctx.mbedtls_ctx, input, input_length, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_cipher_update( &operation->ctx.transparent_test_driver_ctx, input, input_length, output, output_size, output_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_cipher_update( &operation->ctx.opaque_test_driver_ctx, input, input_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)input; (void)input_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_cipher_finish( psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_cipher_finish( &operation->ctx.mbedtls_ctx, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_cipher_finish( &operation->ctx.transparent_test_driver_ctx, output, output_size, output_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_cipher_finish( &operation->ctx.opaque_test_driver_ctx, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_cipher_abort( psa_cipher_operation_t *operation ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_cipher_abort( &operation->ctx.mbedtls_ctx ) ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: status = mbedtls_test_transparent_cipher_abort( &operation->ctx.transparent_test_driver_ctx ); mbedtls_platform_zeroize( &operation->ctx.transparent_test_driver_ctx, sizeof( operation->ctx.transparent_test_driver_ctx ) ); return( status ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: status = mbedtls_test_opaque_cipher_abort( &operation->ctx.opaque_test_driver_ctx ); mbedtls_platform_zeroize( &operation->ctx.opaque_test_driver_ctx, sizeof( operation->ctx.opaque_test_driver_ctx ) ); return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } /* * Hashing functions */ static inline psa_status_t psa_driver_wrapper_hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Try accelerators first */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_hash_compute( alg, input, input_length, hash, hash_size, hash_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* If software fallback is compiled in, try fallback */ #if defined(MBEDTLS_PSA_BUILTIN_HASH) status = mbedtls_psa_hash_compute( alg, input, input_length, hash, hash_size, hash_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif (void) status; (void) alg; (void) input; (void) input_length; (void) hash; (void) hash_size; (void) hash_length; return( PSA_ERROR_NOT_SUPPORTED ); } static inline psa_status_t psa_driver_wrapper_hash_setup( psa_hash_operation_t *operation, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Try setup on accelerators first */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_hash_setup( &operation->ctx.test_driver_ctx, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* If software fallback is compiled in, try fallback */ #if defined(MBEDTLS_PSA_BUILTIN_HASH) status = mbedtls_psa_hash_setup( &operation->ctx.mbedtls_ctx, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* Nothing left to try if we fall through here */ (void) status; (void) operation; (void) alg; return( PSA_ERROR_NOT_SUPPORTED ); } static inline psa_status_t psa_driver_wrapper_hash_clone( const psa_hash_operation_t *source_operation, psa_hash_operation_t *target_operation ) { switch( source_operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_HASH) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: target_operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; return( mbedtls_psa_hash_clone( &source_operation->ctx.mbedtls_ctx, &target_operation->ctx.mbedtls_ctx ) ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: target_operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; return( mbedtls_test_transparent_hash_clone( &source_operation->ctx.test_driver_ctx, &target_operation->ctx.test_driver_ctx ) ); #endif default: (void) target_operation; return( PSA_ERROR_BAD_STATE ); } } static inline psa_status_t psa_driver_wrapper_hash_update( psa_hash_operation_t *operation, const uint8_t *input, size_t input_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_HASH) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_hash_update( &operation->ctx.mbedtls_ctx, input, input_length ) ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_hash_update( &operation->ctx.test_driver_ctx, input, input_length ) ); #endif default: (void) input; (void) input_length; return( PSA_ERROR_BAD_STATE ); } } static inline psa_status_t psa_driver_wrapper_hash_finish( psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_HASH) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_hash_finish( &operation->ctx.mbedtls_ctx, hash, hash_size, hash_length ) ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_hash_finish( &operation->ctx.test_driver_ctx, hash, hash_size, hash_length ) ); #endif default: (void) hash; (void) hash_size; (void) hash_length; return( PSA_ERROR_BAD_STATE ); } } static inline psa_status_t psa_driver_wrapper_hash_abort( psa_hash_operation_t *operation ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_HASH) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_hash_abort( &operation->ctx.mbedtls_ctx ) ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_hash_abort( &operation->ctx.test_driver_ctx ) ); #endif default: return( PSA_ERROR_BAD_STATE ); } } static inline psa_status_t psa_driver_wrapper_aead_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_aead_encrypt( attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, plaintext, plaintext_length, ciphertext, ciphertext_size, ciphertext_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( mbedtls_psa_aead_encrypt( attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, plaintext, plaintext_length, ciphertext, ciphertext_size, ciphertext_length ) ); /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_aead_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_aead_decrypt( attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, ciphertext, ciphertext_length, plaintext, plaintext_size, plaintext_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( mbedtls_psa_aead_decrypt( attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, ciphertext, ciphertext_length, plaintext, plaintext_size, plaintext_length ) ); /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_aead_encrypt_setup( psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; status = mbedtls_test_transparent_aead_encrypt_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; status = mbedtls_psa_aead_encrypt_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); return( status ); /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_aead_decrypt_setup( psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; status = mbedtls_test_transparent_aead_decrypt_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; status = mbedtls_psa_aead_decrypt_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); return( status ); /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_aead_set_nonce( psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_set_nonce( &operation->ctx.mbedtls_ctx, nonce, nonce_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_set_nonce( &operation->ctx.transparent_test_driver_ctx, nonce, nonce_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)nonce; (void)nonce_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_set_lengths( psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_set_lengths( &operation->ctx.mbedtls_ctx, ad_length, plaintext_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_set_lengths( &operation->ctx.transparent_test_driver_ctx, ad_length, plaintext_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)ad_length; (void)plaintext_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_update_ad( psa_aead_operation_t *operation, const uint8_t *input, size_t input_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_update_ad( &operation->ctx.mbedtls_ctx, input, input_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_update_ad( &operation->ctx.transparent_test_driver_ctx, input, input_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)input; (void)input_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_update( psa_aead_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_update( &operation->ctx.mbedtls_ctx, input, input_length, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_update( &operation->ctx.transparent_test_driver_ctx, input, input_length, output, output_size, output_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)input; (void)input_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_finish( psa_aead_operation_t *operation, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag, size_t tag_size, size_t *tag_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx, ciphertext, ciphertext_size, ciphertext_length, tag, tag_size, tag_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_finish( &operation->ctx.transparent_test_driver_ctx, ciphertext, ciphertext_size, ciphertext_length, tag, tag_size, tag_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)ciphertext; (void)ciphertext_size; (void)ciphertext_length; (void)tag; (void)tag_size; (void)tag_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_verify( psa_aead_operation_t *operation, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length, const uint8_t *tag, size_t tag_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE]; size_t check_tag_length; status = mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx, plaintext, plaintext_size, plaintext_length, check_tag, sizeof( check_tag ), &check_tag_length ); if( status == PSA_SUCCESS ) { if( tag_length != check_tag_length || mbedtls_ct_memcmp( tag, check_tag, tag_length ) != 0 ) status = PSA_ERROR_INVALID_SIGNATURE; } mbedtls_platform_zeroize( check_tag, sizeof( check_tag ) ); return( status ); } #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_verify( &operation->ctx.transparent_test_driver_ctx, plaintext, plaintext_size, plaintext_length, tag, tag_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)plaintext; (void)plaintext_size; (void)plaintext_length; (void)tag; (void)tag_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_abort( psa_aead_operation_t *operation ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_abort( &operation->ctx.mbedtls_ctx ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_abort( &operation->ctx.transparent_test_driver_ctx ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } return( PSA_ERROR_INVALID_ARGUMENT ); } /* * MAC functions */ static inline psa_status_t psa_driver_wrapper_mac_compute( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_mac_compute( attributes, key_buffer, key_buffer_size, alg, input, input_length, mac, mac_size, mac_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_MAC) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_mac_compute( attributes, key_buffer, key_buffer_size, alg, input, input_length, mac, mac_size, mac_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_mac_compute( attributes, key_buffer, key_buffer_size, alg, input, input_length, mac, mac_size, mac_length ); return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void) key_buffer; (void) key_buffer_size; (void) alg; (void) input; (void) input_length; (void) mac; (void) mac_size; (void) mac_length; (void) status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_sign_setup( psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_mac_sign_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_MAC) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_mac_sign_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_mac_sign_setup( &operation->ctx.opaque_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void) status; (void) operation; (void) key_buffer; (void) key_buffer_size; (void) alg; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_verify_setup( psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_mac_verify_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_MAC) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_mac_verify_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_mac_verify_setup( &operation->ctx.opaque_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void) status; (void) operation; (void) key_buffer; (void) key_buffer_size; (void) alg; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_update( psa_mac_operation_t *operation, const uint8_t *input, size_t input_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_MAC) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_mac_update( &operation->ctx.mbedtls_ctx, input, input_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_mac_update( &operation->ctx.transparent_test_driver_ctx, input, input_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_mac_update( &operation->ctx.opaque_test_driver_ctx, input, input_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) input; (void) input_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_sign_finish( psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_MAC) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_mac_sign_finish( &operation->ctx.mbedtls_ctx, mac, mac_size, mac_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_mac_sign_finish( &operation->ctx.transparent_test_driver_ctx, mac, mac_size, mac_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_mac_sign_finish( &operation->ctx.opaque_test_driver_ctx, mac, mac_size, mac_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) mac; (void) mac_size; (void) mac_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_verify_finish( psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_MAC) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_mac_verify_finish( &operation->ctx.mbedtls_ctx, mac, mac_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_mac_verify_finish( &operation->ctx.transparent_test_driver_ctx, mac, mac_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_mac_verify_finish( &operation->ctx.opaque_test_driver_ctx, mac, mac_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) mac; (void) mac_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_abort( psa_mac_operation_t *operation ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_MAC) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_mac_abort( &operation->ctx.mbedtls_ctx ) ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_mac_abort( &operation->ctx.transparent_test_driver_ctx ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_mac_abort( &operation->ctx.opaque_test_driver_ctx ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: return( PSA_ERROR_INVALID_ARGUMENT ); } } /* * Asymmetric cryptography */ static inline psa_status_t psa_driver_wrapper_asymmetric_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_asymmetric_encrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ return( mbedtls_psa_asymmetric_encrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_asymmetric_encrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)key_buffer; (void)key_buffer_size; (void)alg; (void)input; (void)input_length; (void)salt; (void)salt_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_asymmetric_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_asymmetric_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ return( mbedtls_psa_asymmetric_decrypt( attributes, key_buffer, key_buffer_size, alg,input, input_length, salt, salt_length, output, output_size, output_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_asymmetric_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)key_buffer; (void)key_buffer_size; (void)alg; (void)input; (void)input_length; (void)salt; (void)salt_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_key_agreement( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_key_agreement( attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && PSA_ALG_IS_ECDH(alg) && PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 && psa_get_key_bits(attributes) == 256 ) { status = p256_transparent_key_agreement( attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length ); if( status != PSA_ERROR_NOT_SUPPORTED) return( status ); } #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Software Fallback */ status = psa_key_agreement_raw_builtin( attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length ); return( status ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_key_agreement( attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) attributes; (void) key_buffer; (void) key_buffer_size; (void) peer_key; (void) peer_key_length; (void) shared_secret; (void) shared_secret_size; (void) shared_secret_length; return( PSA_ERROR_NOT_SUPPORTED ); } } static inline psa_status_t psa_driver_wrapper_pake_setup( psa_pake_operation_t *operation, const psa_crypto_driver_pake_inputs_t *inputs ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( &inputs->attributes ) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ status = PSA_ERROR_NOT_SUPPORTED; #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_pake_setup( &operation->data.ctx.transparent_test_driver_ctx, inputs ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_PAKE) status = mbedtls_psa_pake_setup( &operation->data.ctx.mbedtls_ctx, inputs ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; #endif return status; /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)operation; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_pake_output( psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_PAKE) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_pake_output( &operation->data.ctx.mbedtls_ctx, step, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_pake_output( &operation->data.ctx.transparent_test_driver_ctx, step, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) step; (void) output; (void) output_size; (void) output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_pake_input( psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, const uint8_t *input, size_t input_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_PAKE) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_pake_input( &operation->data.ctx.mbedtls_ctx, step, input, input_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_pake_input( &operation->data.ctx.transparent_test_driver_ctx, step, input, input_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) step; (void) input; (void) input_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_pake_get_implicit_key( psa_pake_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_PAKE) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_pake_get_implicit_key( &operation->data.ctx.mbedtls_ctx, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_pake_get_implicit_key( &operation->data.ctx.transparent_test_driver_ctx, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) output; (void) output_size; (void) output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_pake_abort( psa_pake_operation_t * operation ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_PAKE) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_pake_abort( &operation->data.ctx.mbedtls_ctx ) ); #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_pake_abort( &operation->data.ctx.transparent_test_driver_ctx ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: return( PSA_ERROR_INVALID_ARGUMENT ); } } #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/lms.c0000644000176200001440000006302514740737024016703 0ustar liggesusers/* * The LMS stateful-hash public-key signature scheme * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this implementation * of the LMS algorithm: * * [1] IETF RFC8554 * D. McGrew, M. Curcio, S.Fluhrer * https://datatracker.ietf.org/doc/html/rfc8554 * * [2] NIST Special Publication 800-208 * David A. Cooper et. al. * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf */ #include "common.h" #if defined(MBEDTLS_LMS_C) #include #include "lmots.h" #include "psa/crypto.h" #include "psa_util_internal.h" #include "mbedtls/lms.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/platform.h" /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_lms_errors, ARRAY_LENGTH(psa_to_lms_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #define SIG_Q_LEAF_ID_OFFSET (0) #define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \ MBEDTLS_LMOTS_Q_LEAF_ID_LEN) #define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET + \ MBEDTLS_LMOTS_SIG_LEN(otstype)) #define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \ MBEDTLS_LMS_TYPE_LEN) #define PUBLIC_KEY_TYPE_OFFSET (0) #define PUBLIC_KEY_OTSTYPE_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ MBEDTLS_LMS_TYPE_LEN) #define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_OTSTYPE_OFFSET + \ MBEDTLS_LMOTS_TYPE_LEN) #define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ MBEDTLS_LMOTS_I_KEY_ID_LEN) /* Currently only support H=10 */ #define H_TREE_HEIGHT_MAX 10 #define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u)) #define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type)) #define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \ (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))) #define D_CONST_LEN (2) static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 }; static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 }; /* Calculate the value of a leaf node of the Merkle tree (which is a hash of a * public key and some other parameters like the leaf index). This function * implements RFC8554 section 5.3, in the case where r >= 2^h. * * params The LMS parameter set, the underlying LMOTS * parameter set, and I value which describe the key * being used. * * pub_key The public key of the private whose index * corresponds to the index of this leaf node. This * is a hash output. * * r_node_idx The index of this node in the Merkle tree. Note * that the root node of the Merkle tree is * 1-indexed. * * out The output node value, which is a hash output. */ static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params, unsigned char *pub_key, unsigned int r_node_idx, unsigned char *out) { psa_hash_operation_t op; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char r_node_idx_bytes[4]; op = psa_hash_operation_init(); status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0); status = psa_hash_update(&op, r_node_idx_bytes, 4); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN(params->otstype)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } exit: psa_hash_abort(&op); return PSA_TO_MBEDTLS_ERR(status); } /* Calculate the value of an internal node of the Merkle tree (which is a hash * of a public key and some other parameters like the node index). This function * implements RFC8554 section 5.3, in the case where r < 2^h. * * params The LMS parameter set, the underlying LMOTS * parameter set, and I value which describe the key * being used. * * left_node The value of the child of this node which is on * the left-hand side. As with all nodes on the * Merkle tree, this is a hash output. * * right_node The value of the child of this node which is on * the right-hand side. As with all nodes on the * Merkle tree, this is a hash output. * * r_node_idx The index of this node in the Merkle tree. Note * that the root node of the Merkle tree is * 1-indexed. * * out The output node value, which is a hash output. */ static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params, const unsigned char *left_node, const unsigned char *right_node, unsigned int r_node_idx, unsigned char *out) { psa_hash_operation_t op; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char r_node_idx_bytes[4]; op = psa_hash_operation_init(); status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0); status = psa_hash_update(&op, r_node_idx_bytes, 4); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, left_node, MBEDTLS_LMS_M_NODE_BYTES(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, right_node, MBEDTLS_LMS_M_NODE_BYTES(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } exit: psa_hash_abort(&op); return PSA_TO_MBEDTLS_ERR(status); } void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(*ctx)); } int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx, const unsigned char *key, size_t key_size) { mbedtls_lms_algorithm_type_t type; mbedtls_lmots_algorithm_type_t otstype; type = (mbedtls_lms_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET); if (type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.type = type; if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } otstype = (mbedtls_lmots_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET); if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.otstype = otstype; memcpy(ctx->params.I_key_identifier, key + PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN); memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET, MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); ctx->have_public_key = 1; return 0; } int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len) { if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; } if (!ctx->have_public_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET); MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET); memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET, ctx->T_1_pub_key, MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); if (key_len != NULL) { *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type); } return 0; } int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size) { unsigned int q_leaf_identifier; unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX]; unsigned int height; unsigned int curr_node_id; unsigned int parent_node_id; const unsigned char *left_node; const unsigned char *right_node; mbedtls_lmots_parameters_t ots_params; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (!ctx->have_public_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->params.otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype)) != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET); if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } memcpy(ots_params.I_key_identifier, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0); ots_params.type = ctx->params.otstype; ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params, msg, msg_size, sig + SIG_OTS_SIG_OFFSET, MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), Kc_candidate_ots_pub_key, sizeof(Kc_candidate_ots_pub_key), NULL); if (ret != 0) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } create_merkle_leaf_value( &ctx->params, Kc_candidate_ots_pub_key, MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, Tc_candidate_root_node); curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier; for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); height++) { parent_node_id = curr_node_id / 2; /* Left/right node ordering matters for the hash */ if (curr_node_id & 1) { left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); right_node = Tc_candidate_root_node; } else { left_node = Tc_candidate_root_node; right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); } create_merkle_internal_value(&ctx->params, left_node, right_node, parent_node_id, Tc_candidate_root_node); curr_node_id /= 2; } if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key, MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } return 0; } #if defined(MBEDTLS_LMS_PRIVATE) /* Calculate a full Merkle tree based on a private key. This function * implements RFC8554 section 5.3, and is used to generate a public key (as the * public key is the root node of the Merkle tree). * * ctx The LMS private context, containing a parameter * set and private key material consisting of both * public and private OTS. * * tree The output tree, which is 2^(H + 1) hash outputs. * In the case of H=10 we have 2048 tree nodes (of * which 1024 of them are leaf nodes). Note that * because the Merkle tree root is 1-indexed, the 0 * index tree node is never used. */ static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx, unsigned char *tree) { unsigned int priv_key_idx; unsigned int r_node_idx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* First create the leaf nodes, in ascending order */ for (priv_key_idx = 0; priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type); priv_key_idx++) { r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx; ret = create_merkle_leaf_value(&ctx->params, ctx->ots_public_keys[priv_key_idx].public_key, r_node_idx, &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES( ctx->params.type)]); if (ret != 0) { return ret; } } /* Then the internal nodes, in reverse order so that we can guarantee the * parent has been created */ for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1; r_node_idx > 0; r_node_idx--) { ret = create_merkle_internal_value(&ctx->params, &tree[(r_node_idx * 2) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], &tree[(r_node_idx * 2 + 1) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], r_node_idx, &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]); if (ret != 0) { return ret; } } return 0; } /* Calculate a path from a leaf node of the Merkle tree to the root of the tree, * and return the full path. This function implements RFC8554 section 5.4.1, as * the Merkle path is the main component of an LMS signature. * * ctx The LMS private context, containing a parameter * set and private key material consisting of both * public and private OTS. * * leaf_node_id Which leaf node to calculate the path from. * * path The output path, which is H hash outputs. */ static int get_merkle_path(mbedtls_lms_private_t *ctx, unsigned int leaf_node_id, unsigned char *path) { const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); unsigned int curr_node_id = leaf_node_id; unsigned int adjacent_node_id; unsigned char *tree = NULL; unsigned int height; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type), node_bytes); if (tree == NULL) { return MBEDTLS_ERR_LMS_ALLOC_FAILED; } ret = calculate_merkle_tree(ctx, tree); if (ret != 0) { goto exit; } for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); height++) { adjacent_node_id = curr_node_id ^ 1; memcpy(&path[height * node_bytes], &tree[adjacent_node_id * node_bytes], node_bytes); curr_node_id >>= 1; } ret = 0; exit: mbedtls_zeroize_and_free(tree, node_bytes * (size_t) MERKLE_TREE_NODE_AM(ctx->params.type)); return ret; } void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx) { if (ctx == NULL) { return; } unsigned int idx; if (ctx->have_private_key) { if (ctx->ots_private_keys != NULL) { for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]); } } if (ctx->ots_public_keys != NULL) { for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]); } } mbedtls_free(ctx->ots_private_keys); mbedtls_free(ctx->ots_public_keys); } mbedtls_platform_zeroize(ctx, sizeof(*ctx)); } int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx, mbedtls_lms_algorithm_type_t type, mbedtls_lmots_algorithm_type_t otstype, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *seed, size_t seed_size) { unsigned int idx = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.type = type; ctx->params.otstype = otstype; ctx->have_private_key = 1; ret = f_rng(p_rng, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (ret != 0) { goto exit; } /* Requires a cast to size_t to avoid an implicit cast warning on certain * platforms (particularly Windows) */ ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof(*ctx->ots_private_keys)); if (ctx->ots_private_keys == NULL) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; } /* Requires a cast to size_t to avoid an implicit cast warning on certain * platforms (particularly Windows) */ ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof(*ctx->ots_public_keys)); if (ctx->ots_public_keys == NULL) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; } for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]); mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]); } for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx], otstype, ctx->params.I_key_identifier, idx, seed, seed_size); if (ret != 0) { goto exit; } ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx], &ctx->ots_private_keys[idx]); if (ret != 0) { goto exit; } } ctx->q_next_usable_key = 0; exit: if (ret != 0) { mbedtls_lms_private_free(ctx); } return ret; } int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx, const mbedtls_lms_private_t *priv_ctx) { const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type); int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *tree = NULL; if (!priv_ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (priv_ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (priv_ctx->params.otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type), node_bytes); if (tree == NULL) { return MBEDTLS_ERR_LMS_ALLOC_FAILED; } memcpy(&ctx->params, &priv_ctx->params, sizeof(mbedtls_lmots_parameters_t)); ret = calculate_merkle_tree(priv_ctx, tree); if (ret != 0) { goto exit; } /* Root node is always at position 1, due to 1-based indexing */ memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes); ctx->have_public_key = 1; ret = 0; exit: mbedtls_zeroize_and_free(tree, node_bytes * (size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type)); return ret; } int mbedtls_lms_sign(mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *msg, unsigned int msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len) { uint32_t q_leaf_identifier; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (!ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; } if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->params.otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS; } q_leaf_identifier = ctx->q_next_usable_key; /* This new value must _always_ be written back to the disk before the * signature is returned. */ ctx->q_next_usable_key += 1; if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) < SIG_OTS_SIG_OFFSET) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier], f_rng, p_rng, msg, msg_size, sig + SIG_OTS_SIG_OFFSET, MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) - SIG_OTS_SIG_OFFSET, NULL); if (ret != 0) { return ret; } MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype)); MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET); ret = get_merkle_path(ctx, MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, sig + SIG_PATH_OFFSET(ctx->params.otstype)); if (ret != 0) { return ret; } if (sig_len != NULL) { *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype); } return 0; } #endif /* defined(MBEDTLS_LMS_PRIVATE) */ #endif /* defined(MBEDTLS_LMS_C) */ webfakes/src/mbedtls/library/bignum_internal.h0000644000176200001440000000430714740737024021270 0ustar liggesusers/** * \file bignum_internal.h * * \brief Internal-only bignum public-key cryptosystem API. * * This file declares bignum-related functions that are to be used * only from within the Mbed TLS library itself. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_INTERNAL_H #define MBEDTLS_BIGNUM_INTERNAL_H /** * \brief Perform a modular exponentiation: X = A^E mod N * * \warning This function is not constant time with respect to \p E (the exponent). * * \param X The destination MPI. This must point to an initialized MPI. * This must not alias E or N. * \param A The base of the exponentiation. * This must point to an initialized MPI. * \param E The exponent MPI. This must point to an initialized MPI. * \param N The base for the modular reduction. This must point to an * initialized MPI. * \param prec_RR A helper MPI depending solely on \p N which can be used to * speed-up multiple modular exponentiations for the same value * of \p N. This may be \c NULL. If it is not \c NULL, it must * point to an initialized MPI. If it hasn't been used after * the call to mbedtls_mpi_init(), this function will compute * the helper value and store it in \p prec_RR for reuse on * subsequent calls to this function. Otherwise, the function * will assume that \p prec_RR holds the helper value set by a * previous call to mbedtls_mpi_exp_mod(), and reuse it. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or * even, or if \c E is negative. * \return Another negative error code on different kinds of failures. * */ int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *prec_RR); #endif /* bignum_internal.h */ webfakes/src/mbedtls/library/entropy.c0000644000176200001440000004333114740737024017606 0ustar liggesusers/* * Entropy accumulator implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" #include "entropy_poll.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_FS_IO) #include #endif #include "mbedtls/platform.h" #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ void mbedtls_entropy_init(mbedtls_entropy_context *ctx) { ctx->source_count = 0; memset(ctx->source, 0, sizeof(ctx->source)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif ctx->accumulator_started = 0; mbedtls_md_init(&ctx->accumulator); /* Reminder: Update ENTROPY_HAVE_STRONG in the test files * when adding more strong entropy sources here. */ #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL, MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_SOURCE_STRONG); #endif #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL, MBEDTLS_ENTROPY_MIN_HARDWARE, MBEDTLS_ENTROPY_SOURCE_STRONG); #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL, MBEDTLS_ENTROPY_BLOCK_SIZE, MBEDTLS_ENTROPY_SOURCE_STRONG); ctx->initial_entropy_run = 0; #endif #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ } void mbedtls_entropy_free(mbedtls_entropy_context *ctx) { if (ctx == NULL) { return; } /* If the context was already free, don't call free() again. * This is important for mutexes which don't allow double-free. */ if (ctx->accumulator_started == -1) { return; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&ctx->mutex); #endif mbedtls_md_free(&ctx->accumulator); #if defined(MBEDTLS_ENTROPY_NV_SEED) ctx->initial_entropy_run = 0; #endif ctx->source_count = 0; mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source)); ctx->accumulator_started = -1; } int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx, mbedtls_entropy_f_source_ptr f_source, void *p_source, size_t threshold, int strong) { int idx, ret = 0; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif idx = ctx->source_count; if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) { ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; goto exit; } ctx->source[idx].f_source = f_source; ctx->source[idx].p_source = p_source; ctx->source[idx].threshold = threshold; ctx->source[idx].strong = strong; ctx->source_count++; exit: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * Entropy accumulator update */ static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id, const unsigned char *data, size_t len) { unsigned char header[2]; unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; size_t use_len = len; const unsigned char *p = data; int ret = 0; if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) { if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), data, len, tmp)) != 0) { goto cleanup; } p = tmp; use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; } header[0] = source_id; header[1] = use_len & 0xFF; /* * Start the accumulator if this has not already happened. Note that * it is sufficient to start the accumulator here only because all calls to * gather entropy eventually execute this code. */ if (ctx->accumulator_started == 0) { ret = mbedtls_md_setup(&ctx->accumulator, mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0); if (ret != 0) { goto cleanup; } ret = mbedtls_md_starts(&ctx->accumulator); if (ret != 0) { goto cleanup; } ctx->accumulator_started = 1; } if ((ret = mbedtls_md_update(&ctx->accumulator, header, 2)) != 0) { goto cleanup; } ret = mbedtls_md_update(&ctx->accumulator, p, use_len); cleanup: mbedtls_platform_zeroize(tmp, sizeof(tmp)); return ret; } int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx, const unsigned char *data, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * Run through the different sources to add entropy to our accumulator */ static int entropy_gather_internal(mbedtls_entropy_context *ctx) { int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; int i; int have_one_strong = 0; unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; size_t olen; if (ctx->source_count == 0) { return MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED; } /* * Run through our entropy sources */ for (i = 0; i < ctx->source_count; i++) { if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) { have_one_strong = 1; } olen = 0; if ((ret = ctx->source[i].f_source(ctx->source[i].p_source, buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) { goto cleanup; } /* * Add if we actually gathered something */ if (olen > 0) { if ((ret = entropy_update(ctx, (unsigned char) i, buf, olen)) != 0) { return ret; } ctx->source[i].size += olen; } } if (have_one_strong == 0) { ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; } cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } /* * Thread-safe wrapper for entropy_gather_internal() */ int mbedtls_entropy_gather(mbedtls_entropy_context *ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif ret = entropy_gather_internal(ctx); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } int mbedtls_entropy_func(void *data, unsigned char *output, size_t len) { int ret, count = 0, i, thresholds_reached; size_t strong_size; mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; if (len > MBEDTLS_ENTROPY_BLOCK_SIZE) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } #if defined(MBEDTLS_ENTROPY_NV_SEED) /* Update the NV entropy seed before generating any entropy for outside * use. */ if (ctx->initial_entropy_run == 0) { ctx->initial_entropy_run = 1; if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0) { return ret; } } #endif #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif /* * Always gather extra entropy before a call */ do { if (count++ > ENTROPY_MAX_LOOP) { ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; goto exit; } if ((ret = entropy_gather_internal(ctx)) != 0) { goto exit; } thresholds_reached = 1; strong_size = 0; for (i = 0; i < ctx->source_count; i++) { if (ctx->source[i].size < ctx->source[i].threshold) { thresholds_reached = 0; } if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) { strong_size += ctx->source[i].size; } } } while (!thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE); memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE); /* * Note that at this stage it is assumed that the accumulator was started * in a previous call to entropy_update(). If this is not guaranteed, the * code below will fail. */ if ((ret = mbedtls_md_finish(&ctx->accumulator, buf)) != 0) { goto exit; } /* * Reset accumulator and counters and recycle existing entropy */ mbedtls_md_free(&ctx->accumulator); mbedtls_md_init(&ctx->accumulator); ret = mbedtls_md_setup(&ctx->accumulator, mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_starts(&ctx->accumulator); if (ret != 0) { goto exit; } if ((ret = mbedtls_md_update(&ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { goto exit; } /* * Perform second hashing on entropy */ if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf)) != 0) { goto exit; } for (i = 0; i < ctx->source_count; i++) { ctx->source[i].size = 0; } memcpy(output, buf, len); ret = 0; exit: mbedtls_platform_zeroize(buf, sizeof(buf)); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } #if defined(MBEDTLS_ENTROPY_NV_SEED) int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx) { int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; /* Read new seed and write it to NV */ if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { return ret; } if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) { return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; } /* Manually update the remaining stream with a separator value to diverge */ memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE); ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE); return ret; } #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if defined(MBEDTLS_FS_IO) int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; FILE *f = NULL; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; goto exit; } if ((f = fopen(path, "wb")) == NULL) { ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; goto exit; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) { ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; goto exit; } ret = 0; exit: mbedtls_platform_zeroize(buf, sizeof(buf)); if (f != NULL) { fclose(f); } return ret; } int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path) { int ret = 0; FILE *f; size_t n; unsigned char buf[MBEDTLS_ENTROPY_MAX_SEED_SIZE]; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); fseek(f, 0, SEEK_END); n = (size_t) ftell(f); fseek(f, 0, SEEK_SET); if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE) { n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; } if (fread(buf, 1, n, f) != n) { ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; } else { ret = mbedtls_entropy_update_manual(ctx, buf, n); } fclose(f); mbedtls_platform_zeroize(buf, sizeof(buf)); if (ret != 0) { return ret; } return mbedtls_entropy_write_seed_file(ctx, path); } #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /* * Dummy source function */ static int entropy_dummy_source(void *data, unsigned char *output, size_t len, size_t *olen) { ((void) data); memset(output, 0x2a, len); *olen = len; return 0; } #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) static int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len) { int ret = 0; size_t entropy_len = 0; size_t olen = 0; size_t attempts = buf_len; while (attempts > 0 && entropy_len < buf_len) { if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len, buf_len - entropy_len, &olen)) != 0) { return ret; } entropy_len += olen; attempts--; } if (entropy_len < buf_len) { ret = 1; } return ret; } static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf, size_t buf_len) { unsigned char set = 0xFF; unsigned char unset = 0x00; size_t i; for (i = 0; i < buf_len; i++) { set &= buf[i]; unset |= buf[i]; } return set == 0xFF || unset == 0x00; } /* * A test to ensure that the entropy sources are functioning correctly * and there is no obvious failure. The test performs the following checks: * - The entropy source is not providing only 0s (all bits unset) or 1s (all * bits set). * - The entropy source is not providing values in a pattern. Because the * hardware could be providing data in an arbitrary length, this check polls * the hardware entropy source twice and compares the result to ensure they * are not equal. * - The error code returned by the entropy source is not an error. */ int mbedtls_entropy_source_self_test(int verbose) { int ret = 0; unsigned char buf0[2 * sizeof(unsigned long long int)]; unsigned char buf1[2 * sizeof(unsigned long long int)]; if (verbose != 0) { mbedtls_printf(" ENTROPY_BIAS test: "); } memset(buf0, 0x00, sizeof(buf0)); memset(buf1, 0x00, sizeof(buf1)); if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) { goto cleanup; } if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) { goto cleanup; } /* Make sure that the returned values are not all 0 or 1 */ if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0, sizeof(buf0))) != 0) { goto cleanup; } if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) { goto cleanup; } /* Make sure that the entropy source is not returning values in a * pattern */ ret = memcmp(buf0, buf1, sizeof(buf0)) == 0; cleanup: if (verbose != 0) { if (ret != 0) { mbedtls_printf("failed\n"); } else { mbedtls_printf("passed\n"); } mbedtls_printf("\n"); } return ret != 0; } #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ /* * The actual entropy quality is hard to test, but we can at least * test that the functions don't cause errors and write the correct * amount of data to buffers. */ int mbedtls_entropy_self_test(int verbose) { int ret = 1; mbedtls_entropy_context ctx; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; size_t i, j; if (verbose != 0) { mbedtls_printf(" ENTROPY test: "); } mbedtls_entropy_init(&ctx); /* First do a gather to make sure we have default sources */ if ((ret = mbedtls_entropy_gather(&ctx)) != 0) { goto cleanup; } ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16, MBEDTLS_ENTROPY_SOURCE_WEAK); if (ret != 0) { goto cleanup; } if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) { goto cleanup; } /* * To test that mbedtls_entropy_func writes correct number of bytes: * - use the whole buffer and rely on ASan to detect overruns * - collect entropy 8 times and OR the result in an accumulator: * any byte should then be 0 with probably 2^(-64), so requiring * each of the 32 or 64 bytes to be non-zero has a false failure rate * of at most 2^(-58) which is acceptable. */ for (i = 0; i < 8; i++) { if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0) { goto cleanup; } for (j = 0; j < sizeof(buf); j++) { acc[j] |= buf[j]; } } for (j = 0; j < sizeof(buf); j++) { if (acc[j] == 0) { ret = 1; goto cleanup; } } #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) if ((ret = mbedtls_entropy_source_self_test(0)) != 0) { goto cleanup; } #endif cleanup: mbedtls_entropy_free(&ctx); if (verbose != 0) { if (ret != 0) { mbedtls_printf("failed\n"); } else { mbedtls_printf("passed\n"); } mbedtls_printf("\n"); } return ret != 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_ENTROPY_C */ webfakes/src/mbedtls/library/psa_crypto_storage.h0000644000176200001440000003551714740737024022031 0ustar liggesusers/** * \file psa_crypto_storage.h * * \brief PSA cryptography module: Mbed TLS key storage */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_STORAGE_H #define PSA_CRYPTO_STORAGE_H #ifdef __cplusplus extern "C" { #endif #include "psa/crypto.h" #include "psa/crypto_se_driver.h" #include #include /* Limit the maximum key size in storage. This should have no effect * since the key size is limited in memory. */ #define PSA_CRYPTO_MAX_STORAGE_SIZE (PSA_BITS_TO_BYTES(PSA_MAX_KEY_BITS)) /* Sanity check: a file size must fit in 32 bits. Allow a generous * 64kB of metadata. */ #if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 #error "PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000" #endif /** The maximum permitted persistent slot number. * * In Mbed Crypto 0.1.0b: * - Using the file backend, all key ids are ok except 0. * - Using the ITS backend, all key ids are ok except 0xFFFFFF52 * (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the * device's random seed (if this feature is enabled). * - Only key ids from 1 to #MBEDTLS_PSA_KEY_SLOT_COUNT are actually used. * * Since we need to preserve the random seed, avoid using that key slot. * Reserve a whole range of key slots just in case something else comes up. * * This limitation will probably become moot when we implement client * separation for key storage. */ #define PSA_MAX_PERSISTENT_KEY_IDENTIFIER PSA_KEY_ID_VENDOR_MAX /** * \brief Checks if persistent data is stored for the given key slot number * * This function checks if any key data or metadata exists for the key slot in * the persistent storage. * * \param key Persistent identifier to check. * * \retval 0 * No persistent data present for slot number * \retval 1 * Persistent data present for slot number */ int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key); /** * \brief Format key data and metadata and save to a location for given key * slot. * * This function formats the key data and metadata and saves it to a * persistent storage backend. The storage location corresponding to the * key slot must be empty, otherwise this function will fail. This function * should be called after loading the key into an internal slot to ensure the * persistent key is not saved into a storage location corresponding to an * already occupied non-persistent key, as well as ensuring the key data is * validated. * * Note: This function will only succeed for key buffers which are not * empty. If passed a NULL pointer or zero-length, the function will fail * with #PSA_ERROR_INVALID_ARGUMENT. * * \param[in] attr The attributes of the key to save. * The key identifier field in the attributes * determines the key's location. * \param[in] data Buffer containing the key data. * \param data_length The number of bytes that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr, const uint8_t *data, const size_t data_length); /** * \brief Parses key data and metadata and load persistent key for given * key slot number. * * This function reads from a storage backend, parses the key data and * metadata and writes them to the appropriate output parameters. * * Note: This function allocates a buffer and returns a pointer to it through * the data parameter. On successful return, the pointer is guaranteed to be * valid and the buffer contains at least one byte of data. * psa_free_persistent_key_data() must be called on the data buffer * afterwards to zeroize and free this buffer. * * \param[in,out] attr On input, the key identifier field identifies * the key to load. Other fields are ignored. * On success, the attribute structure contains * the key metadata that was loaded from storage. * \param[out] data Pointer to an allocated key data buffer on return. * \param[out] data_length The number of bytes that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription */ psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr, uint8_t **data, size_t *data_length); /** * \brief Remove persistent data for the given key slot number. * * \param key Persistent identifier of the key to remove * from persistent storage. * * \retval #PSA_SUCCESS * The key was successfully removed, * or the key did not exist. * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key); /** * \brief Free the temporary buffer allocated by psa_load_persistent_key(). * * This function must be called at some point after psa_load_persistent_key() * to zeroize and free the memory allocated to the buffer in that function. * * \param key_data Buffer for the key data. * \param key_data_length Size of the key data buffer. * */ void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length); /** * \brief Formats key data and metadata for persistent storage * * \param[in] data Buffer containing the key data. * \param data_length Length of the key data buffer. * \param[in] attr The core attributes of the key. * \param[out] storage_data Output buffer for the formatted data. * */ void psa_format_key_data_for_storage(const uint8_t *data, const size_t data_length, const psa_key_attributes_t *attr, uint8_t *storage_data); /** * \brief Parses persistent storage data into key data and metadata * * \param[in] storage_data Buffer for the storage data. * \param storage_data_length Length of the storage data buffer * \param[out] key_data On output, pointer to a newly allocated buffer * containing the key data. This must be freed * using psa_free_persistent_key_data() * \param[out] key_data_length Length of the key data buffer * \param[out] attr On success, the attribute structure is filled * with the loaded key metadata. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data, size_t storage_data_length, uint8_t **key_data, size_t *key_data_length, psa_key_attributes_t *attr); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /** This symbol is defined if transaction support is required. */ #define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS 1 #endif #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) /** The type of transaction that is in progress. */ /* This is an integer type rather than an enum for two reasons: to support * unknown values when loading a transaction file, and to ensure that the * type has a known size. */ typedef uint16_t psa_crypto_transaction_type_t; /** No transaction is in progress. * * This has the value 0, so zero-initialization sets a transaction's type to * this value. */ #define PSA_CRYPTO_TRANSACTION_NONE ((psa_crypto_transaction_type_t) 0x0000) /** A key creation transaction. * * This is only used for keys in an external cryptoprocessor (secure element). * Keys in RAM or in internal storage are created atomically in storage * (simple file creation), so they do not need a transaction mechanism. */ #define PSA_CRYPTO_TRANSACTION_CREATE_KEY ((psa_crypto_transaction_type_t) 0x0001) /** A key destruction transaction. * * This is only used for keys in an external cryptoprocessor (secure element). * Keys in RAM or in internal storage are destroyed atomically in storage * (simple file deletion), so they do not need a transaction mechanism. */ #define PSA_CRYPTO_TRANSACTION_DESTROY_KEY ((psa_crypto_transaction_type_t) 0x0002) /** Transaction data. * * This type is designed to be serialized by writing the memory representation * and reading it back on the same device. * * \note The transaction mechanism is not thread-safe. There can only be one * single active transaction at a time. * The transaction object is #psa_crypto_transaction. * * \note If an API call starts a transaction, it must complete this transaction * before returning to the application. * * The lifetime of a transaction is the following (note that only one * transaction may be active at a time): * * -# Call psa_crypto_prepare_transaction() to initialize the transaction * object in memory and declare the type of transaction that is starting. * -# Fill in the type-specific fields of #psa_crypto_transaction. * -# Call psa_crypto_save_transaction() to start the transaction. This * saves the transaction data to internal storage. * -# Perform the work of the transaction by modifying files, contacting * external entities, or whatever needs doing. Note that the transaction * may be interrupted by a power failure, so you need to have a way * recover from interruptions either by undoing what has been done * so far or by resuming where you left off. * -# If there are intermediate stages in the transaction, update * the fields of #psa_crypto_transaction and call * psa_crypto_save_transaction() again when each stage is reached. * -# When the transaction is over, call psa_crypto_stop_transaction() to * remove the transaction data in storage and in memory. * * If the system crashes while a transaction is in progress, psa_crypto_init() * calls psa_crypto_load_transaction() and takes care of completing or * rewinding the transaction. This is done in psa_crypto_recover_transaction() * in psa_crypto.c. If you add a new type of transaction, be * sure to add code for it in psa_crypto_recover_transaction(). */ typedef union { /* Each element of this union must have the following properties * to facilitate serialization and deserialization: * * - The element is a struct. * - The first field of the struct is `psa_crypto_transaction_type_t type`. * - Elements of the struct are arranged such a way that there is * no padding. */ struct psa_crypto_transaction_unknown_s { psa_crypto_transaction_type_t type; uint16_t unused1; uint32_t unused2; uint64_t unused3; uint64_t unused4; } unknown; /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */ struct psa_crypto_transaction_key_s { psa_crypto_transaction_type_t type; uint16_t unused1; psa_key_lifetime_t lifetime; psa_key_slot_number_t slot; mbedtls_svc_key_id_t id; } key; } psa_crypto_transaction_t; /** The single active transaction. */ extern psa_crypto_transaction_t psa_crypto_transaction; /** Prepare for a transaction. * * There must not be an ongoing transaction. * * \param type The type of transaction to start. */ static inline void psa_crypto_prepare_transaction( psa_crypto_transaction_type_t type) { psa_crypto_transaction.unknown.type = type; } /** Save the transaction data to storage. * * You may call this function multiple times during a transaction to * atomically update the transaction state. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription */ psa_status_t psa_crypto_save_transaction(void); /** Load the transaction data from storage, if any. * * This function is meant to be called from psa_crypto_init() to recover * in case a transaction was interrupted by a system crash. * * \retval #PSA_SUCCESS * The data about the ongoing transaction has been loaded to * #psa_crypto_transaction. * \retval #PSA_ERROR_DOES_NOT_EXIST * There is no ongoing transaction. * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ psa_status_t psa_crypto_load_transaction(void); /** Indicate that the current transaction is finished. * * Call this function at the very end of transaction processing. * This function does not "commit" or "abort" the transaction: the storage * subsystem has no concept of "commit" and "abort", just saving and * removing the transaction information in storage. * * This function erases the transaction data in storage (if any) and * resets the transaction data in memory. * * \retval #PSA_SUCCESS * There was transaction data in storage. * \retval #PSA_ERROR_DOES_NOT_EXIST * There was no transaction data in storage. * \retval #PSA_ERROR_STORAGE_FAILURE * It was impossible to determine whether there was transaction data * in storage, or the transaction data could not be erased. */ psa_status_t psa_crypto_stop_transaction(void); /** The ITS file identifier for the transaction data. * * 0xffffffNN = special file; 0x74 = 't' for transaction. */ #define PSA_CRYPTO_ITS_TRANSACTION_UID ((psa_key_id_t) 0xffffff74) #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) /** Backend side of mbedtls_psa_inject_entropy(). * * This function stores the supplied data into the entropy seed file. * * \retval #PSA_SUCCESS * Success * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The entropy seed file already exists. */ psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed, size_t seed_size); #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_STORAGE_H */ webfakes/src/mbedtls/library/ssl_debug_helpers_generated.c0000644000176200001440000002257614740737024023625 0ustar liggesusers/* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */ /** * \file ssl_debug_helpers_generated.c * * \brief Automatically generated helper functions for debugging */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * */ #include "common.h" #if defined(MBEDTLS_DEBUG_C) #include "ssl_debug_helpers.h" const char *mbedtls_ssl_named_group_to_str( uint16_t in ) { switch( in ) { case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1: return "secp192k1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1: return "secp192r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1: return "secp224k1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1: return "secp224r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1: return "secp256k1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1: return "secp256r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1: return "secp384r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1: return "secp521r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1: return "bp256r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1: return "bp384r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1: return "bp512r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_X25519: return "x25519"; case MBEDTLS_SSL_IANA_TLS_GROUP_X448: return "x448"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048: return "ffdhe2048"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072: return "ffdhe3072"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096: return "ffdhe4096"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144: return "ffdhe6144"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192: return "ffdhe8192"; }; return "UNKNOWN"; } const char *mbedtls_ssl_sig_alg_to_str( uint16_t in ) { switch( in ) { case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: return "rsa_pkcs1_sha256"; case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: return "rsa_pkcs1_sha384"; case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: return "rsa_pkcs1_sha512"; case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: return "ecdsa_secp256r1_sha256"; case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: return "ecdsa_secp384r1_sha384"; case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: return "ecdsa_secp521r1_sha512"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: return "rsa_pss_rsae_sha256"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: return "rsa_pss_rsae_sha384"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: return "rsa_pss_rsae_sha512"; case MBEDTLS_TLS1_3_SIG_ED25519: return "ed25519"; case MBEDTLS_TLS1_3_SIG_ED448: return "ed448"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256: return "rsa_pss_pss_sha256"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384: return "rsa_pss_pss_sha384"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512: return "rsa_pss_pss_sha512"; case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1: return "rsa_pkcs1_sha1"; case MBEDTLS_TLS1_3_SIG_ECDSA_SHA1: return "ecdsa_sha1"; case MBEDTLS_TLS1_3_SIG_NONE: return "none"; }; return "UNKNOWN"; } const char *mbedtls_ssl_states_str( mbedtls_ssl_states in ) { switch (in) { case MBEDTLS_SSL_HELLO_REQUEST: return "MBEDTLS_SSL_HELLO_REQUEST"; case MBEDTLS_SSL_CLIENT_HELLO: return "MBEDTLS_SSL_CLIENT_HELLO"; case MBEDTLS_SSL_SERVER_HELLO: return "MBEDTLS_SSL_SERVER_HELLO"; case MBEDTLS_SSL_SERVER_CERTIFICATE: return "MBEDTLS_SSL_SERVER_CERTIFICATE"; case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: return "MBEDTLS_SSL_SERVER_KEY_EXCHANGE"; case MBEDTLS_SSL_CERTIFICATE_REQUEST: return "MBEDTLS_SSL_CERTIFICATE_REQUEST"; case MBEDTLS_SSL_SERVER_HELLO_DONE: return "MBEDTLS_SSL_SERVER_HELLO_DONE"; case MBEDTLS_SSL_CLIENT_CERTIFICATE: return "MBEDTLS_SSL_CLIENT_CERTIFICATE"; case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: return "MBEDTLS_SSL_CLIENT_KEY_EXCHANGE"; case MBEDTLS_SSL_CERTIFICATE_VERIFY: return "MBEDTLS_SSL_CERTIFICATE_VERIFY"; case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: return "MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC"; case MBEDTLS_SSL_CLIENT_FINISHED: return "MBEDTLS_SSL_CLIENT_FINISHED"; case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: return "MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC"; case MBEDTLS_SSL_SERVER_FINISHED: return "MBEDTLS_SSL_SERVER_FINISHED"; case MBEDTLS_SSL_FLUSH_BUFFERS: return "MBEDTLS_SSL_FLUSH_BUFFERS"; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: return "MBEDTLS_SSL_HANDSHAKE_WRAPUP"; case MBEDTLS_SSL_NEW_SESSION_TICKET: return "MBEDTLS_SSL_NEW_SESSION_TICKET"; case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: return "MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT"; case MBEDTLS_SSL_HELLO_RETRY_REQUEST: return "MBEDTLS_SSL_HELLO_RETRY_REQUEST"; case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: return "MBEDTLS_SSL_ENCRYPTED_EXTENSIONS"; case MBEDTLS_SSL_END_OF_EARLY_DATA: return "MBEDTLS_SSL_END_OF_EARLY_DATA"; case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: return "MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY"; case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: return "MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED"; case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: return "MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO"; case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO: return "MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO"; case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: return "MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO"; case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST: return "MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST"; case MBEDTLS_SSL_HANDSHAKE_OVER: return "MBEDTLS_SSL_HANDSHAKE_OVER"; case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: return "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET"; case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH: return "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH"; default: return "UNKNOWN_VALUE"; } } #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) const char *mbedtls_ssl_early_data_status_str( mbedtls_ssl_early_data_status in ) { switch (in) { case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED: return "MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED"; case MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED: return "MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED"; case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED: return "MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED"; default: return "UNKNOWN_VALUE"; } } #endif /* defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) */ const char *mbedtls_ssl_protocol_version_str( mbedtls_ssl_protocol_version in ) { switch (in) { case MBEDTLS_SSL_VERSION_UNKNOWN: return "MBEDTLS_SSL_VERSION_UNKNOWN"; case MBEDTLS_SSL_VERSION_TLS1_2: return "MBEDTLS_SSL_VERSION_TLS1_2"; case MBEDTLS_SSL_VERSION_TLS1_3: return "MBEDTLS_SSL_VERSION_TLS1_3"; default: return "UNKNOWN_VALUE"; } } const char *mbedtls_tls_prf_types_str( mbedtls_tls_prf_types in ) { switch (in) { case MBEDTLS_SSL_TLS_PRF_NONE: return "MBEDTLS_SSL_TLS_PRF_NONE"; case MBEDTLS_SSL_TLS_PRF_SHA384: return "MBEDTLS_SSL_TLS_PRF_SHA384"; case MBEDTLS_SSL_TLS_PRF_SHA256: return "MBEDTLS_SSL_TLS_PRF_SHA256"; case MBEDTLS_SSL_HKDF_EXPAND_SHA384: return "MBEDTLS_SSL_HKDF_EXPAND_SHA384"; case MBEDTLS_SSL_HKDF_EXPAND_SHA256: return "MBEDTLS_SSL_HKDF_EXPAND_SHA256"; default: return "UNKNOWN_VALUE"; } } const char *mbedtls_ssl_key_export_type_str( mbedtls_ssl_key_export_type in ) { switch (in) { case MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET"; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET"; #endif default: return "UNKNOWN_VALUE"; } } #endif /* MBEDTLS_DEBUG_C */ /* End of automatically generated file. */ webfakes/src/mbedtls/library/ssl_tls.c0000644000176200001440000117606214740737024017602 0ustar liggesusers/* * TLS shared functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * http://www.ietf.org/rfc/rfc2246.txt * http://www.ietf.org/rfc/rfc4346.txt */ #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "ssl_client.h" #include "ssl_debug_helpers.h" #include "ssl_misc.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/version.h" #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/psa_util.h" #include "md_psa.h" #include "psa_util_internal.h" #include "psa/crypto.h" #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #include "mbedtls/oid.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Define local translating functions to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif #if defined(MBEDTLS_TEST_HOOKS) static mbedtls_ssl_chk_buf_ptr_args chk_buf_ptr_fail_args; void mbedtls_ssl_set_chk_buf_ptr_fail_args( const uint8_t *cur, const uint8_t *end, size_t need) { chk_buf_ptr_fail_args.cur = cur; chk_buf_ptr_fail_args.end = end; chk_buf_ptr_fail_args.need = need; } void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void) { memset(&chk_buf_ptr_fail_args, 0, sizeof(chk_buf_ptr_fail_args)); } int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args) { return (chk_buf_ptr_fail_args.cur != args->cur) || (chk_buf_ptr_fail_args.end != args->end) || (chk_buf_ptr_fail_args.need != args->need); } #endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* Top-level Connection ID API */ int mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf, size_t len, int ignore_other_cid) { if (len > MBEDTLS_SSL_CID_IN_LEN_MAX) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_FAIL && ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->ignore_unexpected_cid = ignore_other_cid; conf->cid_len = len; return 0; } int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl, int enable, unsigned char const *own_cid, size_t own_cid_len) { if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->negotiate_cid = enable; if (enable == MBEDTLS_SSL_CID_DISABLED) { MBEDTLS_SSL_DEBUG_MSG(3, ("Disable use of CID extension.")); return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("Enable use of CID extension.")); MBEDTLS_SSL_DEBUG_BUF(3, "Own CID", own_cid, own_cid_len); if (own_cid_len != ssl->conf->cid_len) { MBEDTLS_SSL_DEBUG_MSG(3, ("CID length %u does not match CID length %u in config", (unsigned) own_cid_len, (unsigned) ssl->conf->cid_len)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(ssl->own_cid, own_cid, own_cid_len); /* Truncation is not an issue here because * MBEDTLS_SSL_CID_IN_LEN_MAX at most 255. */ ssl->own_cid_len = (uint8_t) own_cid_len; return 0; } int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl, int *enabled, unsigned char own_cid[MBEDTLS_SSL_CID_IN_LEN_MAX], size_t *own_cid_len) { *enabled = MBEDTLS_SSL_CID_DISABLED; if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* We report MBEDTLS_SSL_CID_DISABLED in case the CID length is * zero as this is indistinguishable from not requesting to use * the CID extension. */ if (ssl->own_cid_len == 0 || ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { return 0; } if (own_cid_len != NULL) { *own_cid_len = ssl->own_cid_len; if (own_cid != NULL) { memcpy(own_cid, ssl->own_cid, ssl->own_cid_len); } } *enabled = MBEDTLS_SSL_CID_ENABLED; return 0; } int mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl, int *enabled, unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], size_t *peer_cid_len) { *enabled = MBEDTLS_SSL_CID_DISABLED; if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || mbedtls_ssl_is_handshake_over(ssl) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* We report MBEDTLS_SSL_CID_DISABLED in case the CID extensions * were used, but client and server requested the empty CID. * This is indistinguishable from not using the CID extension * in the first place. */ if (ssl->transform_in->in_cid_len == 0 && ssl->transform_in->out_cid_len == 0) { return 0; } if (peer_cid_len != NULL) { *peer_cid_len = ssl->transform_in->out_cid_len; if (peer_cid != NULL) { memcpy(peer_cid, ssl->transform_in->out_cid, ssl->transform_in->out_cid_len); } } *enabled = MBEDTLS_SSL_CID_ENABLED; return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /* * Convert max_fragment_length codes to length. * RFC 6066 says: * enum{ * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) * } MaxFragmentLength; * and we add 0 -> extension unused */ static unsigned int ssl_mfl_code_to_length(int mfl) { switch (mfl) { case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: return MBEDTLS_TLS_EXT_ADV_CONTENT_LEN; case MBEDTLS_SSL_MAX_FRAG_LEN_512: return 512; case MBEDTLS_SSL_MAX_FRAG_LEN_1024: return 1024; case MBEDTLS_SSL_MAX_FRAG_LEN_2048: return 2048; case MBEDTLS_SSL_MAX_FRAG_LEN_4096: return 4096; default: return MBEDTLS_TLS_EXT_ADV_CONTENT_LEN; } } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, const mbedtls_ssl_session *src) { mbedtls_ssl_session_free(dst); memcpy(dst, src, sizeof(mbedtls_ssl_session)); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) dst->ticket = NULL; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) dst->hostname = NULL; #endif #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \ defined(MBEDTLS_SSL_EARLY_DATA) dst->ticket_alpn = NULL; #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if (src->peer_cert != NULL) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; dst->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); if (dst->peer_cert == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } mbedtls_x509_crt_init(dst->peer_cert); if ((ret = mbedtls_x509_crt_parse_der(dst->peer_cert, src->peer_cert->raw.p, src->peer_cert->raw.len)) != 0) { mbedtls_free(dst->peer_cert); dst->peer_cert = NULL; return ret; } } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (src->peer_cert_digest != NULL) { dst->peer_cert_digest = mbedtls_calloc(1, src->peer_cert_digest_len); if (dst->peer_cert_digest == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(dst->peer_cert_digest, src->peer_cert_digest, src->peer_cert_digest_len); dst->peer_cert_digest_type = src->peer_cert_digest_type; dst->peer_cert_digest_len = src->peer_cert_digest_len; } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \ defined(MBEDTLS_SSL_EARLY_DATA) { int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn); if (ret != 0) { return ret; } } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN && MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) if (src->ticket != NULL) { dst->ticket = mbedtls_calloc(1, src->ticket_len); if (dst->ticket == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(dst->ticket, src->ticket, src->ticket_len); } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (src->endpoint == MBEDTLS_SSL_IS_CLIENT) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_session_set_hostname(dst, src->hostname); if (ret != 0) { return ret; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ return 0; } #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) MBEDTLS_CHECK_RETURN_CRITICAL static int resize_buffer(unsigned char **buffer, size_t len_new, size_t *len_old) { unsigned char *resized_buffer = mbedtls_calloc(1, len_new); if (resized_buffer == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } /* We want to copy len_new bytes when downsizing the buffer, and * len_old bytes when upsizing, so we choose the smaller of two sizes, * to fit one buffer into another. Size checks, ensuring that no data is * lost, are done outside of this function. */ memcpy(resized_buffer, *buffer, (len_new < *len_old) ? len_new : *len_old); mbedtls_zeroize_and_free(*buffer, *len_old); *buffer = resized_buffer; *len_old = len_new; return 0; } static void handle_buffer_resizing(mbedtls_ssl_context *ssl, int downsizing, size_t in_buf_new_len, size_t out_buf_new_len) { int modified = 0; size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0; size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0; if (ssl->in_buf != NULL) { written_in = ssl->in_msg - ssl->in_buf; iv_offset_in = ssl->in_iv - ssl->in_buf; len_offset_in = ssl->in_len - ssl->in_buf; if (downsizing ? ssl->in_buf_len > in_buf_new_len && ssl->in_left < in_buf_new_len : ssl->in_buf_len < in_buf_new_len) { if (resize_buffer(&ssl->in_buf, in_buf_new_len, &ssl->in_buf_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("input buffer resizing failed - out of memory")); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Reallocating in_buf to %" MBEDTLS_PRINTF_SIZET, in_buf_new_len)); modified = 1; } } } if (ssl->out_buf != NULL) { written_out = ssl->out_msg - ssl->out_buf; iv_offset_out = ssl->out_iv - ssl->out_buf; len_offset_out = ssl->out_len - ssl->out_buf; if (downsizing ? ssl->out_buf_len > out_buf_new_len && ssl->out_left < out_buf_new_len : ssl->out_buf_len < out_buf_new_len) { if (resize_buffer(&ssl->out_buf, out_buf_new_len, &ssl->out_buf_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("output buffer resizing failed - out of memory")); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Reallocating out_buf to %" MBEDTLS_PRINTF_SIZET, out_buf_new_len)); modified = 1; } } } if (modified) { /* Update pointers here to avoid doing it twice. */ mbedtls_ssl_reset_in_out_pointers(ssl); /* Fields below might not be properly updated with record * splitting or with CID, so they are manually updated here. */ ssl->out_msg = ssl->out_buf + written_out; ssl->out_len = ssl->out_buf + len_offset_out; ssl->out_iv = ssl->out_buf + iv_offset_out; ssl->in_msg = ssl->in_buf + written_in; ssl->in_len = ssl->in_buf + len_offset_in; ssl->in_iv = ssl->in_buf + iv_offset_in; } } #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) typedef int (*tls_prf_fn)(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id); #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /* Type for the TLS PRF */ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, const unsigned char *, size_t, unsigned char *, size_t); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform, int ciphersuite, const unsigned char master[48], #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) int encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ ssl_tls_prf_t tls_prf, const unsigned char randbytes[64], mbedtls_ssl_protocol_version tls_version, unsigned endpoint, const mbedtls_ssl_context *ssl); #if defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha256(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); static int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *); static int ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int); #endif /* MBEDTLS_MD_CAN_SHA256*/ #if defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha384(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); static int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *); static int ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int); #endif /* MBEDTLS_MD_CAN_SHA384*/ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ static int ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t); #if defined(MBEDTLS_MD_CAN_SHA256) static int ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t); #endif /* MBEDTLS_MD_CAN_SHA256*/ #if defined(MBEDTLS_MD_CAN_SHA384) static int ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t); #endif /* MBEDTLS_MD_CAN_SHA384*/ int mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf, const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { mbedtls_ssl_tls_prf_cb *tls_prf = NULL; switch (prf) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_SSL_TLS_PRF_SHA384: tls_prf = tls_prf_sha384; break; #endif /* MBEDTLS_MD_CAN_SHA384*/ #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_SSL_TLS_PRF_SHA256: tls_prf = tls_prf_sha256; break; #endif /* MBEDTLS_MD_CAN_SHA256*/ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ default: return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } return tls_prf(secret, slen, label, random, rlen, dstbuf, dlen); } #if defined(MBEDTLS_X509_CRT_PARSE_C) static void ssl_clear_peer_cert(mbedtls_ssl_session *session) { #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if (session->peer_cert != NULL) { mbedtls_x509_crt_free(session->peer_cert); mbedtls_free(session->peer_cert); session->peer_cert = NULL; } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (session->peer_cert_digest != NULL) { /* Zeroization is not necessary. */ mbedtls_free(session->peer_cert_digest); session->peer_cert_digest = NULL; session->peer_cert_digest_type = MBEDTLS_MD_NONE; session->peer_cert_digest_len = 0; } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ } #endif /* MBEDTLS_X509_CRT_PARSE_C */ uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type) { switch (extension_type) { case MBEDTLS_TLS_EXT_SERVERNAME: return MBEDTLS_SSL_EXT_ID_SERVERNAME; case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: return MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH; case MBEDTLS_TLS_EXT_STATUS_REQUEST: return MBEDTLS_SSL_EXT_ID_STATUS_REQUEST; case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: return MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS; case MBEDTLS_TLS_EXT_SIG_ALG: return MBEDTLS_SSL_EXT_ID_SIG_ALG; case MBEDTLS_TLS_EXT_USE_SRTP: return MBEDTLS_SSL_EXT_ID_USE_SRTP; case MBEDTLS_TLS_EXT_HEARTBEAT: return MBEDTLS_SSL_EXT_ID_HEARTBEAT; case MBEDTLS_TLS_EXT_ALPN: return MBEDTLS_SSL_EXT_ID_ALPN; case MBEDTLS_TLS_EXT_SCT: return MBEDTLS_SSL_EXT_ID_SCT; case MBEDTLS_TLS_EXT_CLI_CERT_TYPE: return MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE; case MBEDTLS_TLS_EXT_SERV_CERT_TYPE: return MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE; case MBEDTLS_TLS_EXT_PADDING: return MBEDTLS_SSL_EXT_ID_PADDING; case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: return MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY; case MBEDTLS_TLS_EXT_EARLY_DATA: return MBEDTLS_SSL_EXT_ID_EARLY_DATA; case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: return MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS; case MBEDTLS_TLS_EXT_COOKIE: return MBEDTLS_SSL_EXT_ID_COOKIE; case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES: return MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES; case MBEDTLS_TLS_EXT_CERT_AUTH: return MBEDTLS_SSL_EXT_ID_CERT_AUTH; case MBEDTLS_TLS_EXT_OID_FILTERS: return MBEDTLS_SSL_EXT_ID_OID_FILTERS; case MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH: return MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH; case MBEDTLS_TLS_EXT_SIG_ALG_CERT: return MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT; case MBEDTLS_TLS_EXT_KEY_SHARE: return MBEDTLS_SSL_EXT_ID_KEY_SHARE; case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: return MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC; case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: return MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS; case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: return MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC; case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: return MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET; case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: return MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT; case MBEDTLS_TLS_EXT_SESSION_TICKET: return MBEDTLS_SSL_EXT_ID_SESSION_TICKET; } return MBEDTLS_SSL_EXT_ID_UNRECOGNIZED; } uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type) { return 1 << mbedtls_ssl_get_extension_id(extension_type); } #if defined(MBEDTLS_DEBUG_C) static const char *extension_name_table[] = { [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = "unrecognized", [MBEDTLS_SSL_EXT_ID_SERVERNAME] = "server_name", [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = "max_fragment_length", [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = "status_request", [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = "supported_groups", [MBEDTLS_SSL_EXT_ID_SIG_ALG] = "signature_algorithms", [MBEDTLS_SSL_EXT_ID_USE_SRTP] = "use_srtp", [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = "heartbeat", [MBEDTLS_SSL_EXT_ID_ALPN] = "application_layer_protocol_negotiation", [MBEDTLS_SSL_EXT_ID_SCT] = "signed_certificate_timestamp", [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = "client_certificate_type", [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = "server_certificate_type", [MBEDTLS_SSL_EXT_ID_PADDING] = "padding", [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = "pre_shared_key", [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = "early_data", [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = "supported_versions", [MBEDTLS_SSL_EXT_ID_COOKIE] = "cookie", [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = "psk_key_exchange_modes", [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = "certificate_authorities", [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = "oid_filters", [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = "post_handshake_auth", [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = "signature_algorithms_cert", [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = "key_share", [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = "truncated_hmac", [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = "supported_point_formats", [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = "encrypt_then_mac", [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = "extended_master_secret", [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = "session_ticket", [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = "record_size_limit" }; static const unsigned int extension_type_table[] = { [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = 0xff, [MBEDTLS_SSL_EXT_ID_SERVERNAME] = MBEDTLS_TLS_EXT_SERVERNAME, [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = MBEDTLS_TLS_EXT_STATUS_REQUEST, [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, [MBEDTLS_SSL_EXT_ID_SIG_ALG] = MBEDTLS_TLS_EXT_SIG_ALG, [MBEDTLS_SSL_EXT_ID_USE_SRTP] = MBEDTLS_TLS_EXT_USE_SRTP, [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = MBEDTLS_TLS_EXT_HEARTBEAT, [MBEDTLS_SSL_EXT_ID_ALPN] = MBEDTLS_TLS_EXT_ALPN, [MBEDTLS_SSL_EXT_ID_SCT] = MBEDTLS_TLS_EXT_SCT, [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = MBEDTLS_TLS_EXT_CLI_CERT_TYPE, [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = MBEDTLS_TLS_EXT_SERV_CERT_TYPE, [MBEDTLS_SSL_EXT_ID_PADDING] = MBEDTLS_TLS_EXT_PADDING, [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = MBEDTLS_TLS_EXT_PRE_SHARED_KEY, [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = MBEDTLS_TLS_EXT_EARLY_DATA, [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, [MBEDTLS_SSL_EXT_ID_COOKIE] = MBEDTLS_TLS_EXT_COOKIE, [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = MBEDTLS_TLS_EXT_CERT_AUTH, [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = MBEDTLS_TLS_EXT_OID_FILTERS, [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH, [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = MBEDTLS_TLS_EXT_SIG_ALG_CERT, [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = MBEDTLS_TLS_EXT_KEY_SHARE, [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = MBEDTLS_TLS_EXT_TRUNCATED_HMAC, [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = MBEDTLS_TLS_EXT_SESSION_TICKET, [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT }; const char *mbedtls_ssl_get_extension_name(unsigned int extension_type) { return extension_name_table[ mbedtls_ssl_get_extension_id(extension_type)]; } static const char *ssl_tls13_get_hs_msg_name(int hs_msg_type) { switch (hs_msg_type) { case MBEDTLS_SSL_HS_CLIENT_HELLO: return "ClientHello"; case MBEDTLS_SSL_HS_SERVER_HELLO: return "ServerHello"; case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST: return "HelloRetryRequest"; case MBEDTLS_SSL_HS_NEW_SESSION_TICKET: return "NewSessionTicket"; case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS: return "EncryptedExtensions"; case MBEDTLS_SSL_HS_CERTIFICATE: return "Certificate"; case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST: return "CertificateRequest"; } return "Unknown"; } void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl, int level, const char *file, int line, int hs_msg_type, unsigned int extension_type, const char *extra_msg0, const char *extra_msg1) { const char *extra_msg; if (extra_msg0 && extra_msg1) { mbedtls_debug_print_msg( ssl, level, file, line, "%s: %s(%u) extension %s %s.", ssl_tls13_get_hs_msg_name(hs_msg_type), mbedtls_ssl_get_extension_name(extension_type), extension_type, extra_msg0, extra_msg1); return; } extra_msg = extra_msg0 ? extra_msg0 : extra_msg1; if (extra_msg) { mbedtls_debug_print_msg( ssl, level, file, line, "%s: %s(%u) extension %s.", ssl_tls13_get_hs_msg_name(hs_msg_type), mbedtls_ssl_get_extension_name(extension_type), extension_type, extra_msg); return; } mbedtls_debug_print_msg( ssl, level, file, line, "%s: %s(%u) extension.", ssl_tls13_get_hs_msg_name(hs_msg_type), mbedtls_ssl_get_extension_name(extension_type), extension_type); } void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl, int level, const char *file, int line, int hs_msg_type, uint32_t extensions_mask, const char *extra) { for (unsigned i = 0; i < sizeof(extension_name_table) / sizeof(extension_name_table[0]); i++) { mbedtls_ssl_print_extension( ssl, level, file, line, hs_msg_type, extension_type_table[i], extensions_mask & (1 << i) ? "exists" : "does not exist", extra); } } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) static const char *ticket_flag_name_table[] = { [0] = "ALLOW_PSK_RESUMPTION", [2] = "ALLOW_PSK_EPHEMERAL_RESUMPTION", [3] = "ALLOW_EARLY_DATA", }; void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl, int level, const char *file, int line, unsigned int flags) { size_t i; mbedtls_debug_print_msg(ssl, level, file, line, "print ticket_flags (0x%02x)", flags); flags = flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK; for (i = 0; i < ARRAY_LENGTH(ticket_flag_name_table); i++) { if ((flags & (1 << i))) { mbedtls_debug_print_msg(ssl, level, file, line, "- %s is set.", ticket_flag_name_table[i]); } } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ #endif /* MBEDTLS_DEBUG_C */ void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info) { ((void) ciphersuite_info); #if defined(MBEDTLS_MD_CAN_SHA384) if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) { ssl->handshake->update_checksum = ssl_update_checksum_sha384; } else #endif #if defined(MBEDTLS_MD_CAN_SHA256) if (ciphersuite_info->mac != MBEDTLS_MD_SHA384) { ssl->handshake->update_checksum = ssl_update_checksum_sha256; } else #endif { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return; } } int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl, unsigned hs_type, size_t total_hs_len) { unsigned char hs_hdr[4]; /* Build HS header for checksum update. */ hs_hdr[0] = MBEDTLS_BYTE_0(hs_type); hs_hdr[1] = MBEDTLS_BYTE_2(total_hs_len); hs_hdr[2] = MBEDTLS_BYTE_1(total_hs_len); hs_hdr[3] = MBEDTLS_BYTE_0(total_hs_len); return ssl->handshake->update_checksum(ssl, hs_hdr, sizeof(hs_hdr)); } int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl, unsigned hs_type, unsigned char const *msg, size_t msg_len) { int ret; ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, hs_type, msg_len); if (ret != 0) { return ret; } return ssl->handshake->update_checksum(ssl, msg, msg_len); } int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_MD_CAN_SHA256) || \ defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif #else /* SHA-256 or SHA-384 */ ((void) ssl); #endif /* SHA-256 or SHA-384 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_abort(&ssl->handshake->fin_sha256_psa); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } #else mbedtls_md_free(&ssl->handshake->fin_sha256); mbedtls_md_init(&ssl->handshake->fin_sha256); ret = mbedtls_md_setup(&ssl->handshake->fin_sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0); if (ret != 0) { return ret; } ret = mbedtls_md_starts(&ssl->handshake->fin_sha256); if (ret != 0) { return ret; } #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_abort(&ssl->handshake->fin_sha384_psa); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } #else mbedtls_md_free(&ssl->handshake->fin_sha384); mbedtls_md_init(&ssl->handshake->fin_sha384); ret = mbedtls_md_setup(&ssl->handshake->fin_sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); if (ret != 0) { return ret; } ret = mbedtls_md_starts(&ssl->handshake->fin_sha384); if (ret != 0) { return ret; } #endif #endif return 0; } static int ssl_update_checksum_start(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_MD_CAN_SHA256) || \ defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif #else /* SHA-256 or SHA-384 */ ((void) ssl); (void) buf; (void) len; #endif /* SHA-256 or SHA-384 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } #else ret = mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len); if (ret != 0) { return ret; } #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } #else ret = mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len); if (ret != 0) { return ret; } #endif #endif return 0; } #if defined(MBEDTLS_MD_CAN_SHA256) static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) return mbedtls_md_error_from_psa(psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len)); #else return mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len); #endif } #endif #if defined(MBEDTLS_MD_CAN_SHA384) static int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) return mbedtls_md_error_from_psa(psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len)); #else return mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len); #endif } #endif static void ssl_handshake_params_init(mbedtls_ssl_handshake_params *handshake) { memset(handshake, 0, sizeof(mbedtls_ssl_handshake_params)); #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) handshake->fin_sha256_psa = psa_hash_operation_init(); #else mbedtls_md_init(&handshake->fin_sha256); #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) handshake->fin_sha384_psa = psa_hash_operation_init(); #else mbedtls_md_init(&handshake->fin_sha384); #endif #endif handshake->update_checksum = ssl_update_checksum_start; #if defined(MBEDTLS_DHM_C) mbedtls_dhm_init(&handshake->dhm_ctx); #endif #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) mbedtls_ecdh_init(&handshake->ecdh_ctx); #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) handshake->psa_pake_ctx = psa_pake_operation_init(); handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_ecjpake_init(&handshake->ecjpake_ctx); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) handshake->ecjpake_cache = NULL; handshake->ecjpake_cache_len = 0; #endif #endif #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) mbedtls_x509_crt_restart_init(&handshake->ecrs_ctx); #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) mbedtls_pk_init(&handshake->peer_pubkey); #endif } void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform) { memset(transform, 0, sizeof(mbedtls_ssl_transform)); #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_key_enc = MBEDTLS_SVC_KEY_ID_INIT; transform->psa_key_dec = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_cipher_init(&transform->cipher_ctx_enc); mbedtls_cipher_init(&transform->cipher_ctx_dec); #endif #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_mac_enc = MBEDTLS_SVC_KEY_ID_INIT; transform->psa_mac_dec = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_md_init(&transform->md_ctx_enc); mbedtls_md_init(&transform->md_ctx_dec); #endif #endif } void mbedtls_ssl_session_init(mbedtls_ssl_session *session) { memset(session, 0, sizeof(mbedtls_ssl_session)); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_handshake_init(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Clear old handshake information if present */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->transform_negotiate) { mbedtls_ssl_transform_free(ssl->transform_negotiate); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ if (ssl->session_negotiate) { mbedtls_ssl_session_free(ssl->session_negotiate); } if (ssl->handshake) { mbedtls_ssl_handshake_free(ssl); } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * Either the pointers are now NULL or cleared properly and can be freed. * Now allocate missing structures. */ if (ssl->transform_negotiate == NULL) { ssl->transform_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ if (ssl->session_negotiate == NULL) { ssl->session_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_session)); } if (ssl->handshake == NULL) { ssl->handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_handshake_params)); } #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) /* If the buffers are too small - reallocate */ handle_buffer_resizing(ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN, MBEDTLS_SSL_OUT_BUFFER_LEN); #endif /* All pointers should exist and can be directly freed without issue */ if (ssl->handshake == NULL || #if defined(MBEDTLS_SSL_PROTO_TLS1_2) ssl->transform_negotiate == NULL || #endif ssl->session_negotiate == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc() of ssl sub-contexts failed")); mbedtls_free(ssl->handshake); ssl->handshake = NULL; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_free(ssl->transform_negotiate); ssl->transform_negotiate = NULL; #endif mbedtls_free(ssl->session_negotiate); ssl->session_negotiate = NULL; return MBEDTLS_ERR_SSL_ALLOC_FAILED; } #if defined(MBEDTLS_SSL_EARLY_DATA) #if defined(MBEDTLS_SSL_CLI_C) ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IDLE; #endif #if defined(MBEDTLS_SSL_SRV_C) ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; #endif ssl->total_early_data_size = 0; #endif /* MBEDTLS_SSL_EARLY_DATA */ /* Initialize structures */ mbedtls_ssl_session_init(ssl->session_negotiate); ssl_handshake_params_init(ssl->handshake); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_ssl_transform_init(ssl->transform_negotiate); #endif /* Setup handshake checksums */ ret = mbedtls_ssl_reset_checksum(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret); return ret; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) ssl->handshake->new_session_tickets_count = ssl->conf->new_session_tickets_count; #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->handshake->alt_transform_out = ssl->transform_out; if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; } else { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; } mbedtls_ssl_set_timer(ssl, 0); } #endif /* * curve_list is translated to IANA TLS group identifiers here because * mbedtls_ssl_conf_curves returns void and so can't return * any error codes. */ #if defined(MBEDTLS_ECP_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /* Heap allocate and translate curve_list from internal to IANA group ids */ if (ssl->conf->curve_list != NULL) { size_t length; const mbedtls_ecp_group_id *curve_list = ssl->conf->curve_list; for (length = 0; (curve_list[length] != MBEDTLS_ECP_DP_NONE); length++) { } /* Leave room for zero termination */ uint16_t *group_list = mbedtls_calloc(length + 1, sizeof(uint16_t)); if (group_list == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } for (size_t i = 0; i < length; i++) { uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( curve_list[i]); if (tls_id == 0) { mbedtls_free(group_list); return MBEDTLS_ERR_SSL_BAD_CONFIG; } group_list[i] = tls_id; } group_list[length] = 0; ssl->handshake->group_list = group_list; ssl->handshake->group_list_heap_allocated = 1; } else { ssl->handshake->group_list = ssl->conf->group_list; ssl->handshake->group_list_heap_allocated = 0; } #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* Heap allocate and translate sig_hashes from internal hash identifiers to signature algorithms IANA identifiers. */ if (mbedtls_ssl_conf_is_tls12_only(ssl->conf) && ssl->conf->sig_hashes != NULL) { const int *md; const int *sig_hashes = ssl->conf->sig_hashes; size_t sig_algs_len = 0; uint16_t *p; MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN <= (SIZE_MAX - (2 * sizeof(uint16_t))), "MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN too big"); for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) { if (mbedtls_ssl_hash_from_md_alg(*md) == MBEDTLS_SSL_HASH_NONE) { continue; } #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) sig_algs_len += sizeof(uint16_t); #endif #if defined(MBEDTLS_RSA_C) sig_algs_len += sizeof(uint16_t); #endif if (sig_algs_len > MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } } if (sig_algs_len < MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } ssl->handshake->sig_algs = mbedtls_calloc(1, sig_algs_len + sizeof(uint16_t)); if (ssl->handshake->sig_algs == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } p = (uint16_t *) ssl->handshake->sig_algs; for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) { unsigned char hash = mbedtls_ssl_hash_from_md_alg(*md); if (hash == MBEDTLS_SSL_HASH_NONE) { continue; } #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) *p = ((hash << 8) | MBEDTLS_SSL_SIG_ECDSA); p++; #endif #if defined(MBEDTLS_RSA_C) *p = ((hash << 8) | MBEDTLS_SSL_SIG_RSA); p++; #endif } *p = MBEDTLS_TLS_SIG_NONE; ssl->handshake->sig_algs_heap_allocated = 1; } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ { ssl->handshake->sig_algs_heap_allocated = 0; } #endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ return 0; } #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /* Dummy cookie callbacks for defaults */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cookie_write_dummy(void *ctx, unsigned char **p, unsigned char *end, const unsigned char *cli_id, size_t cli_id_len) { ((void) ctx); ((void) p); ((void) end); ((void) cli_id); ((void) cli_id_len); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cookie_check_dummy(void *ctx, const unsigned char *cookie, size_t cookie_len, const unsigned char *cli_id, size_t cli_id_len) { ((void) ctx); ((void) cookie); ((void) cookie_len); ((void) cli_id); ((void) cli_id_len); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ /* * Initialize an SSL context */ void mbedtls_ssl_init(mbedtls_ssl_context *ssl) { memset(ssl, 0, sizeof(mbedtls_ssl_context)); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_version_check(const mbedtls_ssl_context *ssl) { const mbedtls_ssl_config *conf = ssl->conf; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (mbedtls_ssl_conf_is_tls13_only(conf)) { if (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS 1.3 is not yet supported.")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls13 only.")); return 0; } #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (mbedtls_ssl_conf_is_tls12_only(conf)) { MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls12 only.")); return 0; } #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) if (mbedtls_ssl_conf_is_hybrid_tls12_tls13(conf)) { if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS not yet supported in Hybrid TLS 1.3 + TLS 1.2")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is TLS 1.3 or TLS 1.2.")); return 0; } #endif MBEDTLS_SSL_DEBUG_MSG(1, ("The SSL configuration is invalid.")); return MBEDTLS_ERR_SSL_BAD_CONFIG; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_check(const mbedtls_ssl_context *ssl) { int ret; ret = ssl_conf_version_check(ssl); if (ret != 0) { return ret; } if (ssl->conf->f_rng == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided")); return MBEDTLS_ERR_SSL_NO_RNG; } /* Space for further checks */ return 0; } /* * Setup an SSL context */ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; ssl->conf = conf; if ((ret = ssl_conf_check(ssl)) != 0) { return ret; } ssl->tls_version = ssl->conf->max_tls_version; /* * Prepare base structures */ /* Set to NULL in case of an error condition */ ssl->out_buf = NULL; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) ssl->in_buf_len = in_buf_len; #endif ssl->in_buf = mbedtls_calloc(1, in_buf_len); if (ssl->in_buf == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len)); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto error; } #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) ssl->out_buf_len = out_buf_len; #endif ssl->out_buf = mbedtls_calloc(1, out_buf_len); if (ssl->out_buf == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len)); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto error; } mbedtls_ssl_reset_in_out_pointers(ssl); #if defined(MBEDTLS_SSL_DTLS_SRTP) memset(&ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info)); #endif if ((ret = ssl_handshake_init(ssl)) != 0) { goto error; } return 0; error: mbedtls_free(ssl->in_buf); mbedtls_free(ssl->out_buf); ssl->conf = NULL; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) ssl->in_buf_len = 0; ssl->out_buf_len = 0; #endif ssl->in_buf = NULL; ssl->out_buf = NULL; ssl->in_hdr = NULL; ssl->in_ctr = NULL; ssl->in_len = NULL; ssl->in_iv = NULL; ssl->in_msg = NULL; ssl->out_hdr = NULL; ssl->out_ctr = NULL; ssl->out_len = NULL; ssl->out_iv = NULL; ssl->out_msg = NULL; return ret; } /* * Reset an initialized and used SSL context for re-use while retaining * all application-set variables, function pointers and data. * * If partial is non-zero, keep data in the input buffer and client ID. * (Use when a DTLS client reconnects from the same port.) */ void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, int partial) { #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t in_buf_len = ssl->in_buf_len; size_t out_buf_len = ssl->out_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #endif #if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || !defined(MBEDTLS_SSL_SRV_C) partial = 0; #endif /* Cancel any possibly running timer */ mbedtls_ssl_set_timer(ssl, 0); mbedtls_ssl_reset_in_out_pointers(ssl); /* Reset incoming message parsing */ ssl->in_offt = NULL; ssl->nb_zero = 0; ssl->in_msgtype = 0; ssl->in_msglen = 0; ssl->in_hslen = 0; ssl->keep_current_message = 0; ssl->transform_in = NULL; #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->next_record_offset = 0; ssl->in_epoch = 0; #endif /* Keep current datagram if partial == 1 */ if (partial == 0) { ssl->in_left = 0; memset(ssl->in_buf, 0, in_buf_len); } ssl->send_alert = 0; /* Reset outgoing message writing */ ssl->out_msgtype = 0; ssl->out_msglen = 0; ssl->out_left = 0; memset(ssl->out_buf, 0, out_buf_len); memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); ssl->transform_out = NULL; #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) mbedtls_ssl_dtls_replay_reset(ssl); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->transform) { mbedtls_ssl_transform_free(ssl->transform); mbedtls_free(ssl->transform); ssl->transform = NULL; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_transform_free(ssl->transform_application); mbedtls_free(ssl->transform_application); ssl->transform_application = NULL; if (ssl->handshake != NULL) { #if defined(MBEDTLS_SSL_EARLY_DATA) mbedtls_ssl_transform_free(ssl->handshake->transform_earlydata); mbedtls_free(ssl->handshake->transform_earlydata); ssl->handshake->transform_earlydata = NULL; #endif mbedtls_ssl_transform_free(ssl->handshake->transform_handshake); mbedtls_free(ssl->handshake->transform_handshake); ssl->handshake->transform_handshake = NULL; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ } int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ssl->state = MBEDTLS_SSL_HELLO_REQUEST; ssl->tls_version = ssl->conf->max_tls_version; mbedtls_ssl_session_reset_msg_layer(ssl, partial); /* Reset renegotiation state */ #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; ssl->renego_records_seen = 0; ssl->verify_data_len = 0; memset(ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN); memset(ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN); #endif ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; ssl->session_in = NULL; ssl->session_out = NULL; if (ssl->session) { mbedtls_ssl_session_free(ssl->session); mbedtls_free(ssl->session); ssl->session = NULL; } #if defined(MBEDTLS_SSL_ALPN) ssl->alpn_chosen = NULL; #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) int free_cli_id = 1; #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) free_cli_id = (partial == 0); #endif if (free_cli_id) { mbedtls_free(ssl->cli_id); ssl->cli_id = NULL; ssl->cli_id_len = 0; } #endif if ((ret = ssl_handshake_init(ssl)) != 0) { return ret; } return 0; } /* * Reset an initialized and used SSL context for re-use while retaining * all application-set variables, function pointers and data. */ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl) { return mbedtls_ssl_session_reset_int(ssl, 0); } /* * SSL set accessors */ void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint) { conf->endpoint = endpoint; } void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport) { conf->transport = transport; } #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode) { conf->anti_replay = mode; } #endif void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit) { conf->badmac_limit = limit; } #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_set_datagram_packing(mbedtls_ssl_context *ssl, unsigned allow_packing) { ssl->disable_datagram_packing = !allow_packing; } void mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf, uint32_t min, uint32_t max) { conf->hs_timeout_min = min; conf->hs_timeout_max = max; } #endif void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode) { conf->authmode = authmode; } #if defined(MBEDTLS_X509_CRT_PARSE_C) void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { conf->f_vrfy = f_vrfy; conf->p_vrfy = p_vrfy; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ void mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { conf->f_rng = f_rng; conf->p_rng = p_rng; } void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf, void (*f_dbg)(void *, int, const char *, int, const char *), void *p_dbg) { conf->f_dbg = f_dbg; conf->p_dbg = p_dbg; } void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, void *p_bio, mbedtls_ssl_send_t *f_send, mbedtls_ssl_recv_t *f_recv, mbedtls_ssl_recv_timeout_t *f_recv_timeout) { ssl->p_bio = p_bio; ssl->f_send = f_send; ssl->f_recv = f_recv; ssl->f_recv_timeout = f_recv_timeout; } #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu) { ssl->mtu = mtu; } #endif void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout) { conf->read_timeout = timeout; } void mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl, void *p_timer, mbedtls_ssl_set_timer_t *f_set_timer, mbedtls_ssl_get_timer_t *f_get_timer) { ssl->p_timer = p_timer; ssl->f_set_timer = f_set_timer; ssl->f_get_timer = f_get_timer; /* Make sure we start with no timer running */ mbedtls_ssl_set_timer(ssl, 0); } #if defined(MBEDTLS_SSL_SRV_C) void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf, void *p_cache, mbedtls_ssl_cache_get_t *f_get_cache, mbedtls_ssl_cache_set_t *f_set_cache) { conf->p_cache = p_cache; conf->f_get_cache = f_get_cache; conf->f_set_cache = f_set_cache; } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || session == NULL || ssl->session_negotiate == NULL || ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->handshake->resume == 1) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { #if defined(MBEDTLS_SSL_SESSION_TICKETS) const mbedtls_ssl_ciphersuite_t *ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(session->ciphersuite); if (mbedtls_ssl_validate_ciphersuite( ssl, ciphersuite_info, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3) != 0) { MBEDTLS_SSL_DEBUG_MSG(4, ("%d is not a valid TLS 1.3 ciphersuite.", session->ciphersuite)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #else /* * If session tickets are not enabled, it is not possible to resume a * TLS 1.3 session, thus do not make any change to the SSL context in * the first place. */ return 0; #endif } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ if ((ret = mbedtls_ssl_session_copy(ssl->session_negotiate, session)) != 0) { return ret; } ssl->handshake->resume = 1; return 0; } #endif /* MBEDTLS_SSL_CLI_C */ void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, const int *ciphersuites) { conf->ciphersuite_list = ciphersuites; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf, const int kex_modes) { conf->tls13_kex_modes = kex_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; } #if defined(MBEDTLS_SSL_EARLY_DATA) void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf, int early_data_enabled) { conf->early_data_enabled = early_data_enabled; } #if defined(MBEDTLS_SSL_SRV_C) void mbedtls_ssl_conf_max_early_data_size( mbedtls_ssl_config *conf, uint32_t max_early_data_size) { conf->max_early_data_size = max_early_data_size; } #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_X509_CRT_PARSE_C) void mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf, const mbedtls_x509_crt_profile *profile) { conf->cert_profile = profile; } static void ssl_key_cert_free(mbedtls_ssl_key_cert *key_cert) { mbedtls_ssl_key_cert *cur = key_cert, *next; while (cur != NULL) { next = cur->next; mbedtls_free(cur); cur = next; } } /* Append a new keycert entry to a (possibly empty) list */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_append_key_cert(mbedtls_ssl_key_cert **head, mbedtls_x509_crt *cert, mbedtls_pk_context *key) { mbedtls_ssl_key_cert *new_cert; if (cert == NULL) { /* Free list if cert is null */ ssl_key_cert_free(*head); *head = NULL; return 0; } new_cert = mbedtls_calloc(1, sizeof(mbedtls_ssl_key_cert)); if (new_cert == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } new_cert->cert = cert; new_cert->key = key; new_cert->next = NULL; /* Update head if the list was null, else add to the end */ if (*head == NULL) { *head = new_cert; } else { mbedtls_ssl_key_cert *cur = *head; while (cur->next != NULL) { cur = cur->next; } cur->next = new_cert; } return 0; } int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key) { return ssl_append_key_cert(&conf->key_cert, own_cert, pk_key); } void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl) { conf->ca_chain = ca_chain; conf->ca_crl = ca_crl; #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() * cannot be used together. */ conf->f_ca_cb = NULL; conf->p_ca_cb = NULL; #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) void mbedtls_ssl_conf_ca_cb(mbedtls_ssl_config *conf, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb) { conf->f_ca_cb = f_ca_cb; conf->p_ca_cb = p_ca_cb; /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() * cannot be used together. */ conf->ca_chain = NULL; conf->ca_crl = NULL; } #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl, size_t *name_len) { *name_len = ssl->handshake->sni_name_len; return ssl->handshake->sni_name; } int mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key) { return ssl_append_key_cert(&ssl->handshake->sni_key_cert, own_cert, pk_key); } void mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl) { ssl->handshake->sni_ca_chain = ca_chain; ssl->handshake->sni_ca_crl = ca_crl; } #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) void mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl, const mbedtls_x509_crt *crt) { ssl->handshake->dn_hints = crt; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ void mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl, int authmode) { ssl->handshake->sni_authmode = authmode; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_X509_CRT_PARSE_C) void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { ssl->f_vrfy = f_vrfy; ssl->p_vrfy = p_vrfy; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' }; static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' }; static psa_status_t mbedtls_ssl_set_hs_ecjpake_password_common( mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t pwd) { psa_status_t status; psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); const uint8_t *user = NULL; size_t user_len = 0; const uint8_t *peer = NULL; size_t peer_len = 0; psa_pake_cs_set_algorithm(&cipher_suite, PSA_ALG_JPAKE); psa_pake_cs_set_primitive(&cipher_suite, PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256)); psa_pake_cs_set_hash(&cipher_suite, PSA_ALG_SHA_256); status = psa_pake_setup(&ssl->handshake->psa_pake_ctx, &cipher_suite); if (status != PSA_SUCCESS) { return status; } if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { user = jpake_server_id; user_len = sizeof(jpake_server_id); peer = jpake_client_id; peer_len = sizeof(jpake_client_id); } else { user = jpake_client_id; user_len = sizeof(jpake_client_id); peer = jpake_server_id; peer_len = sizeof(jpake_server_id); } status = psa_pake_set_user(&ssl->handshake->psa_pake_ctx, user, user_len); if (status != PSA_SUCCESS) { return status; } status = psa_pake_set_peer(&ssl->handshake->psa_pake_ctx, peer, peer_len); if (status != PSA_SUCCESS) { return status; } status = psa_pake_set_password_key(&ssl->handshake->psa_pake_ctx, pwd); if (status != PSA_SUCCESS) { return status; } ssl->handshake->psa_pake_ctx_is_ok = 1; return PSA_SUCCESS; } int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, const unsigned char *pw, size_t pw_len) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status; if (ssl->handshake == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Empty password is not valid */ if ((pw == NULL) || (pw_len == 0)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&attributes, PSA_ALG_JPAKE); psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD); status = psa_import_key(&attributes, pw, pw_len, &ssl->handshake->psa_pake_password); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl, ssl->handshake->psa_pake_password); if (status != PSA_SUCCESS) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } return 0; } int mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t pwd) { psa_status_t status; if (ssl->handshake == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (mbedtls_svc_key_id_is_null(pwd)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl, pwd); if (status != PSA_SUCCESS) { psa_pake_abort(&ssl->handshake->psa_pake_ctx); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } return 0; } #else /* MBEDTLS_USE_PSA_CRYPTO */ int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, const unsigned char *pw, size_t pw_len) { mbedtls_ecjpake_role role; if (ssl->handshake == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Empty password is not valid */ if ((pw == NULL) || (pw_len == 0)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { role = MBEDTLS_ECJPAKE_SERVER; } else { role = MBEDTLS_ECJPAKE_CLIENT; } return mbedtls_ecjpake_setup(&ssl->handshake->ecjpake_ctx, role, MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, pw, pw_len); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf) { if (conf->psk_identity == NULL || conf->psk_identity_len == 0) { return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { return 1; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (conf->psk != NULL && conf->psk_len != 0) { return 1; } return 0; } static void ssl_conf_remove_psk(mbedtls_ssl_config *conf) { /* Remove reference to existing PSK, if any. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { /* The maintenance of the PSK key slot is the * user's responsibility. */ conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (conf->psk != NULL) { mbedtls_zeroize_and_free(conf->psk, conf->psk_len); conf->psk = NULL; conf->psk_len = 0; } /* Remove reference to PSK identity, if any. */ if (conf->psk_identity != NULL) { mbedtls_free(conf->psk_identity); conf->psk_identity = NULL; conf->psk_identity_len = 0; } } /* This function assumes that PSK identity in the SSL config is unset. * It checks that the provided identity is well-formed and attempts * to make a copy of it in the SSL config. * On failure, the PSK identity in the config remains unset. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_set_psk_identity(mbedtls_ssl_config *conf, unsigned char const *psk_identity, size_t psk_identity_len) { /* Identity len will be encoded on two bytes */ if (psk_identity == NULL || psk_identity_len == 0 || (psk_identity_len >> 16) != 0 || psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->psk_identity = mbedtls_calloc(1, psk_identity_len); if (conf->psk_identity == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } conf->psk_identity_len = psk_identity_len; memcpy(conf->psk_identity, psk_identity, conf->psk_identity_len); return 0; } int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, const unsigned char *psk, size_t psk_len, const unsigned char *psk_identity, size_t psk_identity_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* We currently only support one PSK, raw or opaque. */ if (mbedtls_ssl_conf_has_static_psk(conf)) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } /* Check and set raw PSK */ if (psk == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (psk_len == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (psk_len > MBEDTLS_PSK_MAX_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if ((conf->psk = mbedtls_calloc(1, psk_len)) == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } conf->psk_len = psk_len; memcpy(conf->psk, psk, conf->psk_len); /* Check and set PSK Identity */ ret = ssl_conf_set_psk_identity(conf, psk_identity, psk_identity_len); if (ret != 0) { ssl_conf_remove_psk(conf); } return ret; } static void ssl_remove_psk(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { /* The maintenance of the external PSK key slot is the * user's responsibility. */ if (ssl->handshake->psk_opaque_is_internal) { psa_destroy_key(ssl->handshake->psk_opaque); ssl->handshake->psk_opaque_is_internal = 0; } ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } #else if (ssl->handshake->psk != NULL) { mbedtls_zeroize_and_free(ssl->handshake->psk, ssl->handshake->psk_len); ssl->handshake->psk_len = 0; ssl->handshake->psk = NULL; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl, const unsigned char *psk, size_t psk_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t key_attributes = psa_key_attributes_init(); psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_algorithm_t alg = PSA_ALG_NONE; mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (psk == NULL || ssl->handshake == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (psk_len > MBEDTLS_PSK_MAX_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl_remove_psk(ssl); #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) { alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); } else { alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); } psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { alg = PSA_ALG_HKDF_EXTRACT(PSA_ALG_ANY_HASH); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ psa_set_key_algorithm(&key_attributes, alg); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE); status = psa_import_key(&key_attributes, psk, psk_len, &key); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } /* Allow calling psa_destroy_key() on psk remove */ ssl->handshake->psk_opaque_is_internal = 1; return mbedtls_ssl_set_hs_psk_opaque(ssl, key); #else if ((ssl->handshake->psk = mbedtls_calloc(1, psk_len)) == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } ssl->handshake->psk_len = psk_len; memcpy(ssl->handshake->psk, psk, ssl->handshake->psk_len); return 0; #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf, mbedtls_svc_key_id_t psk, const unsigned char *psk_identity, size_t psk_identity_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* We currently only support one PSK, raw or opaque. */ if (mbedtls_ssl_conf_has_static_psk(conf)) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } /* Check and set opaque PSK */ if (mbedtls_svc_key_id_is_null(psk)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->psk_opaque = psk; /* Check and set PSK Identity */ ret = ssl_conf_set_psk_identity(conf, psk_identity, psk_identity_len); if (ret != 0) { ssl_conf_remove_psk(conf); } return ret; } int mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t psk) { if ((mbedtls_svc_key_id_is_null(psk)) || (ssl->handshake == NULL)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl_remove_psk(ssl); ssl->handshake->psk_opaque = psk; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SRV_C) void mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_psk) { conf->f_psk = f_psk; conf->p_psk = p_psk; } #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode( psa_algorithm_t alg) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (alg == PSA_ALG_CBC_NO_PADDING) { return MBEDTLS_SSL_MODE_CBC; } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ if (PSA_ALG_IS_AEAD(alg)) { return MBEDTLS_SSL_MODE_AEAD; } return MBEDTLS_SSL_MODE_STREAM; } #else /* MBEDTLS_USE_PSA_CRYPTO */ static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode( mbedtls_cipher_mode_t mode) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (mode == MBEDTLS_MODE_CBC) { return MBEDTLS_SSL_MODE_CBC; } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ #if defined(MBEDTLS_GCM_C) || \ defined(MBEDTLS_CCM_C) || \ defined(MBEDTLS_CHACHAPOLY_C) if (mode == MBEDTLS_MODE_GCM || mode == MBEDTLS_MODE_CCM || mode == MBEDTLS_MODE_CHACHAPOLY) { return MBEDTLS_SSL_MODE_AEAD; } #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ return MBEDTLS_SSL_MODE_STREAM; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ static mbedtls_ssl_mode_t mbedtls_ssl_get_actual_mode( mbedtls_ssl_mode_t base_mode, int encrypt_then_mac) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) if (encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && base_mode == MBEDTLS_SSL_MODE_CBC) { return MBEDTLS_SSL_MODE_CBC_ETM; } #else (void) encrypt_then_mac; #endif return base_mode; } mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform( const mbedtls_ssl_transform *transform) { mbedtls_ssl_mode_t base_mode = mbedtls_ssl_get_base_mode( #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_alg #else mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc) #endif ); int encrypt_then_mac = 0; #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) encrypt_then_mac = transform->encrypt_then_mac; #endif return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac); } mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) int encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ const mbedtls_ssl_ciphersuite_t *suite) { mbedtls_ssl_mode_t base_mode = MBEDTLS_SSL_MODE_STREAM; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; psa_algorithm_t alg; psa_key_type_t type; size_t size; status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) suite->cipher, 0, &alg, &type, &size); if (status == PSA_SUCCESS) { base_mode = mbedtls_ssl_get_base_mode(alg); } #else const mbedtls_cipher_info_t *cipher = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) suite->cipher); if (cipher != NULL) { base_mode = mbedtls_ssl_get_base_mode( mbedtls_cipher_info_get_mode(cipher)); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) int encrypt_then_mac = 0; #endif return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac); } #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type, size_t taglen, psa_algorithm_t *alg, psa_key_type_t *key_type, size_t *key_size) { #if !defined(MBEDTLS_SSL_HAVE_CCM) (void) taglen; #endif switch (mbedtls_cipher_type) { #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_AES_128_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_AES; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_AES_128_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_AES_128_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_AES_192_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_AES_192_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_AES_256_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_AES; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_AES_256_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_AES_256_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_ARIA_128_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_ARIA_128_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_ARIA_128_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_ARIA_192_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_ARIA_192_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_ARIA_256_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_ARIA_256_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_ARIA_256_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_CAMELLIA_128_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_CAMELLIA_128_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_CAMELLIA_128_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_CAMELLIA_192_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_CAMELLIA_192_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_CAMELLIA_256_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_CAMELLIA_256_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_CAMELLIA_256_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) case MBEDTLS_CIPHER_CHACHA20_POLY1305: *alg = PSA_ALG_CHACHA20_POLY1305; *key_type = PSA_KEY_TYPE_CHACHA20; *key_size = 256; break; #endif case MBEDTLS_CIPHER_NULL: *alg = MBEDTLS_SSL_NULL_CIPHER; *key_type = 0; *key_size = 0; break; default: return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } #endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) int mbedtls_ssl_conf_dh_param_bin(mbedtls_ssl_config *conf, const unsigned char *dhm_P, size_t P_len, const unsigned char *dhm_G, size_t G_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); if ((ret = mbedtls_mpi_read_binary(&conf->dhm_P, dhm_P, P_len)) != 0 || (ret = mbedtls_mpi_read_binary(&conf->dhm_G, dhm_G, G_len)) != 0) { mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); return ret; } return 0; } int mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); if ((ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_P, &conf->dhm_P)) != 0 || (ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_G, &conf->dhm_G)) != 0) { mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); return ret; } return 0; } #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) /* * Set the minimum length for Diffie-Hellman parameters */ void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, unsigned int bitlen) { conf->dhm_min_bitlen = bitlen; } #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * Set allowed/preferred hashes for handshake signatures */ void mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, const int *hashes) { conf->sig_hashes = hashes; } #endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */ /* Configure allowed signature algorithms for handshake */ void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf, const uint16_t *sig_algs) { #if !defined(MBEDTLS_DEPRECATED_REMOVED) conf->sig_hashes = NULL; #endif /* !MBEDTLS_DEPRECATED_REMOVED */ conf->sig_algs = sig_algs; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECP_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /* * Set the allowed elliptic curves * * mbedtls_ssl_setup() takes the provided list * and translates it to a list of IANA TLS group identifiers, * stored in ssl->handshake->group_list. * */ void mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, const mbedtls_ecp_group_id *curve_list) { conf->curve_list = curve_list; conf->group_list = NULL; } #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_ECP_C */ /* * Set the allowed groups */ void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, const uint16_t *group_list) { #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) conf->curve_list = NULL; #endif conf->group_list = group_list; } #if defined(MBEDTLS_X509_CRT_PARSE_C) int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname) { /* Initialize to suppress unnecessary compiler warning */ size_t hostname_len = 0; /* Check if new hostname is valid before * making any change to current one */ if (hostname != NULL) { hostname_len = strlen(hostname); if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } /* Now it's clear that we will overwrite the old hostname, * so we can free it safely */ if (ssl->hostname != NULL) { mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname)); } /* Passing NULL as hostname shall clear the old one */ if (hostname == NULL) { ssl->hostname = NULL; } else { ssl->hostname = mbedtls_calloc(1, hostname_len + 1); if (ssl->hostname == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ssl->hostname, hostname, hostname_len); ssl->hostname[hostname_len] = '\0'; } return 0; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf, int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_sni) { conf->f_sni = f_sni; conf->p_sni = p_sni; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ALPN) int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos) { size_t cur_len, tot_len; const char **p; /* * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings * MUST NOT be truncated." * We check lengths now rather than later. */ tot_len = 0; for (p = protos; *p != NULL; p++) { cur_len = strlen(*p); tot_len += cur_len; if ((cur_len == 0) || (cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) || (tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } conf->alpn_list = protos; return 0; } const char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl) { return ssl->alpn_chosen; } #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) void mbedtls_ssl_conf_srtp_mki_value_supported(mbedtls_ssl_config *conf, int support_mki_value) { conf->dtls_srtp_mki_support = support_mki_value; } int mbedtls_ssl_dtls_srtp_set_mki_value(mbedtls_ssl_context *ssl, unsigned char *mki_value, uint16_t mki_len) { if (mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } memcpy(ssl->dtls_srtp_info.mki_value, mki_value, mki_len); ssl->dtls_srtp_info.mki_len = mki_len; return 0; } int mbedtls_ssl_conf_dtls_srtp_protection_profiles(mbedtls_ssl_config *conf, const mbedtls_ssl_srtp_profile *profiles) { const mbedtls_ssl_srtp_profile *p; size_t list_size = 0; /* check the profiles list: all entry must be valid, * its size cannot be more than the total number of supported profiles, currently 4 */ for (p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET && list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH; p++) { if (mbedtls_ssl_check_srtp_profile_value(*p) != MBEDTLS_TLS_SRTP_UNSET) { list_size++; } else { /* unsupported value, stop parsing and set the size to an error value */ list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1; } } if (list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH) { conf->dtls_srtp_profile_list = NULL; conf->dtls_srtp_profile_list_len = 0; return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->dtls_srtp_profile_list = profiles; conf->dtls_srtp_profile_list_len = list_size; return 0; } void mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl, mbedtls_dtls_srtp_info *dtls_srtp_info) { dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile; /* do not copy the mki value if there is no chosen profile */ if (dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) { dtls_srtp_info->mki_len = 0; } else { dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len; memcpy(dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value, ssl->dtls_srtp_info.mki_len); } } #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor) { conf->max_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor); } void mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor) { conf->min_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor); } #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_SSL_SRV_C) void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf, char cert_req_ca_list) { conf->cert_req_ca_list = cert_req_ca_list; } #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) void mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm) { conf->encrypt_then_mac = etm; } #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) void mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems) { conf->extended_ms = ems; } #endif #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code) { if (mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || ssl_mfl_code_to_length(mfl_code) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->mfl_code = mfl_code; return 0; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy) { conf->allow_legacy_renegotiation = allow_legacy; } #if defined(MBEDTLS_SSL_RENEGOTIATION) void mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation) { conf->disable_renegotiation = renegotiation; } void mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records) { conf->renego_max_records = max_records; } void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf, const unsigned char period[8]) { memcpy(conf->renego_period, period, 8); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_CLI_C) void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets) { conf->session_tickets &= ~MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK; conf->session_tickets |= (use_tickets != 0) << MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) void mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets( mbedtls_ssl_config *conf, int signal_new_session_tickets) { conf->session_tickets &= ~MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK; conf->session_tickets |= (signal_new_session_tickets != 0) << MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) void mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf, uint16_t num_tickets) { conf->new_session_tickets_count = num_tickets; } #endif void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf, mbedtls_ssl_ticket_write_t *f_ticket_write, mbedtls_ssl_ticket_parse_t *f_ticket_parse, void *p_ticket) { conf->f_ticket_write = f_ticket_write; conf->f_ticket_parse = f_ticket_parse; conf->p_ticket = p_ticket; } #endif #endif /* MBEDTLS_SSL_SESSION_TICKETS */ void mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl, mbedtls_ssl_export_keys_t *f_export_keys, void *p_export_keys) { ssl->f_export_keys = f_export_keys; ssl->p_export_keys = p_export_keys; } #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, mbedtls_ssl_async_sign_t *f_async_sign, mbedtls_ssl_async_decrypt_t *f_async_decrypt, mbedtls_ssl_async_resume_t *f_async_resume, mbedtls_ssl_async_cancel_t *f_async_cancel, void *async_config_data) { conf->f_async_sign_start = f_async_sign; conf->f_async_decrypt_start = f_async_decrypt; conf->f_async_resume = f_async_resume; conf->f_async_cancel = f_async_cancel; conf->p_async_config_data = async_config_data; } void *mbedtls_ssl_conf_get_async_config_data(const mbedtls_ssl_config *conf) { return conf->p_async_config_data; } void *mbedtls_ssl_get_async_operation_data(const mbedtls_ssl_context *ssl) { if (ssl->handshake == NULL) { return NULL; } else { return ssl->handshake->user_async_ctx; } } void mbedtls_ssl_set_async_operation_data(mbedtls_ssl_context *ssl, void *ctx) { if (ssl->handshake != NULL) { ssl->handshake->user_async_ctx = ctx; } } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ /* * SSL get accessors */ uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl) { if (ssl->session != NULL) { return ssl->session->verify_result; } if (ssl->session_negotiate != NULL) { return ssl->session_negotiate->verify_result; } return 0xFFFFFFFF; } int mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl) { if (ssl == NULL || ssl->session == NULL) { return 0; } return ssl->session->ciphersuite; } const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl) { if (ssl == NULL || ssl->session == NULL) { return NULL; } return mbedtls_ssl_get_ciphersuite_name(ssl->session->ciphersuite); } const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { switch (ssl->tls_version) { case MBEDTLS_SSL_VERSION_TLS1_2: return "DTLSv1.2"; default: return "unknown (DTLS)"; } } #endif switch (ssl->tls_version) { case MBEDTLS_SSL_VERSION_TLS1_2: return "TLSv1.2"; case MBEDTLS_SSL_VERSION_TLS1_3: return "TLSv1.3"; default: return "unknown"; } } #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl) { const size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; size_t record_size_limit = max_len; if (ssl->session != NULL && ssl->session->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN && ssl->session->record_size_limit < max_len) { record_size_limit = ssl->session->record_size_limit; } // TODO: this is currently untested /* During a handshake, use the value being negotiated */ if (ssl->session_negotiate != NULL && ssl->session_negotiate->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN && ssl->session_negotiate->record_size_limit < max_len) { record_size_limit = ssl->session_negotiate->record_size_limit; } return record_size_limit; } #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl) { size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN; size_t read_mfl; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */ if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE) { return ssl_mfl_code_to_length(ssl->conf->mfl_code); } #endif /* Check if a smaller max length was negotiated */ if (ssl->session_out != NULL) { read_mfl = ssl_mfl_code_to_length(ssl->session_out->mfl_code); if (read_mfl < max_len) { max_len = read_mfl; } } /* During a handshake, use the value being negotiated */ if (ssl->session_negotiate != NULL) { read_mfl = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code); if (read_mfl < max_len) { max_len = read_mfl; } } return max_len; } size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl) { size_t max_len; /* * Assume mfl_code is correct since it was checked when set */ max_len = ssl_mfl_code_to_length(ssl->conf->mfl_code); /* Check if a smaller max length was negotiated */ if (ssl->session_out != NULL && ssl_mfl_code_to_length(ssl->session_out->mfl_code) < max_len) { max_len = ssl_mfl_code_to_length(ssl->session_out->mfl_code); } /* During a handshake, use the value being negotiated */ if (ssl->session_negotiate != NULL && ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code) < max_len) { max_len = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code); } return max_len; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_PROTO_DTLS) size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl) { /* Return unlimited mtu for client hello messages to avoid fragmentation. */ if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && (ssl->state == MBEDTLS_SSL_CLIENT_HELLO || ssl->state == MBEDTLS_SSL_SERVER_HELLO)) { return 0; } if (ssl->handshake == NULL || ssl->handshake->mtu == 0) { return ssl->mtu; } if (ssl->mtu == 0) { return ssl->handshake->mtu; } return ssl->mtu < ssl->handshake->mtu ? ssl->mtu : ssl->handshake->mtu; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl) { size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; #if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && \ !defined(MBEDTLS_SSL_PROTO_DTLS) (void) ssl; #endif #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl); if (max_len > mfl) { max_len = mfl; } #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) const size_t record_size_limit = mbedtls_ssl_get_output_record_size_limit(ssl); if (max_len > record_size_limit) { max_len = record_size_limit; } #endif if (ssl->transform_out != NULL && ssl->transform_out->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* * In TLS 1.3 case, when records are protected, `max_len` as computed * above is the maximum length of the TLSInnerPlaintext structure that * along the plaintext payload contains the inner content type (one byte) * and some zero padding. Given the algorithm used for padding * in mbedtls_ssl_encrypt_buf(), compute the maximum length for * the plaintext payload. Round down to a multiple of * MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY and * subtract 1. */ max_len = ((max_len / MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) * MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) - 1; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (mbedtls_ssl_get_current_mtu(ssl) != 0) { const size_t mtu = mbedtls_ssl_get_current_mtu(ssl); const int ret = mbedtls_ssl_get_record_expansion(ssl); const size_t overhead = (size_t) ret; if (ret < 0) { return ret; } if (mtu <= overhead) { MBEDTLS_SSL_DEBUG_MSG(1, ("MTU too low for record expansion")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } if (max_len > mtu - overhead) { max_len = mtu - overhead; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ !defined(MBEDTLS_SSL_PROTO_DTLS) && \ !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) ((void) ssl); #endif return (int) max_len; } int mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl) { size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN; #if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) (void) ssl; #endif #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) const size_t mfl = mbedtls_ssl_get_input_max_frag_len(ssl); if (max_len > mfl) { max_len = mfl; } #endif return (int) max_len; } #if defined(MBEDTLS_X509_CRT_PARSE_C) const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl) { if (ssl == NULL || ssl->session == NULL) { return NULL; } #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) return ssl->session->peer_cert; #else return NULL; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ } #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_CLI_C) int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst) { int ret; if (ssl == NULL || dst == NULL || ssl->session == NULL || ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Since Mbed TLS 3.0, mbedtls_ssl_get_session() is no longer * idempotent: Each session can only be exported once. * * (This is in preparation for TLS 1.3 support where we will * need the ability to export multiple sessions (aka tickets), * which will be achieved by calling mbedtls_ssl_get_session() * multiple times until it fails.) * * Check whether we have already exported the current session, * and fail if so. */ if (ssl->session->exported == 1) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } ret = mbedtls_ssl_session_copy(dst, ssl->session); if (ret != 0) { return ret; } /* Remember that we've exported the session. */ ssl->session->exported = 1; return 0; } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* Serialization of TLS 1.2 sessions * * For more detail, see the description of ssl_session_save(). */ static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len) { unsigned char *p = buf; size_t used = 0; #if defined(MBEDTLS_HAVE_TIME) uint64_t start; #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) size_t cert_len; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* * Time */ #if defined(MBEDTLS_HAVE_TIME) used += 8; if (used <= buf_len) { start = (uint64_t) session->start; MBEDTLS_PUT_UINT64_BE(start, p, 0); p += 8; } #endif /* MBEDTLS_HAVE_TIME */ /* * Basic mandatory fields */ used += 1 /* id_len */ + sizeof(session->id) + sizeof(session->master) + 4; /* verify_result */ if (used <= buf_len) { *p++ = MBEDTLS_BYTE_0(session->id_len); memcpy(p, session->id, 32); p += 32; memcpy(p, session->master, 48); p += 48; MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0); p += 4; } /* * Peer's end-entity certificate */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if (session->peer_cert == NULL) { cert_len = 0; } else { cert_len = session->peer_cert->raw.len; } used += 3 + cert_len; if (used <= buf_len) { *p++ = MBEDTLS_BYTE_2(cert_len); *p++ = MBEDTLS_BYTE_1(cert_len); *p++ = MBEDTLS_BYTE_0(cert_len); if (session->peer_cert != NULL) { memcpy(p, session->peer_cert->raw.p, cert_len); p += cert_len; } } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (session->peer_cert_digest != NULL) { used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len; if (used <= buf_len) { *p++ = (unsigned char) session->peer_cert_digest_type; *p++ = (unsigned char) session->peer_cert_digest_len; memcpy(p, session->peer_cert_digest, session->peer_cert_digest_len); p += session->peer_cert_digest_len; } } else { used += 2; if (used <= buf_len) { *p++ = (unsigned char) MBEDTLS_MD_NONE; *p++ = 0; } } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* * Session ticket if any, plus associated data */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */ if (used <= buf_len) { *p++ = MBEDTLS_BYTE_2(session->ticket_len); *p++ = MBEDTLS_BYTE_1(session->ticket_len); *p++ = MBEDTLS_BYTE_0(session->ticket_len); if (session->ticket != NULL) { memcpy(p, session->ticket, session->ticket_len); p += session->ticket_len; } MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0); p += 4; } } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { used += 8; if (used <= buf_len) { MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0); p += 8; } } #endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * Misc extension-related info */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) used += 1; if (used <= buf_len) { *p++ = session->mfl_code; } #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) used += 1; if (used <= buf_len) { *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac); } #endif return used; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_HAVE_TIME) uint64_t start; #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) size_t cert_len; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ const unsigned char *p = buf; const unsigned char * const end = buf + len; /* * Time */ #if defined(MBEDTLS_HAVE_TIME) if (8 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } start = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; session->start = (time_t) start; #endif /* MBEDTLS_HAVE_TIME */ /* * Basic mandatory fields */ if (1 + 32 + 48 + 4 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->id_len = *p++; memcpy(session->id, p, 32); p += 32; memcpy(session->master, p, 48); p += 48; session->verify_result = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; /* Immediately clear invalid pointer values that have been read, in case * we exit early before we replaced them with valid ones. */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) session->peer_cert = NULL; #else session->peer_cert_digest = NULL; #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) session->ticket = NULL; #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ /* * Peer certificate */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* Deserialize CRT from the end of the ticket. */ if (3 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } cert_len = MBEDTLS_GET_UINT24_BE(p, 0); p += 3; if (cert_len != 0) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (cert_len > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); if (session->peer_cert == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } mbedtls_x509_crt_init(session->peer_cert); if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert, p, cert_len)) != 0) { mbedtls_x509_crt_free(session->peer_cert); mbedtls_free(session->peer_cert); session->peer_cert = NULL; return ret; } p += cert_len; } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* Deserialize CRT digest from the end of the ticket. */ if (2 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; session->peer_cert_digest_len = (size_t) *p++; if (session->peer_cert_digest_len != 0) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(session->peer_cert_digest_type); if (md_info == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (session->peer_cert_digest_len > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->peer_cert_digest = mbedtls_calloc(1, session->peer_cert_digest_len); if (session->peer_cert_digest == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->peer_cert_digest, p, session->peer_cert_digest_len); p += session->peer_cert_digest_len; } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* * Session ticket and associated data */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { if (3 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_len = MBEDTLS_GET_UINT24_BE(p, 0); p += 3; if (session->ticket_len != 0) { if (session->ticket_len > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket = mbedtls_calloc(1, session->ticket_len); if (session->ticket == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->ticket, p, session->ticket_len); p += session->ticket_len; } if (4 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { if (8 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; } #endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * Misc extension-related info */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) if (1 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->mfl_code = *p++; #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if (1 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->encrypt_then_mac = *p++; #endif /* Done, should have consumed entire buffer */ if (p != end) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return 0; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* Serialization of TLS 1.3 sessions: * * For more detail, see the description of ssl_session_save(). */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len, size_t *olen) { unsigned char *p = buf; #if defined(MBEDTLS_SSL_CLI_C) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) size_t hostname_len = (session->hostname == NULL) ? 0 : strlen(session->hostname) + 1; #endif #if defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) const size_t alpn_len = (session->ticket_alpn == NULL) ? 0 : strlen(session->ticket_alpn) + 1; #endif size_t needed = 4 /* ticket_age_add */ + 1 /* ticket_flags */ + 1; /* resumption_key length */ *olen = 0; if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } needed += session->resumption_key_len; /* resumption_key */ #if defined(MBEDTLS_SSL_EARLY_DATA) needed += 4; /* max_early_data_size */ #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) needed += 2; /* record_size_limit */ #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_HAVE_TIME) needed += 8; /* ticket_creation_time or ticket_reception_time */ #endif #if defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) needed += 2 /* alpn_len */ + alpn_len; /* alpn */ #endif } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) needed += 2 /* hostname_len */ + hostname_len; /* hostname */ #endif needed += 4 /* ticket_lifetime */ + 2; /* ticket_len */ /* Check size_t overflow */ if (session->ticket_len > SIZE_MAX - needed) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } needed += session->ticket_len; /* ticket */ } #endif /* MBEDTLS_SSL_CLI_C */ *olen = needed; if (needed > buf_len) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 0); p[4] = session->ticket_flags; /* save resumption_key */ p[5] = session->resumption_key_len; p += 6; memcpy(p, session->resumption_key, session->resumption_key_len); p += session->resumption_key_len; #if defined(MBEDTLS_SSL_EARLY_DATA) MBEDTLS_PUT_UINT32_BE(session->max_early_data_size, p, 0); p += 4; #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) MBEDTLS_PUT_UINT16_BE(session->record_size_limit, p, 0); p += 2; #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { #if defined(MBEDTLS_HAVE_TIME) MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0); p += 8; #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) MBEDTLS_PUT_UINT16_BE(alpn_len, p, 0); p += 2; if (alpn_len > 0) { /* save chosen alpn */ memcpy(p, session->ticket_alpn, alpn_len); p += alpn_len; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */ } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0); p += 2; if (hostname_len > 0) { /* save host name */ memcpy(p, session->hostname, hostname_len); p += hostname_len; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_HAVE_TIME) MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_reception_time, p, 0); p += 8; #endif MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0); p += 4; MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0); p += 2; if (session->ticket != NULL && session->ticket_len > 0) { memcpy(p, session->ticket, session->ticket_len); p += session->ticket_len; } } #endif /* MBEDTLS_SSL_CLI_C */ return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len) { const unsigned char *p = buf; const unsigned char *end = buf + len; if (end - p < 6) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 0); session->ticket_flags = p[4]; /* load resumption_key */ session->resumption_key_len = p[5]; p += 6; if (end - p < session->resumption_key_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (sizeof(session->resumption_key) < session->resumption_key_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(session->resumption_key, p, session->resumption_key_len); p += session->resumption_key_len; #if defined(MBEDTLS_SSL_EARLY_DATA) if (end - p < 4) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->max_early_data_size = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { #if defined(MBEDTLS_HAVE_TIME) if (end - p < 8) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) size_t alpn_len; if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } alpn_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; if (end - p < (long int) alpn_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (alpn_len > 0) { int ret = mbedtls_ssl_session_set_ticket_alpn(session, (char *) p); if (ret != 0) { return ret; } p += alpn_len; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */ } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) size_t hostname_len; /* load host name */ if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } hostname_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; if (end - p < (long int) hostname_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (hostname_len > 0) { session->hostname = mbedtls_calloc(1, hostname_len); if (session->hostname == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->hostname, p, hostname_len); p += hostname_len; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_HAVE_TIME) if (end - p < 8) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_reception_time = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; #endif if (end - p < 4) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; if (end - p < (long int) session->ticket_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (session->ticket_len > 0) { session->ticket = mbedtls_calloc(1, session->ticket_len); if (session->ticket == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->ticket, p, session->ticket_len); p += session->ticket_len; } } #endif /* MBEDTLS_SSL_CLI_C */ return 0; } #else /* MBEDTLS_SSL_SESSION_TICKETS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len, size_t *olen) { ((void) session); ((void) buf); ((void) buf_len); *olen = 0; return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } static int ssl_tls13_session_load(const mbedtls_ssl_session *session, const unsigned char *buf, size_t buf_len) { ((void) session); ((void) buf); ((void) buf_len); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #endif /* !MBEDTLS_SSL_SESSION_TICKETS */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /* * Define ticket header determining Mbed TLS version * and structure of the ticket. */ /* * Define bitflag determining compile-time settings influencing * structure of serialized SSL sessions. */ #if defined(MBEDTLS_HAVE_TIME) #define SSL_SERIALIZED_SESSION_CONFIG_TIME 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_TIME 0 #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) #define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 0 #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0 #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) #define SSL_SERIALIZED_SESSION_CONFIG_MFL 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_MFL 0 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) #define SSL_SERIALIZED_SESSION_CONFIG_ETM 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_ETM 0 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) #define SSL_SERIALIZED_SESSION_CONFIG_SNI 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_SNI 0 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_EARLY_DATA) #define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 0 #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) #define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 0 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_EARLY_DATA) #define SSL_SERIALIZED_SESSION_CONFIG_ALPN 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_ALPN 0 #endif /* MBEDTLS_SSL_ALPN */ #define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 #define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 #define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2 #define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3 #define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 4 #define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 5 #define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT 6 #define SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT 7 #define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT 8 #define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT 9 #define SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT 10 #define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ ((uint16_t) ( \ (SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << \ SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT << \ SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_SNI << SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA << \ SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE << \ SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_ALPN << \ SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT))) static const unsigned char ssl_serialized_session_header[] = { MBEDTLS_VERSION_MAJOR, MBEDTLS_VERSION_MINOR, MBEDTLS_VERSION_PATCH, MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), }; /* * Serialize a session in the following format: * (in the presentation language of TLS, RFC 8446 section 3) * * TLS 1.2 session: * * struct { * #if defined(MBEDTLS_SSL_SESSION_TICKETS) * opaque ticket<0..2^24-1>; // length 0 means no ticket * uint32 ticket_lifetime; * #endif * } ClientOnlyData; * * struct { * #if defined(MBEDTLS_HAVE_TIME) * uint64 start_time; * #endif * uint8 session_id_len; // at most 32 * opaque session_id[32]; * opaque master[48]; // fixed length in the standard * uint32 verify_result; * #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert * #else * uint8 peer_cert_digest_type; * opaque peer_cert_digest<0..2^8-1> * #endif * select (endpoint) { * case client: ClientOnlyData; * case server: uint64 ticket_creation_time; * }; * #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) * uint8 mfl_code; // up to 255 according to standard * #endif * #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) * uint8 encrypt_then_mac; // 0 or 1 * #endif * } serialized_session_tls12; * * * TLS 1.3 Session: * * struct { * #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) * opaque hostname<0..2^16-1>; * #endif * #if defined(MBEDTLS_HAVE_TIME) * uint64 ticket_reception_time; * #endif * uint32 ticket_lifetime; * opaque ticket<1..2^16-1>; * } ClientOnlyData; * * struct { * uint32 ticket_age_add; * uint8 ticket_flags; * opaque resumption_key<0..255>; * #if defined(MBEDTLS_SSL_EARLY_DATA) * uint32 max_early_data_size; * #endif * #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) * uint16 record_size_limit; * #endif * select ( endpoint ) { * case client: ClientOnlyData; * case server: * #if defined(MBEDTLS_HAVE_TIME) * uint64 ticket_creation_time; * #endif * #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) * opaque ticket_alpn<0..256>; * #endif * }; * } serialized_session_tls13; * * * SSL session: * * struct { * * opaque mbedtls_version[3]; // library version: major, minor, patch * opaque session_format[2]; // library-version specific 16-bit field * // determining the format of the remaining * // serialized data. * * Note: When updating the format, remember to keep * these version+format bytes. * * // In this version, `session_format` determines * // the setting of those compile-time * // configuration options which influence * // the structure of mbedtls_ssl_session. * * uint8_t minor_ver; // Protocol minor version. Possible values: * // - TLS 1.2 (0x0303) * // - TLS 1.3 (0x0304) * uint8_t endpoint; * uint16_t ciphersuite; * * select (serialized_session.tls_version) { * * case MBEDTLS_SSL_VERSION_TLS1_2: * serialized_session_tls12 data; * case MBEDTLS_SSL_VERSION_TLS1_3: * serialized_session_tls13 data; * * }; * * } serialized_session; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_session_save(const mbedtls_ssl_session *session, unsigned char omit_header, unsigned char *buf, size_t buf_len, size_t *olen) { unsigned char *p = buf; size_t used = 0; size_t remaining_len; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) size_t out_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif if (session == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (!omit_header) { /* * Add Mbed TLS version identifier */ used += sizeof(ssl_serialized_session_header); if (used <= buf_len) { memcpy(p, ssl_serialized_session_header, sizeof(ssl_serialized_session_header)); p += sizeof(ssl_serialized_session_header); } } /* * TLS version identifier, endpoint, ciphersuite */ used += 1 /* TLS version */ + 1 /* endpoint */ + 2; /* ciphersuite */ if (used <= buf_len) { *p++ = MBEDTLS_BYTE_0(session->tls_version); *p++ = session->endpoint; MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0); p += 2; } /* Forward to version-specific serialization routine. */ remaining_len = (buf_len >= used) ? buf_len - used : 0; switch (session->tls_version) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) case MBEDTLS_SSL_VERSION_TLS1_2: used += ssl_tls12_session_save(session, p, remaining_len); break; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) case MBEDTLS_SSL_VERSION_TLS1_3: ret = ssl_tls13_session_save(session, p, remaining_len, &out_len); if (ret != 0 && ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { return ret; } used += out_len; break; #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ default: return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } *olen = used; if (used > buf_len) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } return 0; } /* * Public wrapper for ssl_session_save() */ int mbedtls_ssl_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len, size_t *olen) { return ssl_session_save(session, 0, buf, buf_len, olen); } /* * Deserialize session, see mbedtls_ssl_session_save() for format. * * This internal version is wrapped by a public function that cleans up in * case of error, and has an extra option omit_header. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_session_load(mbedtls_ssl_session *session, unsigned char omit_header, const unsigned char *buf, size_t len) { const unsigned char *p = buf; const unsigned char * const end = buf + len; size_t remaining_len; if (session == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (!omit_header) { /* * Check Mbed TLS version identifier */ if ((size_t) (end - p) < sizeof(ssl_serialized_session_header)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (memcmp(p, ssl_serialized_session_header, sizeof(ssl_serialized_session_header)) != 0) { return MBEDTLS_ERR_SSL_VERSION_MISMATCH; } p += sizeof(ssl_serialized_session_header); } /* * TLS version identifier, endpoint, ciphersuite */ if (4 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->tls_version = (mbedtls_ssl_protocol_version) (0x0300 | *p++); session->endpoint = *p++; session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Dispatch according to TLS version. */ remaining_len = (size_t) (end - p); switch (session->tls_version) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) case MBEDTLS_SSL_VERSION_TLS1_2: return ssl_tls12_session_load(session, p, remaining_len); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) case MBEDTLS_SSL_VERSION_TLS1_3: return ssl_tls13_session_load(session, p, remaining_len); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ default: return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } /* * Deserialize session: public wrapper for error cleaning */ int mbedtls_ssl_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len) { int ret = ssl_session_load(session, 0, buf, len); if (ret != 0) { mbedtls_ssl_session_free(session); } return ret; } /* * Perform a single step of the SSL handshake */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_handshake_step(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * We may have not been able to send to the peer all the handshake data * that were written into the output buffer by the previous handshake step, * if the write to the network callback returned with the * #MBEDTLS_ERR_SSL_WANT_WRITE error code. * We proceed to the next handshake step only when all data from the * previous one have been sent to the peer, thus we make sure that this is * the case here by calling `mbedtls_ssl_flush_output()`. The function may * return with the #MBEDTLS_ERR_SSL_WANT_WRITE error code in which case * we have to wait before to go ahead. * In the case of TLS 1.3, handshake step handlers do not send data to the * peer. Data are only sent here and through * `mbedtls_ssl_handle_pending_alert` in case an error that triggered an * alert occurred. */ if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { return ret; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ return ret; } int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || ssl->conf == NULL || ssl->handshake == NULL || ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ret = ssl_prepare_handshake_step(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_handle_pending_alert(ssl); if (ret != 0) { goto cleanup; } /* If ssl->conf->endpoint is not one of MBEDTLS_SSL_IS_CLIENT or * MBEDTLS_SSL_IS_SERVER, this is the return code we give */ ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { MBEDTLS_SSL_DEBUG_MSG(2, ("client state: %s", mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state))); switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: ssl->state = MBEDTLS_SSL_CLIENT_HELLO; ret = 0; break; case MBEDTLS_SSL_CLIENT_HELLO: ret = mbedtls_ssl_write_client_hello(ssl); break; default: #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { ret = mbedtls_ssl_tls13_handshake_client_step(ssl); } else { ret = mbedtls_ssl_handshake_client_step(ssl); } #elif defined(MBEDTLS_SSL_PROTO_TLS1_2) ret = mbedtls_ssl_handshake_client_step(ssl); #else ret = mbedtls_ssl_tls13_handshake_client_step(ssl); #endif } } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { ret = mbedtls_ssl_tls13_handshake_server_step(ssl); } else { ret = mbedtls_ssl_handshake_server_step(ssl); } #elif defined(MBEDTLS_SSL_PROTO_TLS1_2) ret = mbedtls_ssl_handshake_server_step(ssl); #else ret = mbedtls_ssl_tls13_handshake_server_step(ssl); #endif } #endif /* MBEDTLS_SSL_SRV_C */ if (ret != 0) { /* handshake_step return error. And it is same * with alert_reason. */ if (ssl->send_alert) { ret = mbedtls_ssl_handle_pending_alert(ssl); goto cleanup; } } cleanup: return ret; } /* * Perform the SSL handshake */ int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl) { int ret = 0; /* Sanity checks */ if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && (ssl->f_set_timer == NULL || ssl->f_get_timer == NULL)) { MBEDTLS_SSL_DEBUG_MSG(1, ("You must use " "mbedtls_ssl_set_timer_cb() for DTLS")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG(2, ("=> handshake")); /* Main handshake loop */ while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { ret = mbedtls_ssl_handshake_step(ssl); if (ret != 0) { break; } } MBEDTLS_SSL_DEBUG_MSG(2, ("<= handshake")); return ret; } #if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_SRV_C) /* * Write HelloRequest to request renegotiation on server */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hello_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello request")); ssl->out_msglen = 4; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello request")); return 0; } #endif /* MBEDTLS_SSL_SRV_C */ /* * Actually renegotiate current connection, triggered by either: * - any side: calling mbedtls_ssl_renegotiate(), * - client: receiving a HelloRequest during mbedtls_ssl_read(), * - server: receiving any handshake message on server during mbedtls_ssl_read() after * the initial handshake is completed. * If the handshake doesn't complete due to waiting for I/O, it will continue * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. */ int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> renegotiate")); if ((ret = ssl_handshake_init(ssl)) != 0) { return ret; } /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and * the ServerHello will have message_seq = 1" */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { ssl->handshake->out_msg_seq = 1; } else { ssl->handshake->in_msg_seq = 1; } } #endif ssl->state = MBEDTLS_SSL_HELLO_REQUEST; ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= renegotiate")); return 0; } /* * Renegotiate current connection on client, * or request renegotiation on server */ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_SSL_SRV_C) /* On server, just send the request */ if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { if (mbedtls_ssl_is_handshake_over(ssl) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; /* Did we already try/start sending HelloRequest? */ if (ssl->out_left != 0) { return mbedtls_ssl_flush_output(ssl); } return ssl_write_hello_request(ssl); } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) /* * On client, either start the renegotiation process or, * if already in progress, continue the handshake */ if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { if (mbedtls_ssl_is_handshake_over(ssl) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if ((ret = mbedtls_ssl_start_renegotiation(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", ret); return ret; } } else { if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } } #endif /* MBEDTLS_SSL_CLI_C */ return ret; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params *handshake = ssl->handshake; if (handshake == NULL) { return; } #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #if !defined(MBEDTLS_DEPRECATED_REMOVED) if (ssl->handshake->group_list_heap_allocated) { mbedtls_free((void *) handshake->group_list); } handshake->group_list = NULL; #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) if (ssl->handshake->sig_algs_heap_allocated) { mbedtls_free((void *) handshake->sig_algs); } handshake->sig_algs = NULL; #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->handshake->certificate_request_context) { mbedtls_free((void *) handshake->certificate_request_context); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0) { ssl->conf->f_async_cancel(ssl); handshake->async_in_progress = 0; } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_abort(&handshake->fin_sha256_psa); #else mbedtls_md_free(&handshake->fin_sha256); #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_abort(&handshake->fin_sha384_psa); #else mbedtls_md_free(&handshake->fin_sha384); #endif #endif #if defined(MBEDTLS_DHM_C) mbedtls_dhm_free(&handshake->dhm_ctx); #endif #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) mbedtls_ecdh_free(&handshake->ecdh_ctx); #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_pake_abort(&handshake->psa_pake_ctx); /* * Opaque keys are not stored in the handshake's data and it's the user * responsibility to destroy them. Clear ones, instead, are created by * the TLS library and should be destroyed at the same level */ if (!mbedtls_svc_key_id_is_null(handshake->psa_pake_password)) { psa_destroy_key(handshake->psa_pake_password); } handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_ecjpake_free(&handshake->ecjpake_ctx); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) mbedtls_free(handshake->ecjpake_cache); handshake->ecjpake_cache = NULL; handshake->ecjpake_cache_len = 0; #endif #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) /* explicit void pointer cast for buggy MS compiler */ mbedtls_free((void *) handshake->curves_tls_id); #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { /* The maintenance of the external PSK key slot is the * user's responsibility. */ if (ssl->handshake->psk_opaque_is_internal) { psa_destroy_key(ssl->handshake->psk_opaque); ssl->handshake->psk_opaque_is_internal = 0; } ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } #else if (handshake->psk != NULL) { mbedtls_zeroize_and_free(handshake->psk, handshake->psk_len); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /* * Free only the linked list wrapper, not the keys themselves * since the belong to the SNI callback */ ssl_key_cert_free(handshake->sni_key_cert); #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) mbedtls_x509_crt_restart_free(&handshake->ecrs_ctx); if (handshake->ecrs_peer_cert != NULL) { mbedtls_x509_crt_free(handshake->ecrs_peer_cert); mbedtls_free(handshake->ecrs_peer_cert); } #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) mbedtls_pk_free(&handshake->peer_pubkey); #endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #if defined(MBEDTLS_SSL_CLI_C) && \ (defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) mbedtls_free(handshake->cookie); #endif /* MBEDTLS_SSL_CLI_C && ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) mbedtls_ssl_flight_free(handshake->flight); mbedtls_ssl_buffering_free(ssl); #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED) if (handshake->xxdh_psa_privkey_is_external == 0) { psa_destroy_key(handshake->xxdh_psa_privkey); } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_transform_free(handshake->transform_handshake); mbedtls_free(handshake->transform_handshake); #if defined(MBEDTLS_SSL_EARLY_DATA) mbedtls_ssl_transform_free(handshake->transform_earlydata); mbedtls_free(handshake->transform_earlydata); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) /* If the buffers are too big - reallocate. Because of the way Mbed TLS * processes datagrams and the fact that a datagram is allowed to have * several records in it, it is possible that the I/O buffers are not * empty at this stage */ handle_buffer_resizing(ssl, 1, mbedtls_ssl_get_input_buflen(ssl), mbedtls_ssl_get_output_buflen(ssl)); #endif /* mbedtls_platform_zeroize MUST be last one in this function */ mbedtls_platform_zeroize(handshake, sizeof(mbedtls_ssl_handshake_params)); } void mbedtls_ssl_session_free(mbedtls_ssl_session *session) { if (session == NULL) { return; } #if defined(MBEDTLS_X509_CRT_PARSE_C) ssl_clear_peer_cert(session); #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) mbedtls_free(session->hostname); #endif mbedtls_free(session->ticket); #endif #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && \ defined(MBEDTLS_SSL_SRV_C) mbedtls_free(session->ticket_alpn); #endif mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session)); } #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u #else #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u #else #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_ALPN) #define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u #else #define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u #endif /* MBEDTLS_SSL_ALPN */ #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT 0 #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT 1 #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT 2 #define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT 3 #define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG \ ((uint32_t) ( \ (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << \ SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT) | \ (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << \ SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT) | \ (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << \ SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT) | \ (SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \ 0u)) static const unsigned char ssl_serialized_context_header[] = { MBEDTLS_VERSION_MAJOR, MBEDTLS_VERSION_MINOR, MBEDTLS_VERSION_PATCH, MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), MBEDTLS_BYTE_2(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), MBEDTLS_BYTE_1(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), MBEDTLS_BYTE_0(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), }; /* * Serialize a full SSL context * * The format of the serialized data is: * (in the presentation language of TLS, RFC 8446 section 3) * * // header * opaque mbedtls_version[3]; // major, minor, patch * opaque context_format[5]; // version-specific field determining * // the format of the remaining * // serialized data. * Note: When updating the format, remember to keep these * version+format bytes. (We may make their size part of the API.) * * // session sub-structure * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save() * // transform sub-structure * uint8 random[64]; // ServerHello.random+ClientHello.random * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use * // fields from ssl_context * uint32 badmac_seen; // DTLS: number of records with failing MAC * uint64 in_window_top; // DTLS: last validated record seq_num * uint64 in_window; // DTLS: bitmask for replay protection * uint8 disable_datagram_packing; // DTLS: only one record per datagram * uint64 cur_out_ctr; // Record layer: outgoing sequence number * uint16 mtu; // DTLS: path mtu (max outgoing fragment size) * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol * * Note that many fields of the ssl_context or sub-structures are not * serialized, as they fall in one of the following categories: * * 1. forced value (eg in_left must be 0) * 2. pointer to dynamically-allocated memory (eg session, transform) * 3. value can be re-derived from other data (eg session keys from MS) * 4. value was temporary (eg content of input buffer) * 5. value will be provided by the user again (eg I/O callbacks and context) */ int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl, unsigned char *buf, size_t buf_len, size_t *olen) { unsigned char *p = buf; size_t used = 0; size_t session_len; int ret = 0; /* * Enforce usage restrictions, see "return BAD_INPUT_DATA" in * this function's documentation. * * These are due to assumptions/limitations in the implementation. Some of * them are likely to stay (no handshake in progress) some might go away * (only DTLS) but are currently used to simplify the implementation. */ /* The initial handshake must be over */ if (mbedtls_ssl_is_handshake_over(ssl) == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("Initial handshake isn't over")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->handshake != NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("Handshake isn't completed")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Double-check that sub-structures are indeed ready */ if (ssl->transform == NULL || ssl->session == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("Serialised structures aren't ready")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* There must be no pending incoming or outgoing data */ if (mbedtls_ssl_check_pending(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending incoming data")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->out_left != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending outgoing data")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Protocol must be DTLS, not TLS */ if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("Only DTLS is supported")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Version must be 1.2 */ if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) { MBEDTLS_SSL_DEBUG_MSG(1, ("Only version 1.2 supported")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* We must be using an AEAD ciphersuite */ if (mbedtls_ssl_transform_uses_aead(ssl->transform) != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("Only AEAD ciphersuites supported")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Renegotiation must not be enabled */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED) { MBEDTLS_SSL_DEBUG_MSG(1, ("Renegotiation must not be enabled")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* * Version and format identifier */ used += sizeof(ssl_serialized_context_header); if (used <= buf_len) { memcpy(p, ssl_serialized_context_header, sizeof(ssl_serialized_context_header)); p += sizeof(ssl_serialized_context_header); } /* * Session (length + data) */ ret = ssl_session_save(ssl->session, 1, NULL, 0, &session_len); if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { return ret; } used += 4 + session_len; if (used <= buf_len) { MBEDTLS_PUT_UINT32_BE(session_len, p, 0); p += 4; ret = ssl_session_save(ssl->session, 1, p, session_len, &session_len); if (ret != 0) { return ret; } p += session_len; } /* * Transform */ used += sizeof(ssl->transform->randbytes); if (used <= buf_len) { memcpy(p, ssl->transform->randbytes, sizeof(ssl->transform->randbytes)); p += sizeof(ssl->transform->randbytes); } #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) used += 2U + ssl->transform->in_cid_len + ssl->transform->out_cid_len; if (used <= buf_len) { *p++ = ssl->transform->in_cid_len; memcpy(p, ssl->transform->in_cid, ssl->transform->in_cid_len); p += ssl->transform->in_cid_len; *p++ = ssl->transform->out_cid_len; memcpy(p, ssl->transform->out_cid, ssl->transform->out_cid_len); p += ssl->transform->out_cid_len; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /* * Saved fields from top-level ssl_context structure */ used += 4; if (used <= buf_len) { MBEDTLS_PUT_UINT32_BE(ssl->badmac_seen, p, 0); p += 4; } #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) used += 16; if (used <= buf_len) { MBEDTLS_PUT_UINT64_BE(ssl->in_window_top, p, 0); p += 8; MBEDTLS_PUT_UINT64_BE(ssl->in_window, p, 0); p += 8; } #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_PROTO_DTLS) used += 1; if (used <= buf_len) { *p++ = ssl->disable_datagram_packing; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; if (used <= buf_len) { memcpy(p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; } #if defined(MBEDTLS_SSL_PROTO_DTLS) used += 2; if (used <= buf_len) { MBEDTLS_PUT_UINT16_BE(ssl->mtu, p, 0); p += 2; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_ALPN) { const uint8_t alpn_len = ssl->alpn_chosen ? (uint8_t) strlen(ssl->alpn_chosen) : 0; used += 1 + alpn_len; if (used <= buf_len) { *p++ = alpn_len; if (ssl->alpn_chosen != NULL) { memcpy(p, ssl->alpn_chosen, alpn_len); p += alpn_len; } } } #endif /* MBEDTLS_SSL_ALPN */ /* * Done */ *olen = used; if (used > buf_len) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } MBEDTLS_SSL_DEBUG_BUF(4, "saved context", buf, used); return mbedtls_ssl_session_reset_int(ssl, 0); } /* * Deserialize context, see mbedtls_ssl_context_save() for format. * * This internal version is wrapped by a public function that cleans up in * case of error. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_context_load(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { const unsigned char *p = buf; const unsigned char * const end = buf + len; size_t session_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) tls_prf_fn prf_func = NULL; #endif /* * The context should have been freshly setup or reset. * Give the user an error in case of obvious misuse. * (Checking session is useful because it won't be NULL if we're * renegotiating, or if the user mistakenly loaded a session first.) */ if (ssl->state != MBEDTLS_SSL_HELLO_REQUEST || ssl->session != NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * We can't check that the config matches the initial one, but we can at * least check it matches the requirements for serializing. */ if ( #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || #endif ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || ssl->conf->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2 || ssl->conf->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 ) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_DEBUG_BUF(4, "context to load", buf, len); /* * Check version identifier */ if ((size_t) (end - p) < sizeof(ssl_serialized_context_header)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (memcmp(p, ssl_serialized_context_header, sizeof(ssl_serialized_context_header)) != 0) { return MBEDTLS_ERR_SSL_VERSION_MISMATCH; } p += sizeof(ssl_serialized_context_header); /* * Session */ if ((size_t) (end - p) < 4) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session_len = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; /* This has been allocated by ssl_handshake_init(), called by * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ ssl->session = ssl->session_negotiate; ssl->session_in = ssl->session; ssl->session_out = ssl->session; ssl->session_negotiate = NULL; if ((size_t) (end - p) < session_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ret = ssl_session_load(ssl->session, 1, p, session_len); if (ret != 0) { mbedtls_ssl_session_free(ssl->session); return ret; } p += session_len; /* * Transform */ /* This has been allocated by ssl_handshake_init(), called by * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) ssl->transform = ssl->transform_negotiate; ssl->transform_in = ssl->transform; ssl->transform_out = ssl->transform; ssl->transform_negotiate = NULL; #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) prf_func = ssl_tls12prf_from_cs(ssl->session->ciphersuite); if (prf_func == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Read random bytes and populate structure */ if ((size_t) (end - p) < sizeof(ssl->transform->randbytes)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ret = ssl_tls12_populate_transform(ssl->transform, ssl->session->ciphersuite, ssl->session->master, #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) ssl->session->encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ prf_func, p, /* currently pointing to randbytes */ MBEDTLS_SSL_VERSION_TLS1_2, /* (D)TLS 1.2 is forced */ ssl->conf->endpoint, ssl); if (ret != 0) { return ret; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ p += sizeof(ssl->transform->randbytes); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* Read connection IDs and store them */ if ((size_t) (end - p) < 1) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->transform->in_cid_len = *p++; if ((size_t) (end - p) < ssl->transform->in_cid_len + 1u) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(ssl->transform->in_cid, p, ssl->transform->in_cid_len); p += ssl->transform->in_cid_len; ssl->transform->out_cid_len = *p++; if ((size_t) (end - p) < ssl->transform->out_cid_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(ssl->transform->out_cid, p, ssl->transform->out_cid_len); p += ssl->transform->out_cid_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /* * Saved fields from top-level ssl_context structure */ if ((size_t) (end - p) < 4) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->badmac_seen = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if ((size_t) (end - p) < 16) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->in_window_top = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; ssl->in_window = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if ((size_t) (end - p) < 1) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->disable_datagram_packing = *p++; #endif /* MBEDTLS_SSL_PROTO_DTLS */ if ((size_t) (end - p) < sizeof(ssl->cur_out_ctr)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(ssl->cur_out_ctr, p, sizeof(ssl->cur_out_ctr)); p += sizeof(ssl->cur_out_ctr); #if defined(MBEDTLS_SSL_PROTO_DTLS) if ((size_t) (end - p) < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->mtu = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_ALPN) { uint8_t alpn_len; const char **cur; if ((size_t) (end - p) < 1) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } alpn_len = *p++; if (alpn_len != 0 && ssl->conf->alpn_list != NULL) { /* alpn_chosen should point to an item in the configured list */ for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) { if (strlen(*cur) == alpn_len && memcmp(p, *cur, alpn_len) == 0) { ssl->alpn_chosen = *cur; break; } } } /* can only happen on conf mismatch */ if (alpn_len != 0 && ssl->alpn_chosen == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } p += alpn_len; } #endif /* MBEDTLS_SSL_ALPN */ /* * Forced fields from top-level ssl_context structure * * Most of them already set to the correct value by mbedtls_ssl_init() and * mbedtls_ssl_reset(), so we only need to set the remaining ones. */ ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; /* Adjust pointers for header fields of outgoing records to * the given transform, accounting for explicit IV and CID. */ mbedtls_ssl_update_out_pointers(ssl, ssl->transform); #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->in_epoch = 1; #endif /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated, * which we don't want - otherwise we'd end up freeing the wrong transform * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform() * inappropriately. */ if (ssl->handshake != NULL) { mbedtls_ssl_handshake_free(ssl); mbedtls_free(ssl->handshake); ssl->handshake = NULL; } /* * Done - should have consumed entire buffer */ if (p != end) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return 0; } /* * Deserialize context: public wrapper for error cleaning */ int mbedtls_ssl_context_load(mbedtls_ssl_context *context, const unsigned char *buf, size_t len) { int ret = ssl_context_load(context, buf, len); if (ret != 0) { mbedtls_ssl_free(context); } return ret; } #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /* * Free an SSL context */ void mbedtls_ssl_free(mbedtls_ssl_context *ssl) { if (ssl == NULL) { return; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> free")); if (ssl->out_buf != NULL) { #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len; #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #endif mbedtls_zeroize_and_free(ssl->out_buf, out_buf_len); ssl->out_buf = NULL; } if (ssl->in_buf != NULL) { #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t in_buf_len = ssl->in_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; #endif mbedtls_zeroize_and_free(ssl->in_buf, in_buf_len); ssl->in_buf = NULL; } if (ssl->transform) { mbedtls_ssl_transform_free(ssl->transform); mbedtls_free(ssl->transform); } if (ssl->handshake) { mbedtls_ssl_handshake_free(ssl); mbedtls_free(ssl->handshake); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_ssl_transform_free(ssl->transform_negotiate); mbedtls_free(ssl->transform_negotiate); #endif mbedtls_ssl_session_free(ssl->session_negotiate); mbedtls_free(ssl->session_negotiate); } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_transform_free(ssl->transform_application); mbedtls_free(ssl->transform_application); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ if (ssl->session) { mbedtls_ssl_session_free(ssl->session); mbedtls_free(ssl->session); } #if defined(MBEDTLS_X509_CRT_PARSE_C) if (ssl->hostname != NULL) { mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname)); } #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) mbedtls_free(ssl->cli_id); #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= free")); /* Actually clear after last debug message */ mbedtls_platform_zeroize(ssl, sizeof(mbedtls_ssl_context)); } /* * Initialize mbedtls_ssl_config */ void mbedtls_ssl_config_init(mbedtls_ssl_config *conf) { memset(conf, 0, sizeof(mbedtls_ssl_config)); } /* The selection should be the same as mbedtls_x509_crt_profile_default in * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters: * curves with a lower resource usage come first. * See the documentation of mbedtls_ssl_conf_curves() for what we promise * about this list. */ static const uint16_t ssl_preset_default_groups[] = { #if defined(MBEDTLS_ECP_HAVE_CURVE25519) MBEDTLS_SSL_IANA_TLS_GROUP_X25519, #endif #if defined(MBEDTLS_ECP_HAVE_SECP256R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, #endif #if defined(MBEDTLS_ECP_HAVE_SECP384R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, #endif #if defined(MBEDTLS_ECP_HAVE_CURVE448) MBEDTLS_SSL_IANA_TLS_GROUP_X448, #endif #if defined(MBEDTLS_ECP_HAVE_SECP521R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, #endif #if defined(MBEDTLS_ECP_HAVE_BP256R1) MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, #endif #if defined(MBEDTLS_ECP_HAVE_BP384R1) MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, #endif #if defined(MBEDTLS_ECP_HAVE_BP512R1) MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, #endif #if defined(PSA_WANT_ALG_FFDH) MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048, MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072, MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096, MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144, MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192, #endif MBEDTLS_SSL_IANA_TLS_GROUP_NONE }; static const int ssl_preset_suiteb_ciphersuites[] = { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 0 }; #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* NOTICE: * For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following * rules SHOULD be upheld. * - No duplicate entries. * - But if there is a good reason, do not change the order of the algorithms. * - ssl_tls12_preset* is for TLS 1.2 use only. * - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes. */ static const uint16_t ssl_preset_default_sig_algs[] = { #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA256) && \ defined(PSA_WANT_ECC_SECP_R1_256) MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA384) && \ defined(PSA_WANT_ECC_SECP_R1_384) MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA512) && \ defined(PSA_WANT_ECC_SECP_R1_521) MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512) #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA512) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, #endif #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512, #endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */ #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384, #endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256, #endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 */ MBEDTLS_TLS_SIG_NONE }; /* NOTICE: see above */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) static uint16_t ssl_tls12_preset_default_sig_algs[] = { #if defined(MBEDTLS_MD_CAN_SHA512) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512), #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, #endif #if defined(MBEDTLS_RSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512), #endif #endif /* MBEDTLS_MD_CAN_SHA512 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, #endif #if defined(MBEDTLS_RSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384), #endif #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256), #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, #endif #if defined(MBEDTLS_RSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256), #endif #endif /* MBEDTLS_MD_CAN_SHA256 */ MBEDTLS_TLS_SIG_NONE }; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* NOTICE: see above */ static const uint16_t ssl_preset_suiteb_sig_algs[] = { #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA256) && \ defined(MBEDTLS_ECP_HAVE_SECP256R1) MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA384) && \ defined(MBEDTLS_ECP_HAVE_SECP384R1) MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384) #endif MBEDTLS_TLS_SIG_NONE }; /* NOTICE: see above */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) static uint16_t ssl_tls12_preset_suiteb_sig_algs[] = { #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256), #endif #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), #endif #endif /* MBEDTLS_MD_CAN_SHA384 */ MBEDTLS_TLS_SIG_NONE }; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ static const uint16_t ssl_preset_suiteb_groups[] = { #if defined(MBEDTLS_ECP_HAVE_SECP256R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, #endif #if defined(MBEDTLS_ECP_HAVE_SECP384R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, #endif MBEDTLS_SSL_IANA_TLS_GROUP_NONE }; #if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs` * to make sure there are no duplicated signature algorithm entries. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_no_sig_alg_duplication(const uint16_t *sig_algs) { size_t i, j; int ret = 0; for (i = 0; sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) { for (j = 0; j < i; j++) { if (sig_algs[i] != sig_algs[j]) { continue; } mbedtls_printf(" entry(%04x,%" MBEDTLS_PRINTF_SIZET ") is duplicated at %" MBEDTLS_PRINTF_SIZET "\n", sig_algs[i], j, i); ret = -1; } } return ret; } #endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ /* * Load default in mbedtls_ssl_config */ int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf, int endpoint, int transport, int preset) { #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif #if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) if (ssl_check_no_sig_alg_duplication(ssl_preset_suiteb_sig_algs)) { mbedtls_printf("ssl_preset_suiteb_sig_algs has duplicated entries\n"); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } if (ssl_check_no_sig_alg_duplication(ssl_preset_default_sig_algs)) { mbedtls_printf("ssl_preset_default_sig_algs has duplicated entries\n"); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_suiteb_sig_algs)) { mbedtls_printf("ssl_tls12_preset_suiteb_sig_algs has duplicated entries\n"); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_default_sig_algs)) { mbedtls_printf("ssl_tls12_preset_default_sig_algs has duplicated entries\n"); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ /* Use the functions here so that they are covered in tests, * but otherwise access member directly for efficiency */ mbedtls_ssl_conf_endpoint(conf, endpoint); mbedtls_ssl_conf_transport(conf, transport); /* * Things that are common to all presets */ #if defined(MBEDTLS_SSL_CLI_C) if (endpoint == MBEDTLS_SSL_IS_CLIENT) { conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; #if defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_conf_session_tickets(conf, MBEDTLS_SSL_SESSION_TICKETS_ENABLED); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* Contrary to TLS 1.2 tickets, TLS 1.3 NewSessionTicket message * handling is disabled by default in Mbed TLS 3.6.x for backward * compatibility with client applications developed using Mbed TLS 3.5 * or earlier with the default configuration. * * Up to Mbed TLS 3.5, in the default configuration TLS 1.3 was * disabled, and a Mbed TLS client with the default configuration would * establish a TLS 1.2 connection with a TLS 1.2 and TLS 1.3 capable * server. * * Starting with Mbed TLS 3.6.0, TLS 1.3 is enabled by default, and thus * an Mbed TLS client with the default configuration establishes a * TLS 1.3 connection with a TLS 1.2 and TLS 1.3 capable server. If * following the handshake the TLS 1.3 server sends NewSessionTicket * messages and the Mbed TLS client processes them, this results in * Mbed TLS high level APIs (mbedtls_ssl_read(), * mbedtls_ssl_handshake(), ...) to eventually return an * #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET non fatal error code * (see the documentation of mbedtls_ssl_read() for more information on * that error code). Applications unaware of that TLS 1.3 specific non * fatal error code are then failing. */ mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets( conf, MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED); #endif #endif } #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) conf->f_cookie_write = ssl_cookie_write_dummy; conf->f_cookie_check = ssl_cookie_check_dummy; #endif #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; #endif #if defined(MBEDTLS_SSL_SRV_C) conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; conf->respect_cli_pref = MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER; #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; memset(conf->renego_period, 0x00, 2); memset(conf->renego_period + 2, 0xFF, 6); #endif #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) if (endpoint == MBEDTLS_SSL_IS_SERVER) { const unsigned char dhm_p[] = MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; const unsigned char dhm_g[] = MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; if ((ret = mbedtls_ssl_conf_dh_param_bin(conf, dhm_p, sizeof(dhm_p), dhm_g, sizeof(dhm_g))) != 0) { return ret; } } #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(MBEDTLS_SSL_EARLY_DATA) mbedtls_ssl_conf_early_data(conf, MBEDTLS_SSL_EARLY_DATA_DISABLED); #if defined(MBEDTLS_SSL_SRV_C) mbedtls_ssl_conf_max_early_data_size(conf, MBEDTLS_SSL_MAX_EARLY_DATA_SIZE); #endif #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_conf_new_session_tickets( conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS); #endif /* * Allow all TLS 1.3 key exchange modes by default. */ conf->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; #else return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; #endif } else { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; #elif defined(MBEDTLS_SSL_PROTO_TLS1_3) conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; #elif defined(MBEDTLS_SSL_PROTO_TLS1_2) conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; #else return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; #endif } /* * Preset-specific defaults */ switch (preset) { /* * NSA Suite B */ case MBEDTLS_SSL_PRESET_SUITEB: conf->ciphersuite_list = ssl_preset_suiteb_ciphersuites; #if defined(MBEDTLS_X509_CRT_PARSE_C) conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (mbedtls_ssl_conf_is_tls12_only(conf)) { conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs; } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ conf->sig_algs = ssl_preset_suiteb_sig_algs; #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) conf->curve_list = NULL; #endif conf->group_list = ssl_preset_suiteb_groups; break; /* * Default */ default: conf->ciphersuite_list = mbedtls_ssl_list_ciphersuites(); #if defined(MBEDTLS_X509_CRT_PARSE_C) conf->cert_profile = &mbedtls_x509_crt_profile_default; #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (mbedtls_ssl_conf_is_tls12_only(conf)) { conf->sig_algs = ssl_tls12_preset_default_sig_algs; } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ conf->sig_algs = ssl_preset_default_sig_algs; #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) conf->curve_list = NULL; #endif conf->group_list = ssl_preset_default_groups; #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) conf->dhm_min_bitlen = 1024; #endif } return 0; } /* * Free mbedtls_ssl_config */ void mbedtls_ssl_config_free(mbedtls_ssl_config *conf) { if (conf == NULL) { return; } #if defined(MBEDTLS_DHM_C) mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (conf->psk != NULL) { mbedtls_zeroize_and_free(conf->psk, conf->psk_len); conf->psk = NULL; conf->psk_len = 0; } if (conf->psk_identity != NULL) { mbedtls_zeroize_and_free(conf->psk_identity, conf->psk_identity_len); conf->psk_identity = NULL; conf->psk_identity_len = 0; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) ssl_key_cert_free(conf->key_cert); #endif mbedtls_platform_zeroize(conf, sizeof(mbedtls_ssl_config)); } #if defined(MBEDTLS_PK_C) && \ (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED)) /* * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX */ unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk) { #if defined(MBEDTLS_RSA_C) if (mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA)) { return MBEDTLS_SSL_SIG_RSA; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECDSA)) { return MBEDTLS_SSL_SIG_ECDSA; } #endif return MBEDTLS_SSL_SIG_ANON; } unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type) { switch (type) { case MBEDTLS_PK_RSA: return MBEDTLS_SSL_SIG_RSA; case MBEDTLS_PK_ECDSA: case MBEDTLS_PK_ECKEY: return MBEDTLS_SSL_SIG_ECDSA; default: return MBEDTLS_SSL_SIG_ANON; } } mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig) { switch (sig) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_SSL_SIG_RSA: return MBEDTLS_PK_RSA; #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) case MBEDTLS_SSL_SIG_ECDSA: return MBEDTLS_PK_ECDSA; #endif default: return MBEDTLS_PK_NONE; } } #endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED ) */ /* * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX */ mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash) { switch (hash) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_SSL_HASH_MD5: return MBEDTLS_MD_MD5; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_SSL_HASH_SHA1: return MBEDTLS_MD_SHA1; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_SSL_HASH_SHA224: return MBEDTLS_MD_SHA224; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_SSL_HASH_SHA256: return MBEDTLS_MD_SHA256; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_SSL_HASH_SHA384: return MBEDTLS_MD_SHA384; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_SSL_HASH_SHA512: return MBEDTLS_MD_SHA512; #endif default: return MBEDTLS_MD_NONE; } } /* * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX */ unsigned char mbedtls_ssl_hash_from_md_alg(int md) { switch (md) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_MD_MD5: return MBEDTLS_SSL_HASH_MD5; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_MD_SHA1: return MBEDTLS_SSL_HASH_SHA1; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_MD_SHA224: return MBEDTLS_SSL_HASH_SHA224; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: return MBEDTLS_SSL_HASH_SHA256; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: return MBEDTLS_SSL_HASH_SHA384; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_MD_SHA512: return MBEDTLS_SSL_HASH_SHA512; #endif default: return MBEDTLS_SSL_HASH_NONE; } } /* * Check if a curve proposed by the peer is in our list. * Return 0 if we're willing to use it, -1 otherwise. */ int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id) { const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); if (group_list == NULL) { return -1; } for (; *group_list != 0; group_list++) { if (*group_list == tls_id) { return 0; } } return -1; } #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * Same as mbedtls_ssl_check_curve_tls_id() but with a mbedtls_ecp_group_id. */ int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id) { uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); if (tls_id == 0) { return -1; } return mbedtls_ssl_check_curve_tls_id(ssl, tls_id); } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ static const struct { uint16_t tls_id; mbedtls_ecp_group_id ecp_group_id; psa_ecc_family_t psa_family; uint16_t bits; } tls_id_match_table[] = { #if defined(MBEDTLS_ECP_HAVE_SECP521R1) { 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521 }, #endif #if defined(MBEDTLS_ECP_HAVE_BP512R1) { 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP384R1) { 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384 }, #endif #if defined(MBEDTLS_ECP_HAVE_BP384R1) { 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP256R1) { 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP256K1) { 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256 }, #endif #if defined(MBEDTLS_ECP_HAVE_BP256R1) { 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP224R1) { 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP224K1) { 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP192R1) { 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP192K1) { 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192 }, #endif #if defined(MBEDTLS_ECP_HAVE_CURVE25519) { 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255 }, #endif #if defined(MBEDTLS_ECP_HAVE_CURVE448) { 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448 }, #endif { 0, MBEDTLS_ECP_DP_NONE, 0, 0 }, }; int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id, psa_key_type_t *type, size_t *bits) { for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) { if (tls_id_match_table[i].tls_id == tls_id) { if (type != NULL) { *type = PSA_KEY_TYPE_ECC_KEY_PAIR(tls_id_match_table[i].psa_family); } if (bits != NULL) { *bits = tls_id_match_table[i].bits; } return PSA_SUCCESS; } } return PSA_ERROR_NOT_SUPPORTED; } mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id) { for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) { if (tls_id_match_table[i].tls_id == tls_id) { return tls_id_match_table[i].ecp_group_id; } } return MBEDTLS_ECP_DP_NONE; } uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id) { for (int i = 0; tls_id_match_table[i].ecp_group_id != MBEDTLS_ECP_DP_NONE; i++) { if (tls_id_match_table[i].ecp_group_id == grp_id) { return tls_id_match_table[i].tls_id; } } return 0; } #if defined(MBEDTLS_DEBUG_C) static const struct { uint16_t tls_id; const char *name; } tls_id_curve_name_table[] = { { MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, "secp521r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, "brainpoolP512r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, "secp384r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, "brainpoolP384r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, "secp256r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1, "secp256k1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, "brainpoolP256r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1, "secp224r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1, "secp224k1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1, "secp192r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1, "secp192k1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_X25519, "x25519" }, { MBEDTLS_SSL_IANA_TLS_GROUP_X448, "x448" }, { 0, NULL }, }; const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id) { for (int i = 0; tls_id_curve_name_table[i].tls_id != 0; i++) { if (tls_id_curve_name_table[i].tls_id == tls_id) { return tls_id_curve_name_table[i].name; } } return NULL; } #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, const mbedtls_md_type_t md, unsigned char *dst, size_t dst_len, size_t *olen) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_hash_operation_t *hash_operation_to_clone; psa_hash_operation_t hash_operation = psa_hash_operation_init(); *olen = 0; switch (md) { #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: hash_operation_to_clone = &ssl->handshake->fin_sha384_psa; break; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: hash_operation_to_clone = &ssl->handshake->fin_sha256_psa; break; #endif default: goto exit; } status = psa_hash_clone(hash_operation_to_clone, &hash_operation); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&hash_operation, dst, dst_len, olen); if (status != PSA_SUCCESS) { goto exit; } exit: #if !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA256) (void) ssl; #endif return PSA_TO_MBEDTLS_ERR(status); } #else /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_handshake_transcript_sha384(mbedtls_ssl_context *ssl, unsigned char *dst, size_t dst_len, size_t *olen) { int ret; mbedtls_md_context_t sha384; if (dst_len < 48) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } mbedtls_md_init(&sha384); ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384); if (ret != 0) { goto exit; } if ((ret = mbedtls_md_finish(&sha384, dst)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); goto exit; } *olen = 48; exit: mbedtls_md_free(&sha384); return ret; } #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_handshake_transcript_sha256(mbedtls_ssl_context *ssl, unsigned char *dst, size_t dst_len, size_t *olen) { int ret; mbedtls_md_context_t sha256; if (dst_len < 32) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } mbedtls_md_init(&sha256); ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256); if (ret != 0) { goto exit; } if ((ret = mbedtls_md_finish(&sha256, dst)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); goto exit; } *olen = 32; exit: mbedtls_md_free(&sha256); return ret; } #endif /* MBEDTLS_MD_CAN_SHA256 */ int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, const mbedtls_md_type_t md, unsigned char *dst, size_t dst_len, size_t *olen) { switch (md) { #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: return ssl_get_handshake_transcript_sha384(ssl, dst, dst_len, olen); #endif /* MBEDTLS_MD_CAN_SHA384*/ #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: return ssl_get_handshake_transcript_sha256(ssl, dst, dst_len, olen); #endif /* MBEDTLS_MD_CAN_SHA256*/ default: #if !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA256) (void) ssl; (void) dst; (void) dst_len; (void) olen; #endif break; } return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* mbedtls_ssl_parse_sig_alg_ext() * * The `extension_data` field of signature algorithm contains a `SignatureSchemeList` * value (TLS 1.3 RFC8446): * enum { * .... * ecdsa_secp256r1_sha256( 0x0403 ), * ecdsa_secp384r1_sha384( 0x0503 ), * ecdsa_secp521r1_sha512( 0x0603 ), * .... * } SignatureScheme; * * struct { * SignatureScheme supported_signature_algorithms<2..2^16-2>; * } SignatureSchemeList; * * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm` * value (TLS 1.2 RFC5246): * enum { * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), * sha512(6), (255) * } HashAlgorithm; * * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } * SignatureAlgorithm; * * struct { * HashAlgorithm hash; * SignatureAlgorithm signature; * } SignatureAndHashAlgorithm; * * SignatureAndHashAlgorithm * supported_signature_algorithms<2..2^16-2>; * * The TLS 1.3 signature algorithm extension was defined to be a compatible * generalization of the TLS 1.2 signature algorithm extension. * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by * `SignatureScheme` field of TLS 1.3 * */ int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t supported_sig_algs_len = 0; const unsigned char *supported_sig_algs_end; uint16_t sig_alg; uint32_t common_idx = 0; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); supported_sig_algs_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; memset(ssl->handshake->received_sig_algs, 0, sizeof(ssl->handshake->received_sig_algs)); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, supported_sig_algs_len); supported_sig_algs_end = p + supported_sig_algs_len; while (p < supported_sig_algs_end) { MBEDTLS_SSL_CHK_BUF_READ_PTR(p, supported_sig_algs_end, 2); sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(4, ("received signature algorithm: 0x%x %s", sig_alg, mbedtls_ssl_sig_alg_to_str(sig_alg))); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && (!(mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg) && mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)))) { continue; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_SSL_DEBUG_MSG(4, ("valid signature algorithm: %s", mbedtls_ssl_sig_alg_to_str(sig_alg))); if (common_idx + 1 < MBEDTLS_RECEIVED_SIG_ALGS_SIZE) { ssl->handshake->received_sig_algs[common_idx] = sig_alg; common_idx += 1; } } /* Check that we consumed all the message. */ if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("Signature algorithms extension length misaligned")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (common_idx == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("no signature algorithm in common")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->handshake->received_sig_algs[common_idx] = MBEDTLS_TLS_SIG_NONE; return 0; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_USE_PSA_CRYPTO) static psa_status_t setup_psa_key_derivation(psa_key_derivation_operation_t *derivation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const unsigned char *raw_psk, size_t raw_psk_length, const unsigned char *seed, size_t seed_length, const unsigned char *label, size_t label_length, const unsigned char *other_secret, size_t other_secret_length, size_t capacity) { psa_status_t status; status = psa_key_derivation_setup(derivation, alg); if (status != PSA_SUCCESS) { return status; } if (PSA_ALG_IS_TLS12_PRF(alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) { status = psa_key_derivation_input_bytes(derivation, PSA_KEY_DERIVATION_INPUT_SEED, seed, seed_length); if (status != PSA_SUCCESS) { return status; } if (other_secret != NULL) { status = psa_key_derivation_input_bytes(derivation, PSA_KEY_DERIVATION_INPUT_OTHER_SECRET, other_secret, other_secret_length); if (status != PSA_SUCCESS) { return status; } } if (mbedtls_svc_key_id_is_null(key)) { status = psa_key_derivation_input_bytes( derivation, PSA_KEY_DERIVATION_INPUT_SECRET, raw_psk, raw_psk_length); } else { status = psa_key_derivation_input_key( derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key); } if (status != PSA_SUCCESS) { return status; } status = psa_key_derivation_input_bytes(derivation, PSA_KEY_DERIVATION_INPUT_LABEL, label, label_length); if (status != PSA_SUCCESS) { return status; } } else { return PSA_ERROR_NOT_SUPPORTED; } status = psa_key_derivation_set_capacity(derivation, capacity); if (status != PSA_SUCCESS) { return status; } return PSA_SUCCESS; } #if defined(PSA_WANT_ALG_SHA_384) || \ defined(PSA_WANT_ALG_SHA_256) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_generic(mbedtls_md_type_t md_type, const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { psa_status_t status; psa_algorithm_t alg; mbedtls_svc_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_derivation_operation_t derivation = PSA_KEY_DERIVATION_OPERATION_INIT; if (md_type == MBEDTLS_MD_SHA384) { alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384); } else { alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256); } /* Normally a "secret" should be long enough to be impossible to * find by brute force, and in particular should not be empty. But * this PRF is also used to derive an IV, in particular in EAP-TLS, * and for this use case it makes sense to have a 0-length "secret". * Since the key API doesn't allow importing a key of length 0, * keep master_key=0, which setup_psa_key_derivation() understands * to mean a 0-length "secret" input. */ if (slen != 0) { psa_key_attributes_t key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, alg); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE); status = psa_import_key(&key_attributes, secret, slen, &master_key); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } } status = setup_psa_key_derivation(&derivation, master_key, alg, NULL, 0, random, rlen, (unsigned char const *) label, (size_t) strlen(label), NULL, 0, dlen); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); psa_destroy_key(master_key); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_output_bytes(&derivation, dstbuf, dlen); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); psa_destroy_key(master_key); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_abort(&derivation); if (status != PSA_SUCCESS) { psa_destroy_key(master_key); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } if (!mbedtls_svc_key_id_is_null(master_key)) { status = psa_destroy_key(master_key); } if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } return 0; } #endif /* PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384 */ #else /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_MD_C) && \ (defined(MBEDTLS_MD_CAN_SHA256) || \ defined(MBEDTLS_MD_CAN_SHA384)) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_generic(mbedtls_md_type_t md_type, const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { size_t nb; size_t i, j, k, md_len; unsigned char *tmp; size_t tmp_len = 0; unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_init(&md_ctx); if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } md_len = mbedtls_md_get_size(md_info); tmp_len = md_len + strlen(label) + rlen; tmp = mbedtls_calloc(1, tmp_len); if (tmp == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } nb = strlen(label); memcpy(tmp + md_len, label, nb); memcpy(tmp + md_len + nb, random, rlen); nb += rlen; /* * Compute P_(secret, label + random)[0..dlen] */ if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { goto exit; } ret = mbedtls_md_hmac_starts(&md_ctx, secret, slen); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&md_ctx, tmp + md_len, nb); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_finish(&md_ctx, tmp); if (ret != 0) { goto exit; } for (i = 0; i < dlen; i += md_len) { ret = mbedtls_md_hmac_reset(&md_ctx); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len + nb); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_finish(&md_ctx, h_i); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_reset(&md_ctx); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_finish(&md_ctx, tmp); if (ret != 0) { goto exit; } k = (i + md_len > dlen) ? dlen % md_len : md_len; for (j = 0; j < k; j++) { dstbuf[i + j] = h_i[j]; } } exit: mbedtls_md_free(&md_ctx); if (tmp != NULL) { mbedtls_platform_zeroize(tmp, tmp_len); } mbedtls_platform_zeroize(h_i, sizeof(h_i)); mbedtls_free(tmp); return ret; } #endif /* MBEDTLS_MD_C && ( MBEDTLS_MD_CAN_SHA256 || MBEDTLS_MD_CAN_SHA384 ) */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha256(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { return tls_prf_generic(MBEDTLS_MD_SHA256, secret, slen, label, random, rlen, dstbuf, dlen); } #endif /* MBEDTLS_MD_CAN_SHA256*/ #if defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha384(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { return tls_prf_generic(MBEDTLS_MD_SHA384, secret, slen, label, random, rlen, dstbuf, dlen); } #endif /* MBEDTLS_MD_CAN_SHA384*/ /* * Set appropriate PRF function and other SSL / TLS1.2 functions * * Inputs: * - hash associated with the ciphersuite (only used by TLS 1.2) * * Outputs: * - the tls_prf, calc_verify and calc_finished members of handshake structure */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_set_handshake_prfs(mbedtls_ssl_handshake_params *handshake, mbedtls_md_type_t hash) { #if defined(MBEDTLS_MD_CAN_SHA384) if (hash == MBEDTLS_MD_SHA384) { handshake->tls_prf = tls_prf_sha384; handshake->calc_verify = ssl_calc_verify_tls_sha384; handshake->calc_finished = ssl_calc_finished_tls_sha384; } else #endif #if defined(MBEDTLS_MD_CAN_SHA256) { (void) hash; handshake->tls_prf = tls_prf_sha256; handshake->calc_verify = ssl_calc_verify_tls_sha256; handshake->calc_finished = ssl_calc_finished_tls_sha256; } #else { (void) handshake; (void) hash; return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif return 0; } /* * Compute master secret if needed * * Parameters: * [in/out] handshake * [in] resume, premaster, extended_ms, calc_verify, tls_prf * (PSA-PSK) ciphersuite_info, psk_opaque * [out] premaster (cleared) * [out] master * [in] ssl: optionally used for debugging, EMS and PSA-PSK * debug: conf->f_dbg, conf->p_dbg * EMS: passed to calc_verify (debug + session_negotiate) * PSA-PSA: conf */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake, unsigned char *master, const mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* cf. RFC 5246, Section 8.1: * "The master secret is always exactly 48 bytes in length." */ size_t const master_secret_len = 48; #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) unsigned char session_hash[48]; #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ /* The label for the KDF used for key expansion. * This is either "master secret" or "extended master secret" * depending on whether the Extended Master Secret extension * is used. */ char const *lbl = "master secret"; /* The seed for the KDF used for key expansion. * - If the Extended Master Secret extension is not used, * this is ClientHello.Random + ServerHello.Random * (see Sect. 8.1 in RFC 5246). * - If the Extended Master Secret extension is used, * this is the transcript of the handshake so far. * (see Sect. 4 in RFC 7627). */ unsigned char const *seed = handshake->randbytes; size_t seed_len = 64; #if !defined(MBEDTLS_DEBUG_C) && \ !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) ssl = NULL; /* make sure we don't use it except for those cases */ (void) ssl; #endif if (handshake->resume != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("no premaster (session resumed)")); return 0; } #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) { lbl = "extended master secret"; seed = session_hash; ret = handshake->calc_verify(ssl, session_hash, &seed_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret); } MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret", session_hash, seed_len); } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (mbedtls_ssl_ciphersuite_uses_psk(handshake->ciphersuite_info) == 1) { /* Perform PSK-to-MS expansion in a single step. */ psa_status_t status; psa_algorithm_t alg; mbedtls_svc_key_id_t psk; psa_key_derivation_operation_t derivation = PSA_KEY_DERIVATION_OPERATION_INIT; mbedtls_md_type_t hash_alg = (mbedtls_md_type_t) handshake->ciphersuite_info->mac; MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PSK-to-MS expansion")); psk = mbedtls_ssl_get_opaque_psk(ssl); if (hash_alg == MBEDTLS_MD_SHA384) { alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); } else { alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); } size_t other_secret_len = 0; unsigned char *other_secret = NULL; switch (handshake->ciphersuite_info->key_exchange) { /* Provide other secret. * Other secret is stored in premaster, where first 2 bytes hold the * length of the other key. */ case MBEDTLS_KEY_EXCHANGE_RSA_PSK: /* For RSA-PSK other key length is always 48 bytes. */ other_secret_len = 48; other_secret = handshake->premaster + 2; break; case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: other_secret_len = MBEDTLS_GET_UINT16_BE(handshake->premaster, 0); other_secret = handshake->premaster + 2; break; default: break; } status = setup_psa_key_derivation(&derivation, psk, alg, ssl->conf->psk, ssl->conf->psk_len, seed, seed_len, (unsigned char const *) lbl, (size_t) strlen(lbl), other_secret, other_secret_len, master_secret_len); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_output_bytes(&derivation, master, master_secret_len); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_abort(&derivation); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } } else #endif { #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { psa_status_t status; psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS; psa_key_derivation_operation_t derivation = PSA_KEY_DERIVATION_OPERATION_INIT; MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PMS KDF for ECJPAKE")); handshake->pmslen = PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE; status = psa_key_derivation_setup(&derivation, alg); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_set_capacity(&derivation, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_pake_get_implicit_key(&handshake->psa_pake_ctx, &derivation); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_output_bytes(&derivation, handshake->premaster, handshake->pmslen); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_abort(&derivation); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } } #endif ret = handshake->tls_prf(handshake->premaster, handshake->pmslen, lbl, seed, seed_len, master, master_secret_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "prf", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "premaster secret", handshake->premaster, handshake->pmslen); mbedtls_platform_zeroize(handshake->premaster, sizeof(handshake->premaster)); } return 0; } int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive keys")); /* Set PRF, calc_verify and calc_finished function pointers */ ret = ssl_set_handshake_prfs(ssl->handshake, (mbedtls_md_type_t) ciphersuite_info->mac); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_set_handshake_prfs", ret); return ret; } /* Compute master secret if needed */ ret = ssl_compute_master(ssl->handshake, ssl->session_negotiate->master, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_compute_master", ret); return ret; } /* Swap the client and server random values: * - MS derivation wanted client+server (RFC 5246 8.1) * - key derivation wants server+client (RFC 5246 6.3) */ { unsigned char tmp[64]; memcpy(tmp, ssl->handshake->randbytes, 64); memcpy(ssl->handshake->randbytes, tmp + 32, 32); memcpy(ssl->handshake->randbytes + 32, tmp, 32); mbedtls_platform_zeroize(tmp, sizeof(tmp)); } /* Populate transform structure */ ret = ssl_tls12_populate_transform(ssl->transform_negotiate, ssl->session_negotiate->ciphersuite, ssl->session_negotiate->master, #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) ssl->session_negotiate->encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ ssl->handshake->tls_prf, ssl->handshake->randbytes, ssl->tls_version, ssl->conf->endpoint, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls12_populate_transform", ret); return ret; } /* We no longer need Server/ClientHello.random values */ mbedtls_platform_zeroize(ssl->handshake->randbytes, sizeof(ssl->handshake->randbytes)); MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive keys")); return 0; } int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md) { switch (md) { #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_SSL_HASH_SHA384: ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; break; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_SSL_HASH_SHA256: ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; break; #endif default: return -1; } #if !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA256) (void) ssl; #endif return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) static int ssl_calc_verify_tls_psa(const mbedtls_ssl_context *ssl, const psa_hash_operation_t *hs_op, size_t buffer_size, unsigned char *hash, size_t *hlen) { psa_status_t status; psa_hash_operation_t cloned_op = psa_hash_operation_init(); #if !defined(MBEDTLS_DEBUG_C) (void) ssl; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify")); status = psa_hash_clone(hs_op, &cloned_op); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&cloned_op, hash, buffer_size, hlen); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen); MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify")); exit: psa_hash_abort(&cloned_op); return mbedtls_md_error_from_psa(status); } #else static int ssl_calc_verify_tls_legacy(const mbedtls_ssl_context *ssl, const mbedtls_md_context_t *hs_ctx, unsigned char *hash, size_t *hlen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_context_t cloned_ctx; mbedtls_md_init(&cloned_ctx); #if !defined(MBEDTLS_DEBUG_C) (void) ssl; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify")); ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_clone(&cloned_ctx, hs_ctx); if (ret != 0) { goto exit; } ret = mbedtls_md_finish(&cloned_ctx, hash); if (ret != 0) { goto exit; } *hlen = mbedtls_md_get_size(mbedtls_md_info_from_ctx(hs_ctx)); MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen); MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify")); exit: mbedtls_md_free(&cloned_ctx); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_MD_CAN_SHA256) int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hlen) { #if defined(MBEDTLS_USE_PSA_CRYPTO) return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha256_psa, 32, hash, hlen); #else return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha256, hash, hlen); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hlen) { #if defined(MBEDTLS_USE_PSA_CRYPTO) return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha384_psa, 48, hash, hlen); #else return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha384, hash, hlen); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_MD_CAN_SHA384 */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex) { unsigned char *p = ssl->handshake->premaster; unsigned char *end = p + sizeof(ssl->handshake->premaster); const unsigned char *psk = NULL; size_t psk_len = 0; int psk_ret = mbedtls_ssl_get_psk(ssl, &psk, &psk_len); if (psk_ret == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) { /* * This should never happen because the existence of a PSK is always * checked before calling this function. * * The exception is opaque DHE-PSK. For DHE-PSK fill premaster with * the shared secret without PSK. */ if (key_ex != MBEDTLS_KEY_EXCHANGE_DHE_PSK) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } /* * PMS = struct { * opaque other_secret<0..2^16-1>; * opaque psk<0..2^16-1>; * }; * with "other_secret" depending on the particular key exchange */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) if (key_ex == MBEDTLS_KEY_EXCHANGE_PSK) { if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT16_BE(psk_len, p, 0); p += 2; if (end < p || (size_t) (end - p) < psk_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memset(p, 0, psk_len); p += psk_len; } else #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if (key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { /* * other_secret already set by the ClientKeyExchange message, * and is 48 bytes long */ if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } *p++ = 0; *p++ = 48; p += 48; } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if (key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* Write length only when we know the actual value */ if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, p + 2, (size_t) (end - (p + 2)), &len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return ret; } MBEDTLS_PUT_UINT16_BE(len, p, 0); p += 2 + len; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t zlen; if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &zlen, p + 2, (size_t) (end - (p + 2)), ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret); return ret; } MBEDTLS_PUT_UINT16_BE(zlen, p, 0); p += 2 + zlen; MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Z); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* opaque psk<0..2^16-1>; */ if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT16_BE(psk_len, p, 0); p += 2; if (end < p || (size_t) (end - p) < psk_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(p, psk, psk_len); p += psk_len; ssl->handshake->pmslen = (size_t) (p - ssl->handshake->premaster); return 0; } #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hello_request(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_PROTO_DTLS) int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl) { /* If renegotiation is not enforced, retransmit until we would reach max * timeout if we were using the usual handshake doubling scheme */ if (ssl->conf->renego_max_records < 0) { uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; unsigned char doublings = 1; while (ratio != 0) { ++doublings; ratio >>= 1; } if (++ssl->renego_records_seen > doublings) { MBEDTLS_SSL_DEBUG_MSG(2, ("no longer retransmitting hello request")); return 0; } } return ssl_write_hello_request(ssl); } #endif #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ /* * Handshake functions */ #if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* No certificate support -> dummy functions */ int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /* Some certificate support -> implement write and parse */ int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t i, n; const mbedtls_x509_crt *crt; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); ssl->state++; return 0; } #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { if (ssl->handshake->client_auth == 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); ssl->state++; return 0; } } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { if (mbedtls_ssl_own_cert(ssl) == NULL) { /* Should never happen because we shouldn't have picked the * ciphersuite if we don't have a certificate. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } #endif MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", mbedtls_ssl_own_cert(ssl)); /* * 0 . 0 handshake type * 1 . 3 handshake length * 4 . 6 length of all certs * 7 . 9 length of cert. 1 * 10 . n-1 peer certificate * n . n+2 length of cert. 2 * n+3 . ... upper level cert, etc. */ i = 7; crt = mbedtls_ssl_own_cert(ssl); while (crt != NULL) { n = crt->raw.len; if (n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i) { MBEDTLS_SSL_DEBUG_MSG(1, ("certificate too large, %" MBEDTLS_PRINTF_SIZET " > %" MBEDTLS_PRINTF_SIZET, i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN)); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } ssl->out_msg[i] = MBEDTLS_BYTE_2(n); ssl->out_msg[i + 1] = MBEDTLS_BYTE_1(n); ssl->out_msg[i + 2] = MBEDTLS_BYTE_0(n); i += 3; memcpy(ssl->out_msg + i, crt->raw.p, n); i += n; crt = crt->next; } ssl->out_msg[4] = MBEDTLS_BYTE_2(i - 7); ssl->out_msg[5] = MBEDTLS_BYTE_1(i - 7); ssl->out_msg[6] = MBEDTLS_BYTE_0(i - 7); ssl->out_msglen = i; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate")); return ret; } #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl, unsigned char *crt_buf, size_t crt_buf_len) { mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert; if (peer_crt == NULL) { return -1; } if (peer_crt->raw.len != crt_buf_len) { return -1; } return memcmp(peer_crt->raw.p, crt_buf, peer_crt->raw.len); } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl, unsigned char *crt_buf, size_t crt_buf_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char const * const peer_cert_digest = ssl->session->peer_cert_digest; mbedtls_md_type_t const peer_cert_digest_type = ssl->session->peer_cert_digest_type; mbedtls_md_info_t const * const digest_info = mbedtls_md_info_from_type(peer_cert_digest_type); unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN]; size_t digest_len; if (peer_cert_digest == NULL || digest_info == NULL) { return -1; } digest_len = mbedtls_md_get_size(digest_info); if (digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN) { return -1; } ret = mbedtls_md(digest_info, crt_buf, crt_buf_len, tmp_digest); if (ret != 0) { return -1; } return memcmp(tmp_digest, peer_cert_digest, digest_len); } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ /* * Once the certificate message is read, parse it into a cert chain and * perform basic checks, but leave actual verification to the caller */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_chain(mbedtls_ssl_context *ssl, mbedtls_x509_crt *chain) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) int crt_cnt = 0; #endif size_t i, n; uint8_t alert; if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } if (ssl->in_hslen < mbedtls_ssl_hs_hdr_len(ssl) + 3 + 3) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } i = mbedtls_ssl_hs_hdr_len(ssl); /* * Same message structure as in mbedtls_ssl_write_certificate() */ n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1); if (ssl->in_msg[i] != 0 || ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */ i += 3; /* Iterate through and parse the CRTs in the provided chain. */ while (i < ssl->in_hslen) { /* Check that there's room for the next CRT's length fields. */ if (i + 3 > ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* In theory, the CRT can be up to 2**24 Bytes, but we don't support * anything beyond 2**16 ~ 64K. */ if (ssl->in_msg[i] != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT); return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } /* Read length of the next CRT in the chain. */ n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1); i += 3; if (n < 128 || i + n > ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Check if we're handling the first CRT in the chain. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) if (crt_cnt++ == 0 && ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { /* During client-side renegotiation, check that the server's * end-CRTs hasn't changed compared to the initial handshake, * mitigating the triple handshake attack. On success, reuse * the original end-CRT instead of parsing it again. */ MBEDTLS_SSL_DEBUG_MSG(3, ("Check that peer CRT hasn't changed during renegotiation")); if (ssl_check_peer_crt_unchanged(ssl, &ssl->in_msg[i], n) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("new server cert during renegotiation")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED); return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } /* Now we can safely free the original chain. */ ssl_clear_peer_cert(ssl->session); } #endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ /* Parse the next certificate in the chain. */ #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) ret = mbedtls_x509_crt_parse_der(chain, ssl->in_msg + i, n); #else /* If we don't need to store the CRT chain permanently, parse * it in-place from the input buffer instead of making a copy. */ ret = mbedtls_x509_crt_parse_der_nocopy(chain, ssl->in_msg + i, n); #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ switch (ret) { case 0: /*ok*/ case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: /* Ignore certificate with an unknown algorithm: maybe a prior certificate was already trusted. */ break; case MBEDTLS_ERR_X509_ALLOC_FAILED: alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; goto crt_parse_der_failed; case MBEDTLS_ERR_X509_UNKNOWN_VERSION: alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; goto crt_parse_der_failed; default: alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; crt_parse_der_failed: mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert); MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); return ret; } i += n; } MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", chain); return 0; } #if defined(MBEDTLS_SSL_SRV_C) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_srv_check_client_no_crt_notification(mbedtls_ssl_context *ssl) { if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { return -1; } if (ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len(ssl) && ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), "\0\0\0", 3) == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate")); return 0; } return -1; } #endif /* MBEDTLS_SSL_SRV_C */ /* Check if a certificate message is expected. * Return either * - SSL_CERTIFICATE_EXPECTED, or * - SSL_CERTIFICATE_SKIP * indicating whether a Certificate message is expected or not. */ #define SSL_CERTIFICATE_EXPECTED 0 #define SSL_CERTIFICATE_SKIP 1 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl, int authmode) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { return SSL_CERTIFICATE_SKIP; } #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { return SSL_CERTIFICATE_SKIP; } if (authmode == MBEDTLS_SSL_VERIFY_NONE) { ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; return SSL_CERTIFICATE_SKIP; } } #else ((void) authmode); #endif /* MBEDTLS_SSL_SRV_C */ return SSL_CERTIFICATE_EXPECTED; } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl, unsigned char *start, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Remember digest of the peer's end-CRT. */ ssl->session_negotiate->peer_cert_digest = mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN); if (ssl->session_negotiate->peer_cert_digest == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%d bytes) failed", MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN)); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } ret = mbedtls_md(mbedtls_md_info_from_type( MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE), start, len, ssl->session_negotiate->peer_cert_digest); ssl->session_negotiate->peer_cert_digest_type = MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE; ssl->session_negotiate->peer_cert_digest_len = MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN; return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_remember_peer_pubkey(mbedtls_ssl_context *ssl, unsigned char *start, size_t len) { unsigned char *end = start + len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Make a copy of the peer's raw public key. */ mbedtls_pk_init(&ssl->handshake->peer_pubkey); ret = mbedtls_pk_parse_subpubkey(&start, end, &ssl->handshake->peer_pubkey); if (ret != 0) { /* We should have parsed the public key before. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return 0; } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl) { int ret = 0; int crt_expected; /* Authmode: precedence order is SNI if used else configuration */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ? ssl->handshake->sni_authmode : ssl->conf->authmode; #else const int authmode = ssl->conf->authmode; #endif void *rs_ctx = NULL; mbedtls_x509_crt *chain = NULL; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); crt_expected = ssl_parse_certificate_coordinate(ssl, authmode); if (crt_expected == SSL_CERTIFICATE_SKIP) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate")); goto exit; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_crt_verify) { chain = ssl->handshake->ecrs_peer_cert; ssl->handshake->ecrs_peer_cert = NULL; goto crt_verify; } #endif if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { /* mbedtls_ssl_read_record may have sent an alert already. We let it decide whether to alert. */ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); goto exit; } #if defined(MBEDTLS_SSL_SRV_C) if (ssl_srv_check_client_no_crt_notification(ssl) == 0) { ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; if (authmode != MBEDTLS_SSL_VERIFY_OPTIONAL) { ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; } goto exit; } #endif /* MBEDTLS_SSL_SRV_C */ /* Clear existing peer CRT structure in case we tried to * reuse a session but it failed, and allocate a new one. */ ssl_clear_peer_cert(ssl->session_negotiate); chain = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); if (chain == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", sizeof(mbedtls_x509_crt))); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } mbedtls_x509_crt_init(chain); ret = ssl_parse_certificate_chain(ssl, chain); if (ret != 0) { goto exit; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; } crt_verify: if (ssl->handshake->ecrs_enabled) { rs_ctx = &ssl->handshake->ecrs_ctx; } #endif ret = mbedtls_ssl_verify_certificate(ssl, authmode, chain, ssl->handshake->ciphersuite_info, rs_ctx); if (ret != 0) { goto exit; } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) { unsigned char *crt_start, *pk_start; size_t crt_len, pk_len; /* We parse the CRT chain without copying, so * these pointers point into the input buffer, * and are hence still valid after freeing the * CRT chain. */ crt_start = chain->raw.p; crt_len = chain->raw.len; pk_start = chain->pk_raw.p; pk_len = chain->pk_raw.len; /* Free the CRT structures before computing * digest and copying the peer's public key. */ mbedtls_x509_crt_free(chain); mbedtls_free(chain); chain = NULL; ret = ssl_remember_peer_crt_digest(ssl, crt_start, crt_len); if (ret != 0) { goto exit; } ret = ssl_remember_peer_pubkey(ssl, pk_start, pk_len); if (ret != 0) { goto exit; } } #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* Pass ownership to session structure. */ ssl->session_negotiate->peer_cert = chain; chain = NULL; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate")); exit: if (ret == 0) { ssl->state++; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) { ssl->handshake->ecrs_peer_cert = chain; chain = NULL; } #endif if (chain != NULL) { mbedtls_x509_crt_free(chain); mbedtls_free(chain); } return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ static int ssl_calc_finished_tls_generic(mbedtls_ssl_context *ssl, void *ctx, unsigned char *padbuf, size_t hlen, unsigned char *buf, int from) { unsigned int len = 12; const char *sender; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; psa_hash_operation_t *hs_op = ctx; psa_hash_operation_t cloned_op = PSA_HASH_OPERATION_INIT; size_t hash_size; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_context_t *hs_ctx = ctx; mbedtls_md_context_t cloned_ctx; mbedtls_md_init(&cloned_ctx); #endif mbedtls_ssl_session *session = ssl->session_negotiate; if (!session) { session = ssl->session; } sender = (from == MBEDTLS_SSL_IS_CLIENT) ? "client finished" : "server finished"; #if defined(MBEDTLS_USE_PSA_CRYPTO) MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls")); status = psa_hash_clone(hs_op, &cloned_op); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&cloned_op, padbuf, hlen, &hash_size); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, hlen); #else MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished tls")); ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_clone(&cloned_ctx, hs_ctx); if (ret != 0) { goto exit; } ret = mbedtls_md_finish(&cloned_ctx, padbuf); if (ret != 0) { goto exit; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_BUF(4, "finished output", padbuf, hlen); /* * TLSv1.2: * hash = PRF( master, finished_label, * Hash( handshake ) )[0.11] */ ssl->handshake->tls_prf(session->master, 48, sender, padbuf, hlen, buf, len); MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len); mbedtls_platform_zeroize(padbuf, hlen); MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc finished")); exit: #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_abort(&cloned_op); return mbedtls_md_error_from_psa(status); #else mbedtls_md_free(&cloned_ctx); return ret; #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #if defined(MBEDTLS_MD_CAN_SHA256) static int ssl_calc_finished_tls_sha256( mbedtls_ssl_context *ssl, unsigned char *buf, int from) { unsigned char padbuf[32]; return ssl_calc_finished_tls_generic(ssl, #if defined(MBEDTLS_USE_PSA_CRYPTO) &ssl->handshake->fin_sha256_psa, #else &ssl->handshake->fin_sha256, #endif padbuf, sizeof(padbuf), buf, from); } #endif /* MBEDTLS_MD_CAN_SHA256*/ #if defined(MBEDTLS_MD_CAN_SHA384) static int ssl_calc_finished_tls_sha384( mbedtls_ssl_context *ssl, unsigned char *buf, int from) { unsigned char padbuf[48]; return ssl_calc_finished_tls_generic(ssl, #if defined(MBEDTLS_USE_PSA_CRYPTO) &ssl->handshake->fin_sha384_psa, #else &ssl->handshake->fin_sha384, #endif padbuf, sizeof(padbuf), buf, from); } #endif /* MBEDTLS_MD_CAN_SHA384*/ void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup: final free")); /* * Free our handshake params */ mbedtls_ssl_handshake_free(ssl); mbedtls_free(ssl->handshake); ssl->handshake = NULL; /* * Free the previous transform and switch in the current one */ if (ssl->transform) { mbedtls_ssl_transform_free(ssl->transform); mbedtls_free(ssl->transform); } ssl->transform = ssl->transform_negotiate; ssl->transform_negotiate = NULL; MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup: final free")); } void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl) { int resume = ssl->handshake->resume; MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup")); #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; ssl->renego_records_seen = 0; } #endif /* * Free the previous session and switch in the current one */ if (ssl->session) { #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) /* RFC 7366 3.1: keep the EtM state */ ssl->session_negotiate->encrypt_then_mac = ssl->session->encrypt_then_mac; #endif mbedtls_ssl_session_free(ssl->session); mbedtls_free(ssl->session); } ssl->session = ssl->session_negotiate; ssl->session_negotiate = NULL; /* * Add cache entry */ if (ssl->conf->f_set_cache != NULL && ssl->session->id_len != 0 && resume == 0) { if (ssl->conf->f_set_cache(ssl->conf->p_cache, ssl->session->id, ssl->session->id_len, ssl->session) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("cache did not store session")); } } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->flight != NULL) { /* Cancel handshake timer */ mbedtls_ssl_set_timer(ssl, 0); /* Keep last flight around in case we need to resend it: * we need the handshake and transform structures for that */ MBEDTLS_SSL_DEBUG_MSG(3, ("skip freeing handshake and transform")); } else #endif mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl); ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup")); } int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl) { int ret; unsigned int hash_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished")); mbedtls_ssl_update_out_pointers(ssl, ssl->transform_negotiate); ret = ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret); } /* * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites * may define some other value. Currently (early 2016), no defined * ciphersuite does this (and this is unlikely to change as activity has * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. */ hash_len = 12; #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->verify_data_len = hash_len; memcpy(ssl->own_verify_data, ssl->out_msg + 4, hash_len); #endif ssl->out_msglen = 4 + hash_len; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; /* * In case of session resuming, invert the client and server * ChangeCipherSpec messages order. */ if (ssl->handshake->resume != 0) { #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; } #endif #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; } #endif } else { ssl->state++; } /* * Switch to our negotiated transform and session parameters for outbound * data. */ MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for outbound data")); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { unsigned char i; /* Remember current epoch settings for resending */ ssl->handshake->alt_transform_out = ssl->transform_out; memcpy(ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, sizeof(ssl->handshake->alt_out_ctr)); /* Set sequence_number to zero */ memset(&ssl->cur_out_ctr[2], 0, sizeof(ssl->cur_out_ctr) - 2); /* Increment epoch */ for (i = 2; i > 0; i--) { if (++ssl->cur_out_ctr[i - 1] != 0) { break; } } /* The loop goes to its end iff the counter is wrapping */ if (i == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap")); return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; } } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); ssl->transform_out = ssl->transform_negotiate; ssl->session_out = ssl->session_negotiate; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_send_flight_completed(ssl); } #endif if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); return ret; } #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished")); return 0; } #define SSL_MAX_HASH_LEN 12 int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned int hash_len = 12; unsigned char buf[SSL_MAX_HASH_LEN]; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished")); ret = ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret); } if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); goto exit; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; goto exit; } if (ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; goto exit; } if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + hash_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); ret = MBEDTLS_ERR_SSL_DECODE_ERROR; goto exit; } if (mbedtls_ct_memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), buf, hash_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR); ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; goto exit; } #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->verify_data_len = hash_len; memcpy(ssl->peer_verify_data, buf, hash_len); #endif if (ssl->handshake->resume != 0) { #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; } #endif #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; } #endif } else { ssl->state++; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_recv_flight_completed(ssl); } #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished")); exit: mbedtls_platform_zeroize(buf, hash_len); return ret; } #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) /* * Helper to get TLS 1.2 PRF from ciphersuite * (Duplicates bits of logic from ssl_set_handshake_prfs().) */ static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id) { const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id); #if defined(MBEDTLS_MD_CAN_SHA384) if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA384) { return tls_prf_sha384; } else #endif #if defined(MBEDTLS_MD_CAN_SHA256) { if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA256) { return tls_prf_sha256; } } #endif #if !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA256) (void) ciphersuite_info; #endif return NULL; } #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ static mbedtls_tls_prf_types tls_prf_get_type(mbedtls_ssl_tls_prf_cb *tls_prf) { ((void) tls_prf); #if defined(MBEDTLS_MD_CAN_SHA384) if (tls_prf == tls_prf_sha384) { return MBEDTLS_SSL_TLS_PRF_SHA384; } else #endif #if defined(MBEDTLS_MD_CAN_SHA256) if (tls_prf == tls_prf_sha256) { return MBEDTLS_SSL_TLS_PRF_SHA256; } else #endif return MBEDTLS_SSL_TLS_PRF_NONE; } /* * Populate a transform structure with session keys and all the other * necessary information. * * Parameters: * - [in/out]: transform: structure to populate * [in] must be just initialised with mbedtls_ssl_transform_init() * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf() * - [in] ciphersuite * - [in] master * - [in] encrypt_then_mac * - [in] tls_prf: pointer to PRF to use for key derivation * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random * - [in] tls_version: TLS version * - [in] endpoint: client or server * - [in] ssl: used for: * - ssl->conf->{f,p}_export_keys * [in] optionally used for: * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform, int ciphersuite, const unsigned char master[48], #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) int encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ ssl_tls_prf_t tls_prf, const unsigned char randbytes[64], mbedtls_ssl_protocol_version tls_version, unsigned endpoint, const mbedtls_ssl_context *ssl) { int ret = 0; unsigned char keyblk[256]; unsigned char *key1; unsigned char *key2; unsigned char *mac_enc; unsigned char *mac_dec; size_t mac_key_len = 0; size_t iv_copy_len; size_t keylen; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; mbedtls_ssl_mode_t ssl_mode; #if !defined(MBEDTLS_USE_PSA_CRYPTO) const mbedtls_cipher_info_t *cipher_info; const mbedtls_md_info_t *md_info; #endif /* !MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_type_t key_type; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t alg; psa_algorithm_t mac_alg = 0; size_t key_bits; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif /* * Some data just needs copying into the structure */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) transform->encrypt_then_mac = encrypt_then_mac; #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ transform->tls_version = tls_version; #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes)); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform * generation separate. This should never happen. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /* * Get various info structures */ ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); if (ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found", ciphersuite)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite( #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ ciphersuite_info); if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { transform->taglen = ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, transform->taglen, &alg, &key_type, &key_bits)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", ret); goto end; } #else cipher_info = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) ciphersuite_info->cipher); if (cipher_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found", ciphersuite_info->cipher)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) mac_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); if (mac_alg == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md_psa_alg_from_type for %u not found", (unsigned) ciphersuite_info->mac)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #else md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) ciphersuite_info->mac); if (md_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md info for %u not found", (unsigned) ciphersuite_info->mac)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* Copy own and peer's CID if the use of the CID * extension has been negotiated. */ if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED) { MBEDTLS_SSL_DEBUG_MSG(3, ("Copy CIDs into SSL transform")); transform->in_cid_len = ssl->own_cid_len; memcpy(transform->in_cid, ssl->own_cid, ssl->own_cid_len); MBEDTLS_SSL_DEBUG_BUF(3, "Incoming CID", transform->in_cid, transform->in_cid_len); transform->out_cid_len = ssl->handshake->peer_cid_len; memcpy(transform->out_cid, ssl->handshake->peer_cid, ssl->handshake->peer_cid_len); MBEDTLS_SSL_DEBUG_BUF(3, "Outgoing CID", transform->out_cid, transform->out_cid_len); } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /* * Compute key block using the PRF */ ret = tls_prf(master, 48, "key expansion", randbytes, 64, keyblk, 256); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "prf", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite = %s", mbedtls_ssl_get_ciphersuite_name(ciphersuite))); MBEDTLS_SSL_DEBUG_BUF(3, "master secret", master, 48); MBEDTLS_SSL_DEBUG_BUF(4, "random bytes", randbytes, 64); MBEDTLS_SSL_DEBUG_BUF(4, "key block", keyblk, 256); /* * Determine the appropriate key, IV and MAC length. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) keylen = PSA_BITS_TO_BYTES(key_bits); #else keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; #endif #if defined(MBEDTLS_SSL_HAVE_AEAD) if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { size_t explicit_ivlen; transform->maclen = 0; mac_key_len = 0; /* All modes haves 96-bit IVs, but the length of the static parts vary * with mode and version: * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes * (to be concatenated with a dynamically chosen IV of 8 Bytes) * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's * a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record * sequence number). */ transform->ivlen = 12; int is_chachapoly = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) is_chachapoly = (key_type == PSA_KEY_TYPE_CHACHA20); #else is_chachapoly = (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CHACHAPOLY); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (is_chachapoly) { transform->fixed_ivlen = 12; } else { transform->fixed_ivlen = 4; } /* Minimum length of encrypted record */ explicit_ivlen = transform->ivlen - transform->fixed_ivlen; transform->minlen = explicit_ivlen + transform->taglen; } else #endif /* MBEDTLS_SSL_HAVE_AEAD */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (ssl_mode == MBEDTLS_SSL_MODE_STREAM || ssl_mode == MBEDTLS_SSL_MODE_CBC || ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type); #else size_t block_size = mbedtls_cipher_info_get_block_size(cipher_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Get MAC length */ mac_key_len = PSA_HASH_LENGTH(mac_alg); #else /* Initialize HMAC contexts */ if ((ret = mbedtls_md_setup(&transform->md_ctx_enc, md_info, 1)) != 0 || (ret = mbedtls_md_setup(&transform->md_ctx_dec, md_info, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret); goto end; } /* Get MAC length */ mac_key_len = mbedtls_md_get_size(md_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ transform->maclen = mac_key_len; /* IV length */ #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->ivlen = PSA_CIPHER_IV_LENGTH(key_type, alg); #else transform->ivlen = mbedtls_cipher_info_get_iv_size(cipher_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Minimum length */ if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { transform->minlen = transform->maclen; } else { /* * GenericBlockCipher: * 1. if EtM is in use: one block plus MAC * otherwise: * first multiple of blocklen greater than maclen * 2. IV */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { transform->minlen = transform->maclen + block_size; } else #endif { transform->minlen = transform->maclen + block_size - transform->maclen % block_size; } if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { transform->minlen += transform->ivlen; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto end; } } } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("keylen: %u, minlen: %u, ivlen: %u, maclen: %u", (unsigned) keylen, (unsigned) transform->minlen, (unsigned) transform->ivlen, (unsigned) transform->maclen)); /* * Finally setup the cipher contexts, IVs and MAC secrets. */ #if defined(MBEDTLS_SSL_CLI_C) if (endpoint == MBEDTLS_SSL_IS_CLIENT) { key1 = keyblk + mac_key_len * 2; key2 = keyblk + mac_key_len * 2 + keylen; mac_enc = keyblk; mac_dec = keyblk + mac_key_len; iv_copy_len = (transform->fixed_ivlen) ? transform->fixed_ivlen : transform->ivlen; memcpy(transform->iv_enc, key2 + keylen, iv_copy_len); memcpy(transform->iv_dec, key2 + keylen + iv_copy_len, iv_copy_len); } else #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) if (endpoint == MBEDTLS_SSL_IS_SERVER) { key1 = keyblk + mac_key_len * 2 + keylen; key2 = keyblk + mac_key_len * 2; mac_enc = keyblk + mac_key_len; mac_dec = keyblk; iv_copy_len = (transform->fixed_ivlen) ? transform->fixed_ivlen : transform->ivlen; memcpy(transform->iv_dec, key1 + keylen, iv_copy_len); memcpy(transform->iv_enc, key1 + keylen + iv_copy_len, iv_copy_len); } else #endif /* MBEDTLS_SSL_SRV_C */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto end; } if (ssl->f_export_keys != NULL) { ssl->f_export_keys(ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET, master, 48, randbytes + 32, randbytes, tls_prf_get_type(tls_prf)); } #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_alg = alg; if (alg != MBEDTLS_SSL_NULL_CIPHER) { psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, key_type); if ((status = psa_import_key(&attributes, key1, PSA_BITS_TO_BYTES(key_bits), &transform->psa_key_enc)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(3, "psa_import_key", (int) status); ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret); goto end; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); if ((status = psa_import_key(&attributes, key2, PSA_BITS_TO_BYTES(key_bits), &transform->psa_key_dec)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret); goto end; } } #else if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc, cipher_info)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); goto end; } if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec, cipher_info)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); goto end; } if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key1, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), MBEDTLS_ENCRYPT)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); goto end; } if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key2, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), MBEDTLS_DECRYPT)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); goto end; } #if defined(MBEDTLS_CIPHER_MODE_CBC) if (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CBC) { if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_enc, MBEDTLS_PADDING_NONE)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret); goto end; } if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_dec, MBEDTLS_PADDING_NONE)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret); goto end; } } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) /* For HMAC-based ciphersuites, initialize the HMAC transforms. For AEAD-based ciphersuites, there is nothing to do here. */ if (mac_key_len != 0) { #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_mac_alg = PSA_ALG_HMAC(mac_alg); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(mac_alg)); psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); if ((status = psa_import_key(&attributes, mac_enc, mac_key_len, &transform->psa_mac_enc)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret); goto end; } if ((transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) || ((transform->psa_alg == PSA_ALG_CBC_NO_PADDING) #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) && (transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) #endif )) { /* mbedtls_ct_hmac() requires the key to be exportable */ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH); } else { psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); } if ((status = psa_import_key(&attributes, mac_dec, mac_key_len, &transform->psa_mac_dec)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret); goto end; } #else ret = mbedtls_md_hmac_starts(&transform->md_ctx_enc, mac_enc, mac_key_len); if (ret != 0) { goto end; } ret = mbedtls_md_hmac_starts(&transform->md_ctx_dec, mac_dec, mac_key_len); if (ret != 0) { goto end; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ ((void) mac_dec); ((void) mac_enc); end: mbedtls_platform_zeroize(keyblk, sizeof(keyblk)); return ret; } #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_psa_ecjpake_read_round( psa_pake_operation_t *pake_ctx, const unsigned char *buf, size_t len, mbedtls_ecjpake_rounds_t round) { psa_status_t status; size_t input_offset = 0; /* * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice * At round two perform a single cycle */ unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; for (; remaining_steps > 0; remaining_steps--) { for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; step <= PSA_PAKE_STEP_ZK_PROOF; ++step) { /* Length is stored at the first byte */ size_t length = buf[input_offset]; input_offset += 1; if (input_offset + length > len) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } status = psa_pake_input(pake_ctx, step, buf + input_offset, length); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } input_offset += length; } } if (input_offset != len) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } return 0; } int mbedtls_psa_ecjpake_write_round( psa_pake_operation_t *pake_ctx, unsigned char *buf, size_t len, size_t *olen, mbedtls_ecjpake_rounds_t round) { psa_status_t status; size_t output_offset = 0; size_t output_len; /* * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice * At round two perform a single cycle */ unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; for (; remaining_steps > 0; remaining_steps--) { for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; step <= PSA_PAKE_STEP_ZK_PROOF; ++step) { /* * For each step, prepend 1 byte with the length of the data as * given by psa_pake_output(). */ status = psa_pake_output(pake_ctx, step, buf + output_offset + 1, len - output_offset - 1, &output_len); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } *(buf + output_offset) = (uint8_t) output_len; output_offset += output_len + 1; } } *olen = output_offset; return 0; } #endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hashlen, unsigned char *data, size_t data_len, mbedtls_md_type_t md_alg) { psa_status_t status; psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(md_alg); MBEDTLS_SSL_DEBUG_MSG(3, ("Perform PSA-based computation of digest of ServerKeyExchange")); if ((status = psa_hash_setup(&hash_operation, hash_alg)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_setup", status); goto exit; } if ((status = psa_hash_update(&hash_operation, ssl->handshake->randbytes, 64)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status); goto exit; } if ((status = psa_hash_update(&hash_operation, data, data_len)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status); goto exit; } if ((status = psa_hash_finish(&hash_operation, hash, PSA_HASH_MAX_SIZE, hashlen)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_finish", status); goto exit; } exit: if (status != PSA_SUCCESS) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); switch (status) { case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */ case PSA_ERROR_BUFFER_TOO_SMALL: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; case PSA_ERROR_INSUFFICIENT_MEMORY: return MBEDTLS_ERR_MD_ALLOC_FAILED; default: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } } return 0; } #else int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hashlen, unsigned char *data, size_t data_len, mbedtls_md_type_t md_alg) { int ret = 0; mbedtls_md_context_t ctx; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg); *hashlen = mbedtls_md_get_size(md_info); MBEDTLS_SSL_DEBUG_MSG(3, ("Perform mbedtls-based computation of digest of ServerKeyExchange")); mbedtls_md_init(&ctx); /* * digitally-signed struct { * opaque client_random[32]; * opaque server_random[32]; * ServerDHParams params; * }; */ if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret); goto exit; } if ((ret = mbedtls_md_starts(&ctx)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_starts", ret); goto exit; } if ((ret = mbedtls_md_update(&ctx, ssl->handshake->randbytes, 64)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret); goto exit; } if ((ret = mbedtls_md_update(&ctx, data, data_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret); goto exit; } if ((ret = mbedtls_md_finish(&ctx, hash)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); goto exit; } exit: mbedtls_md_free(&ctx); if (ret != 0) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); } return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* Find the preferred hash for a given signature algorithm. */ unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( mbedtls_ssl_context *ssl, unsigned int sig_alg) { unsigned int i; uint16_t *received_sig_algs = ssl->handshake->received_sig_algs; if (sig_alg == MBEDTLS_SSL_SIG_ANON) { return MBEDTLS_SSL_HASH_NONE; } for (i = 0; received_sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) { unsigned int hash_alg_received = MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG( received_sig_algs[i]); unsigned int sig_alg_received = MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG( received_sig_algs[i]); mbedtls_md_type_t md_alg = mbedtls_ssl_md_alg_from_hash((unsigned char) hash_alg_received); if (md_alg == MBEDTLS_MD_NONE) { continue; } if (sig_alg == sig_alg_received) { #if defined(MBEDTLS_USE_PSA_CRYPTO) if (ssl->handshake->key_cert && ssl->handshake->key_cert->key) { psa_algorithm_t psa_hash_alg = mbedtls_md_psa_alg_from_type(md_alg); if (sig_alg_received == MBEDTLS_SSL_SIG_ECDSA && !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key, PSA_ALG_ECDSA(psa_hash_alg), PSA_KEY_USAGE_SIGN_HASH)) { continue; } if (sig_alg_received == MBEDTLS_SSL_SIG_RSA && !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key, PSA_ALG_RSA_PKCS1V15_SIGN( psa_hash_alg), PSA_KEY_USAGE_SIGN_HASH)) { continue; } } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return hash_alg_received; } } return MBEDTLS_SSL_HASH_NONE; } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ int mbedtls_ssl_validate_ciphersuite( const mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *suite_info, mbedtls_ssl_protocol_version min_tls_version, mbedtls_ssl_protocol_version max_tls_version) { (void) ssl; if (suite_info == NULL) { return -1; } if ((suite_info->min_tls_version > max_tls_version) || (suite_info->max_tls_version < min_tls_version)) { return -1; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && ssl->handshake->psa_pake_ctx_is_ok != 1) #else if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) #endif /* MBEDTLS_USE_PSA_CRYPTO */ { return -1; } #endif /* Don't suggest PSK-based ciphersuite if no PSK is available. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) && mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { return -1; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ return 0; } #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* * Function for writing a signature algorithm extension. * * The `extension_data` field of signature algorithm contains a `SignatureSchemeList` * value (TLS 1.3 RFC8446): * enum { * .... * ecdsa_secp256r1_sha256( 0x0403 ), * ecdsa_secp384r1_sha384( 0x0503 ), * ecdsa_secp521r1_sha512( 0x0603 ), * .... * } SignatureScheme; * * struct { * SignatureScheme supported_signature_algorithms<2..2^16-2>; * } SignatureSchemeList; * * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm` * value (TLS 1.2 RFC5246): * enum { * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), * sha512(6), (255) * } HashAlgorithm; * * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } * SignatureAlgorithm; * * struct { * HashAlgorithm hash; * SignatureAlgorithm signature; * } SignatureAndHashAlgorithm; * * SignatureAndHashAlgorithm * supported_signature_algorithms<2..2^16-2>; * * The TLS 1.3 signature algorithm extension was defined to be a compatible * generalization of the TLS 1.2 signature algorithm extension. * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by * `SignatureScheme` field of TLS 1.3 * */ int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len) { unsigned char *p = buf; unsigned char *supported_sig_alg; /* Start of supported_signature_algorithms */ size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */ *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("adding signature_algorithms extension")); /* Check if we have space for header and length field: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - supported_signature_algorithms_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); p += 6; /* * Write supported_signature_algorithms */ supported_sig_alg = p; const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); if (sig_alg == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { MBEDTLS_SSL_DEBUG_MSG(3, ("got signature scheme [%x] %s", *sig_alg, mbedtls_ssl_sig_alg_to_str(*sig_alg))); if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) { continue; } MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(3, ("sent signature scheme [%x] %s", *sig_alg, mbedtls_ssl_sig_alg_to_str(*sig_alg))); } /* Length of supported_signature_algorithms */ supported_sig_alg_len = (size_t) (p - supported_sig_alg); if (supported_sig_alg_len == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("No signature algorithms defined.")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SIG_ALG, buf, 0); MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len + 2, buf, 2); MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len, buf, 4); *out_len = (size_t) (p - buf); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SIG_ALG); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ return 0; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /* * mbedtls_ssl_parse_server_name_ext * * Structure of server_name extension: * * enum { * host_name(0), (255) * } NameType; * opaque HostName<1..2^16-1>; * * struct { * NameType name_type; * select (name_type) { * case host_name: HostName; * } name; * } ServerName; * struct { * ServerName server_name_list<1..2^16-1> * } ServerNameList; */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; size_t server_name_list_len, hostname_len; const unsigned char *server_name_list_end; MBEDTLS_SSL_DEBUG_MSG(3, ("parse ServerName extension")); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); server_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, server_name_list_len); server_name_list_end = p + server_name_list_len; while (p < server_name_list_end) { MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, 3); hostname_len = MBEDTLS_GET_UINT16_BE(p, 1); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, hostname_len + 3); if (p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME) { /* sni_name is intended to be used only during the parsing of the * ClientHello message (it is reset to NULL before the end of * the message parsing). Thus it is ok to just point to the * reception buffer and not make a copy of it. */ ssl->handshake->sni_name = p + 3; ssl->handshake->sni_name_len = hostname_len; if (ssl->conf->f_sni == NULL) { return 0; } ret = ssl->conf->f_sni(ssl->conf->p_sni, ssl, p + 3, hostname_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_sni_wrapper", ret); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME, MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME); return MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME; } return 0; } p += hostname_len + 3; } return 0; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t protocol_name_list_len; const unsigned char *protocol_name_list; const unsigned char *protocol_name_list_end; size_t protocol_name_len; /* If ALPN not configured, just ignore the extension */ if (ssl->conf->alpn_list == NULL) { return 0; } /* * RFC7301, section 3.1 * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; */ /* * protocol_name_list_len 2 bytes * protocol_name_len 1 bytes * protocol_name >=1 byte */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len); protocol_name_list = p; protocol_name_list_end = p + protocol_name_list_len; /* Validate peer's list (lengths) */ while (p < protocol_name_list_end) { protocol_name_len = *p++; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, protocol_name_len); if (protocol_name_len == 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += protocol_name_len; } /* Use our order of preference */ for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) { size_t const alpn_len = strlen(*alpn); p = protocol_name_list; while (p < protocol_name_list_end) { protocol_name_len = *p++; if (protocol_name_len == alpn_len && memcmp(p, *alpn, alpn_len) == 0) { ssl->alpn_chosen = *alpn; return 0; } p += protocol_name_len; } } /* If we get here, no match was found */ MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL, MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL); return MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL; } int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; size_t protocol_name_len; *out_len = 0; if (ssl->alpn_chosen == NULL) { return 0; } protocol_name_len = strlen(ssl->alpn_chosen); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7 + protocol_name_len); MBEDTLS_SSL_DEBUG_MSG(3, ("server side, adding alpn extension")); /* * 0 . 1 ext identifier * 2 . 3 ext length * 4 . 5 protocol list length * 6 . 6 protocol name length * 7 . 7+n protocol name */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0); *out_len = 7 + protocol_name_len; MBEDTLS_PUT_UINT16_BE(protocol_name_len + 3, p, 2); MBEDTLS_PUT_UINT16_BE(protocol_name_len + 1, p, 4); /* Note: the length of the chosen protocol has been checked to be less * than 255 bytes in `mbedtls_ssl_conf_alpn_protocols`. */ p[6] = MBEDTLS_BYTE_0(protocol_name_len); memcpy(p + 7, ssl->alpn_chosen, protocol_name_len); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN); #endif return 0; } #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ defined(MBEDTLS_SSL_CLI_C) int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session, const char *hostname) { /* Initialize to suppress unnecessary compiler warning */ size_t hostname_len = 0; /* Check if new hostname is valid before * making any change to current one */ if (hostname != NULL) { hostname_len = strlen(hostname); if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } /* Now it's clear that we will overwrite the old hostname, * so we can free it safely */ if (session->hostname != NULL) { mbedtls_zeroize_and_free(session->hostname, strlen(session->hostname)); } /* Passing NULL as hostname shall clear the old one */ if (hostname == NULL) { session->hostname = NULL; } else { session->hostname = mbedtls_calloc(1, hostname_len + 1); if (session->hostname == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->hostname, hostname, hostname_len); } return 0; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \ defined(MBEDTLS_SSL_ALPN) int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session, const char *alpn) { size_t alpn_len = 0; if (alpn != NULL) { alpn_len = strlen(alpn); if (alpn_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } if (session->ticket_alpn != NULL) { mbedtls_zeroize_and_free(session->ticket_alpn, strlen(session->ticket_alpn)); session->ticket_alpn = NULL; } if (alpn != NULL) { session->ticket_alpn = mbedtls_calloc(alpn_len + 1, 1); if (session->ticket_alpn == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->ticket_alpn, alpn, alpn_len); } return 0; } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */ /* * The following functions are used by 1.2 and 1.3, client and server. */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, const mbedtls_ssl_ciphersuite_t *ciphersuite, int recv_endpoint, mbedtls_ssl_protocol_version tls_version, uint32_t *flags) { int ret = 0; unsigned int usage = 0; const char *ext_oid; size_t ext_len; /* * keyUsage */ /* Note: don't guard this with MBEDTLS_SSL_CLI_C because the server wants * to check what a compliant client will think while choosing which cert * to send to the client. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && recv_endpoint == MBEDTLS_SSL_IS_CLIENT) { /* TLS 1.2 server part of the key exchange */ switch (ciphersuite->key_exchange) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; break; case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; break; case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: usage = MBEDTLS_X509_KU_KEY_AGREEMENT; break; /* Don't use default: we want warnings when adding new values */ case MBEDTLS_KEY_EXCHANGE_NONE: case MBEDTLS_KEY_EXCHANGE_PSK: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECJPAKE: usage = 0; } } else #endif { /* This is either TLS 1.3 authentication, which always uses signatures, * or 1.2 client auth: rsa_sign and mbedtls_ecdsa_sign are the only * options we implement, both using signatures. */ (void) tls_version; (void) ciphersuite; usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; } if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) { *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; ret = -1; } /* * extKeyUsage */ if (recv_endpoint == MBEDTLS_SSL_IS_CLIENT) { ext_oid = MBEDTLS_OID_SERVER_AUTH; ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH); } else { ext_oid = MBEDTLS_OID_CLIENT_AUTH; ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH); } if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) { *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; ret = -1; } return ret; } int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl, int authmode, mbedtls_x509_crt *chain, const mbedtls_ssl_ciphersuite_t *ciphersuite_info, void *rs_ctx) { if (authmode == MBEDTLS_SSL_VERIFY_NONE) { return 0; } /* * Primary check: use the appropriate X.509 verification function */ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); void *p_vrfy; if (ssl->f_vrfy != NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback")); f_vrfy = ssl->f_vrfy; p_vrfy = ssl->p_vrfy; } else { MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback")); f_vrfy = ssl->conf->f_vrfy; p_vrfy = ssl->conf->p_vrfy; } int ret = 0; int have_ca_chain_or_callback = 0; #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) if (ssl->conf->f_ca_cb != NULL) { ((void) rs_ctx); have_ca_chain_or_callback = 1; MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification")); ret = mbedtls_x509_crt_verify_with_ca_cb( chain, ssl->conf->f_ca_cb, ssl->conf->p_ca_cb, ssl->conf->cert_profile, ssl->hostname, &ssl->session_negotiate->verify_result, f_vrfy, p_vrfy); } else #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ { mbedtls_x509_crt *ca_chain; mbedtls_x509_crl *ca_crl; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_ca_chain != NULL) { ca_chain = ssl->handshake->sni_ca_chain; ca_crl = ssl->handshake->sni_ca_crl; } else #endif { ca_chain = ssl->conf->ca_chain; ca_crl = ssl->conf->ca_crl; } if (ca_chain != NULL) { have_ca_chain_or_callback = 1; } ret = mbedtls_x509_crt_verify_restartable( chain, ca_chain, ca_crl, ssl->conf->cert_profile, ssl->hostname, &ssl->session_negotiate->verify_result, f_vrfy, p_vrfy, rs_ctx); } if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret); } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif /* * Secondary checks: always done, but change 'ret' only if it was 0 */ /* With TLS 1.2 and ECC certs, check that the curve used by the * certificate is on our list of acceptable curves. * * With TLS 1.3 this is not needed because the curve is part of the * signature algorithm (eg ecdsa_secp256r1_sha256) which is checked when * we validate the signature made with the key associated to this cert. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && mbedtls_pk_can_do(&chain->pk, MBEDTLS_PK_ECKEY)) { if (mbedtls_ssl_check_curve(ssl, mbedtls_pk_get_ec_group_id(&chain->pk)) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)")); ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; if (ret == 0) { ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } } } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_PK_HAVE_ECC_KEYS */ /* Check X.509 usage extensions (keyUsage, extKeyUsage) */ if (mbedtls_ssl_check_cert_usage(chain, ciphersuite_info, ssl->conf->endpoint, ssl->tls_version, &ssl->session_negotiate->verify_result) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)")); if (ret == 0) { ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } } /* With authmode optional, we want to keep going if the certificate was * unacceptable, but still fail on other errors (out of memory etc), * including fatal errors from the f_vrfy callback. * * The only acceptable errors are: * - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: cert rejected by primary check; * - MBEDTLS_ERR_SSL_BAD_CERTIFICATE: cert rejected by secondary checks. * Anything else is a fatal error. */ if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) { ret = 0; } /* Return a specific error as this is a user error: inconsistent * configuration - can't verify without trust anchors. */ if (have_ca_chain_or_callback == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain")); ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; } if (ret != 0) { uint8_t alert; /* The certificate may have been rejected for several reasons. Pick one and send the corresponding alert. Which alert to send may be a subject of debate in some cases. */ if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) { alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) { alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) { alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) { alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) { alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) { alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) { alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) { alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; } else { alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; } mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert); } #if defined(MBEDTLS_DEBUG_C) if (ssl->session_negotiate->verify_result != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x", (unsigned int) ssl->session_negotiate->verify_result)); } else { MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear")); } #endif /* MBEDTLS_DEBUG_C */ return ret; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #endif /* MBEDTLS_SSL_TLS_C */ webfakes/src/mbedtls/library/psa_crypto_invasive.h0000644000176200001440000000720114740737024022176 0ustar liggesusers/** * \file psa_crypto_invasive.h * * \brief PSA cryptography module: invasive interfaces for test only. * * The interfaces in this file are intended for testing purposes only. * They MUST NOT be made available to clients over IPC in integrations * with isolation, and they SHOULD NOT be made available in library * integrations except when building the library for testing. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_INVASIVE_H #define PSA_CRYPTO_INVASIVE_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" #include "psa/crypto.h" #include "common.h" #include "mbedtls/entropy.h" #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) /** \brief Configure entropy sources. * * This function may only be called before a call to psa_crypto_init(), * or after a call to mbedtls_psa_crypto_free() and before any * subsequent call to psa_crypto_init(). * * This function is only intended for test purposes. The functionality * it provides is also useful for system integrators, but * system integrators should configure entropy drivers instead of * breaking through to the Mbed TLS API. * * \param entropy_init Function to initialize the entropy context * and set up the desired entropy sources. * It is called by psa_crypto_init(). * By default this is mbedtls_entropy_init(). * This function cannot report failures directly. * To indicate a failure, set the entropy context * to a state where mbedtls_entropy_func() will * return an error. * \param entropy_free Function to free the entropy context * and associated resources. * It is called by mbedtls_psa_crypto_free(). * By default this is mbedtls_entropy_free(). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_PERMITTED * The caller does not have the permission to configure * entropy sources. * \retval #PSA_ERROR_BAD_STATE * The library has already been initialized. */ psa_status_t mbedtls_psa_crypto_configure_entropy_sources( void (* entropy_init)(mbedtls_entropy_context *ctx), void (* entropy_free)(mbedtls_entropy_context *ctx)); #endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) psa_status_t psa_mac_key_can_do( psa_algorithm_t algorithm, psa_key_type_t key_type); psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len, uint8_t *input_copy, size_t input_copy_len); psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len, uint8_t *output, size_t output_len); /* * Test hooks to use for memory unpoisoning/poisoning in copy functions. */ extern void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len); extern void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len); extern void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len); extern void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len); #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */ #endif /* PSA_CRYPTO_INVASIVE_H */ webfakes/src/mbedtls/library/ssl_ciphersuites_internal.h0000644000176200001440000001151514740737024023376 0ustar liggesusers/** * \file ssl_ciphersuites_internal.h * * \brief Internal part of the public "ssl_ciphersuites.h". */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H #define MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H #include "mbedtls/pk.h" #if defined(MBEDTLS_PK_C) mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info); #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info); psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info); #endif /* MBEDTLS_PK_C */ int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info); int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) static inline int mbedtls_ssl_ciphersuite_has_pfs(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECJPAKE: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) static inline int mbedtls_ssl_ciphersuite_no_pfs(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_PSK: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_ecdh(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ static inline int mbedtls_ssl_ciphersuite_cert_req_allowed(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return 1; default: return 0; } } static inline int mbedtls_ssl_ciphersuite_uses_srv_cert(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return 1; default: return 0; } } #if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_dhe(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_ecdhe(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ #endif /* MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H */ webfakes/src/mbedtls/library/ecp.c0000644000176200001440000034612114740737024016660 0ustar liggesusers/* * Elliptic curves over GF(p): generic functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * SEC1 https://www.secg.org/sec1-v2.pdf * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf * RFC 4492 for the related TLS structures and constants * - https://www.rfc-editor.org/rfc/rfc4492 * RFC 7748 for the Curve448 and Curve25519 curve definitions * - https://www.rfc-editor.org/rfc/rfc7748 * * [Curve25519] https://cr.yp.to/ecdh/curve25519-20060209.pdf * * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis * for elliptic curve cryptosystems. In : Cryptographic Hardware and * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. * * * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to * render ECC resistant against Side Channel Attacks. IACR Cryptology * ePrint Archive, 2004, vol. 2004, p. 342. * */ #include "common.h" /** * \brief Function level alternative implementation. * * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to * replace certain functions in this module. The alternative implementations are * typically hardware accelerators and need to activate the hardware before the * computation starts and deactivate it after it finishes. The * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve * this purpose. * * To preserve the correct functionality the following conditions must hold: * * - The alternative implementation must be activated by * mbedtls_internal_ecp_init() before any of the replaceable functions is * called. * - mbedtls_internal_ecp_free() must \b only be called when the alternative * implementation is activated. * - mbedtls_internal_ecp_init() must \b not be called when the alternative * implementation is activated. * - Public functions must not return while the alternative implementation is * activated. * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) ) * \endcode ensures that the alternative implementation supports the current * group. */ #if defined(MBEDTLS_ECP_INTERNAL_ALT) #endif #if defined(MBEDTLS_ECP_LIGHT) #include "mbedtls/ecp.h" #include "mbedtls/threading.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "bn_mul.h" #include "ecp_invasive.h" #include #if !defined(MBEDTLS_ECP_ALT) #include "mbedtls/platform.h" #include "ecp_internal_alt.h" #if defined(MBEDTLS_SELF_TEST) /* * Counts of point addition and doubling, and field multiplications. * Used to test resistance of point multiplication to simple timing attacks. */ #if defined(MBEDTLS_ECP_C) static unsigned long add_count, dbl_count; #endif /* MBEDTLS_ECP_C */ static unsigned long mul_count; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Maximum number of "basic operations" to be done in a row. * * Default value 0 means that ECC operations will not yield. * Note that regardless of the value of ecp_max_ops, always at * least one step is performed before yielding. * * Setting ecp_max_ops=1 can be suitable for testing purposes * as it will interrupt computation at all possible points. */ static unsigned ecp_max_ops = 0; /* * Set ecp_max_ops */ void mbedtls_ecp_set_max_ops(unsigned max_ops) { ecp_max_ops = max_ops; } /* * Check if restart is enabled */ int mbedtls_ecp_restart_is_enabled(void) { return ecp_max_ops != 0; } /* * Restart sub-context for ecp_mul_comb() */ struct mbedtls_ecp_restart_mul { mbedtls_ecp_point R; /* current intermediate result */ size_t i; /* current index in various loops, 0 outside */ mbedtls_ecp_point *T; /* table for precomputed points */ unsigned char T_size; /* number of points in table T */ enum { /* what were we doing last time we returned? */ ecp_rsm_init = 0, /* nothing so far, dummy initial state */ ecp_rsm_pre_dbl, /* precompute 2^n multiples */ ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ ecp_rsm_pre_add, /* precompute remaining points by adding */ ecp_rsm_pre_norm_add, /* normalize all precomputed points */ ecp_rsm_comb_core, /* ecp_mul_comb_core() */ ecp_rsm_final_norm, /* do the final normalization */ } state; }; /* * Init restart_mul sub-context */ static void ecp_restart_rsm_init(mbedtls_ecp_restart_mul_ctx *ctx) { mbedtls_ecp_point_init(&ctx->R); ctx->i = 0; ctx->T = NULL; ctx->T_size = 0; ctx->state = ecp_rsm_init; } /* * Free the components of a restart_mul sub-context */ static void ecp_restart_rsm_free(mbedtls_ecp_restart_mul_ctx *ctx) { unsigned char i; if (ctx == NULL) { return; } mbedtls_ecp_point_free(&ctx->R); if (ctx->T != NULL) { for (i = 0; i < ctx->T_size; i++) { mbedtls_ecp_point_free(ctx->T + i); } mbedtls_free(ctx->T); } ecp_restart_rsm_init(ctx); } /* * Restart context for ecp_muladd() */ struct mbedtls_ecp_restart_muladd { mbedtls_ecp_point mP; /* mP value */ mbedtls_ecp_point R; /* R intermediate result */ enum { /* what should we do next? */ ecp_rsma_mul1 = 0, /* first multiplication */ ecp_rsma_mul2, /* second multiplication */ ecp_rsma_add, /* addition */ ecp_rsma_norm, /* normalization */ } state; }; /* * Init restart_muladd sub-context */ static void ecp_restart_ma_init(mbedtls_ecp_restart_muladd_ctx *ctx) { mbedtls_ecp_point_init(&ctx->mP); mbedtls_ecp_point_init(&ctx->R); ctx->state = ecp_rsma_mul1; } /* * Free the components of a restart_muladd sub-context */ static void ecp_restart_ma_free(mbedtls_ecp_restart_muladd_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_ecp_point_free(&ctx->mP); mbedtls_ecp_point_free(&ctx->R); ecp_restart_ma_init(ctx); } /* * Initialize a restart context */ void mbedtls_ecp_restart_init(mbedtls_ecp_restart_ctx *ctx) { ctx->ops_done = 0; ctx->depth = 0; ctx->rsm = NULL; ctx->ma = NULL; } /* * Free the components of a restart context */ void mbedtls_ecp_restart_free(mbedtls_ecp_restart_ctx *ctx) { if (ctx == NULL) { return; } ecp_restart_rsm_free(ctx->rsm); mbedtls_free(ctx->rsm); ecp_restart_ma_free(ctx->ma); mbedtls_free(ctx->ma); mbedtls_ecp_restart_init(ctx); } /* * Check if we can do the next step */ int mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx, unsigned ops) { if (rs_ctx != NULL && ecp_max_ops != 0) { /* scale depending on curve size: the chosen reference is 256-bit, * and multiplication is quadratic. Round to the closest integer. */ if (grp->pbits >= 512) { ops *= 4; } else if (grp->pbits >= 384) { ops *= 2; } /* Avoid infinite loops: always allow first step. * Because of that, however, it's not generally true * that ops_done <= ecp_max_ops, so the check * ops_done > ecp_max_ops below is mandatory. */ if ((rs_ctx->ops_done != 0) && (rs_ctx->ops_done > ecp_max_ops || ops > ecp_max_ops - rs_ctx->ops_done)) { return MBEDTLS_ERR_ECP_IN_PROGRESS; } /* update running count */ rs_ctx->ops_done += ops; } return 0; } /* Call this when entering a function that needs its own sub-context */ #define ECP_RS_ENTER(SUB) do { \ /* reset ops count for this call if top-level */ \ if (rs_ctx != NULL && rs_ctx->depth++ == 0) \ rs_ctx->ops_done = 0; \ \ /* set up our own sub-context if needed */ \ if (mbedtls_ecp_restart_is_enabled() && \ rs_ctx != NULL && rs_ctx->SUB == NULL) \ { \ rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB)); \ if (rs_ctx->SUB == NULL) \ return MBEDTLS_ERR_ECP_ALLOC_FAILED; \ \ ecp_restart_## SUB ##_init(rs_ctx->SUB); \ } \ } while (0) /* Call this when leaving a function that needs its own sub-context */ #define ECP_RS_LEAVE(SUB) do { \ /* clear our sub-context when not in progress (done or error) */ \ if (rs_ctx != NULL && rs_ctx->SUB != NULL && \ ret != MBEDTLS_ERR_ECP_IN_PROGRESS) \ { \ ecp_restart_## SUB ##_free(rs_ctx->SUB); \ mbedtls_free(rs_ctx->SUB); \ rs_ctx->SUB = NULL; \ } \ \ if (rs_ctx != NULL) \ rs_ctx->depth--; \ } while (0) #else /* MBEDTLS_ECP_RESTARTABLE */ #define ECP_RS_ENTER(sub) (void) rs_ctx; #define ECP_RS_LEAVE(sub) (void) rs_ctx; #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECP_C) static void mpi_init_many(mbedtls_mpi *arr, size_t size) { while (size--) { mbedtls_mpi_init(arr++); } } static void mpi_free_many(mbedtls_mpi *arr, size_t size) { while (size--) { mbedtls_mpi_free(arr++); } } #endif /* MBEDTLS_ECP_C */ /* * List of supported curves: * - internal ID * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2, RFC 8446 sec. 4.2.7) * - size in bits * - readable name * * Curves are listed in order: largest curves first, and for a given size, * fastest curves first. * * Reminder: update profiles in x509_crt.c and ssl_tls.c when adding a new curve! */ static const mbedtls_ecp_curve_info ecp_supported_curves[] = { #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, #endif #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, #endif #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, #endif #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) { MBEDTLS_ECP_DP_CURVE25519, 29, 256, "x25519" }, #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) { MBEDTLS_ECP_DP_CURVE448, 30, 448, "x448" }, #endif { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, }; #define ECP_NB_CURVES sizeof(ecp_supported_curves) / \ sizeof(ecp_supported_curves[0]) static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; /* * List of supported curves and associated info */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void) { return ecp_supported_curves; } /* * List of supported curves, group ID only */ const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void) { static int init_done = 0; if (!init_done) { size_t i = 0; const mbedtls_ecp_curve_info *curve_info; for (curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++) { ecp_supported_grp_id[i++] = curve_info->grp_id; } ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; init_done = 1; } return ecp_supported_grp_id; } /* * Get the curve info for the internal identifier */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id(mbedtls_ecp_group_id grp_id) { const mbedtls_ecp_curve_info *curve_info; for (curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++) { if (curve_info->grp_id == grp_id) { return curve_info; } } return NULL; } /* * Get the curve info from the TLS identifier */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id(uint16_t tls_id) { const mbedtls_ecp_curve_info *curve_info; for (curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++) { if (curve_info->tls_id == tls_id) { return curve_info; } } return NULL; } /* * Get the curve info from the name */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name(const char *name) { const mbedtls_ecp_curve_info *curve_info; if (name == NULL) { return NULL; } for (curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++) { if (strcmp(curve_info->name, name) == 0) { return curve_info; } } return NULL; } /* * Get the type of a curve */ mbedtls_ecp_curve_type mbedtls_ecp_get_type(const mbedtls_ecp_group *grp) { if (grp->G.X.p == NULL) { return MBEDTLS_ECP_TYPE_NONE; } if (grp->G.Y.p == NULL) { return MBEDTLS_ECP_TYPE_MONTGOMERY; } else { return MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS; } } /* * Initialize (the components of) a point */ void mbedtls_ecp_point_init(mbedtls_ecp_point *pt) { mbedtls_mpi_init(&pt->X); mbedtls_mpi_init(&pt->Y); mbedtls_mpi_init(&pt->Z); } /* * Initialize (the components of) a group */ void mbedtls_ecp_group_init(mbedtls_ecp_group *grp) { grp->id = MBEDTLS_ECP_DP_NONE; mbedtls_mpi_init(&grp->P); mbedtls_mpi_init(&grp->A); mbedtls_mpi_init(&grp->B); mbedtls_ecp_point_init(&grp->G); mbedtls_mpi_init(&grp->N); grp->pbits = 0; grp->nbits = 0; grp->h = 0; grp->modp = NULL; grp->t_pre = NULL; grp->t_post = NULL; grp->t_data = NULL; grp->T = NULL; grp->T_size = 0; } /* * Initialize (the components of) a key pair */ void mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key) { mbedtls_ecp_group_init(&key->grp); mbedtls_mpi_init(&key->d); mbedtls_ecp_point_init(&key->Q); } /* * Unallocate (the components of) a point */ void mbedtls_ecp_point_free(mbedtls_ecp_point *pt) { if (pt == NULL) { return; } mbedtls_mpi_free(&(pt->X)); mbedtls_mpi_free(&(pt->Y)); mbedtls_mpi_free(&(pt->Z)); } /* * Check that the comb table (grp->T) is static initialized. */ static int ecp_group_is_static_comb_table(const mbedtls_ecp_group *grp) { #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 return grp->T != NULL && grp->T_size == 0; #else (void) grp; return 0; #endif } /* * Unallocate (the components of) a group */ void mbedtls_ecp_group_free(mbedtls_ecp_group *grp) { size_t i; if (grp == NULL) { return; } if (grp->h != 1) { mbedtls_mpi_free(&grp->A); mbedtls_mpi_free(&grp->B); mbedtls_ecp_point_free(&grp->G); #if !defined(MBEDTLS_ECP_WITH_MPI_UINT) mbedtls_mpi_free(&grp->N); mbedtls_mpi_free(&grp->P); #endif } if (!ecp_group_is_static_comb_table(grp) && grp->T != NULL) { for (i = 0; i < grp->T_size; i++) { mbedtls_ecp_point_free(&grp->T[i]); } mbedtls_free(grp->T); } mbedtls_platform_zeroize(grp, sizeof(mbedtls_ecp_group)); } /* * Unallocate (the components of) a key pair */ void mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key) { if (key == NULL) { return; } mbedtls_ecp_group_free(&key->grp); mbedtls_mpi_free(&key->d); mbedtls_ecp_point_free(&key->Q); } /* * Copy the contents of a point */ int mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->X, &Q->X)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Y, &Q->Y)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Z, &Q->Z)); cleanup: return ret; } /* * Copy the contents of a group object */ int mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src) { return mbedtls_ecp_group_load(dst, src->id); } /* * Set point to zero */ int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->X, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Y, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 0)); cleanup: return ret; } /* * Tell if a point is zero */ int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt) { return mbedtls_mpi_cmp_int(&pt->Z, 0) == 0; } /* * Compare two points lazily */ int mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q) { if (mbedtls_mpi_cmp_mpi(&P->X, &Q->X) == 0 && mbedtls_mpi_cmp_mpi(&P->Y, &Q->Y) == 0 && mbedtls_mpi_cmp_mpi(&P->Z, &Q->Z) == 0) { return 0; } return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Import a non-zero point from ASCII strings */ int mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix, const char *x, const char *y) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->X, radix, x)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->Y, radix, y)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&P->Z, 1)); cleanup: return ret; } /* * Export a point into unsigned binary data (SEC1 2.3.3 and RFC7748) */ int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; size_t plen; if (format != MBEDTLS_ECP_PF_UNCOMPRESSED && format != MBEDTLS_ECP_PF_COMPRESSED) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } plen = mbedtls_mpi_size(&grp->P); #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) (void) format; /* Montgomery curves always use the same point format */ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { *olen = plen; if (buflen < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&P->X, buf, plen)); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { /* * Common case: P == 0 */ if (mbedtls_mpi_cmp_int(&P->Z, 0) == 0) { if (buflen < 1) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } buf[0] = 0x00; *olen = 1; return 0; } if (format == MBEDTLS_ECP_PF_UNCOMPRESSED) { *olen = 2 * plen + 1; if (buflen < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } buf[0] = 0x04; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->X, buf + 1, plen)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->Y, buf + 1 + plen, plen)); } else if (format == MBEDTLS_ECP_PF_COMPRESSED) { *olen = plen + 1; if (buflen < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } buf[0] = 0x02 + mbedtls_mpi_get_bit(&P->Y, 0); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->X, buf + 1, plen)); } } #endif cleanup: return ret; } #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp, const mbedtls_mpi *X, mbedtls_mpi *Y, int parity_bit); #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ /* * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748) */ int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, const unsigned char *buf, size_t ilen) { int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; size_t plen; if (ilen < 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } plen = mbedtls_mpi_size(&grp->P); #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { if (plen != ilen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&pt->X, buf, plen)); mbedtls_mpi_free(&pt->Y); if (grp->id == MBEDTLS_ECP_DP_CURVE25519) { /* Set most significant bit to 0 as prescribed in RFC7748 §5 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&pt->X, plen * 8 - 1, 0)); } MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1)); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { if (buf[0] == 0x00) { if (ilen == 1) { return mbedtls_ecp_set_zero(pt); } else { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } } if (ilen < 1 + plen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, buf + 1, plen)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1)); if (buf[0] == 0x04) { /* format == MBEDTLS_ECP_PF_UNCOMPRESSED */ if (ilen != 1 + plen * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return mbedtls_mpi_read_binary(&pt->Y, buf + 1 + plen, plen); } else if (buf[0] == 0x02 || buf[0] == 0x03) { /* format == MBEDTLS_ECP_PF_COMPRESSED */ if (ilen != 1 + plen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return mbedtls_ecp_sw_derive_y(grp, &pt->X, &pt->Y, (buf[0] & 1)); } else { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } } #endif cleanup: return ret; } /* * Import a point from a TLS ECPoint record (RFC 4492) * struct { * opaque point <1..2^8-1>; * } ECPoint; */ int mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, const unsigned char **buf, size_t buf_len) { unsigned char data_len; const unsigned char *buf_start; /* * We must have at least two bytes (1 for length, at least one for data) */ if (buf_len < 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } data_len = *(*buf)++; if (data_len < 1 || data_len > buf_len - 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Save buffer start for read_binary and update buf */ buf_start = *buf; *buf += data_len; return mbedtls_ecp_point_read_binary(grp, pt, buf_start, data_len); } /* * Export a point as a TLS ECPoint record (RFC 4492) * struct { * opaque point <1..2^8-1>; * } ECPoint; */ int mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, int format, size_t *olen, unsigned char *buf, size_t blen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (format != MBEDTLS_ECP_PF_UNCOMPRESSED && format != MBEDTLS_ECP_PF_COMPRESSED) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * buffer length must be at least one, for our length byte */ if (blen < 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } if ((ret = mbedtls_ecp_point_write_binary(grp, pt, format, olen, buf + 1, blen - 1)) != 0) { return ret; } /* * write length to the first byte and update total length */ buf[0] = (unsigned char) *olen; ++*olen; return 0; } /* * Set a group from an ECParameters record (RFC 4492) */ int mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp, const unsigned char **buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group_id grp_id; if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, len)) != 0) { return ret; } return mbedtls_ecp_group_load(grp, grp_id); } /* * Read a group id from an ECParameters record (RFC 4492) and convert it to * mbedtls_ecp_group_id. */ int mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp, const unsigned char **buf, size_t len) { uint16_t tls_id; const mbedtls_ecp_curve_info *curve_info; /* * We expect at least three bytes (see below) */ if (len < 3) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * First byte is curve_type; only named_curve is handled */ if (*(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Next two bytes are the namedcurve value */ tls_id = MBEDTLS_GET_UINT16_BE(*buf, 0); *buf += 2; if ((curve_info = mbedtls_ecp_curve_info_from_tls_id(tls_id)) == NULL) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } *grp = curve_info->grp_id; return 0; } /* * Write the ECParameters record corresponding to a group (RFC 4492) */ int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen) { const mbedtls_ecp_curve_info *curve_info; if ((curve_info = mbedtls_ecp_curve_info_from_grp_id(grp->id)) == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * We are going to write 3 bytes (see below) */ *olen = 3; if (blen < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } /* * First byte is curve_type, always named_curve */ *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; /* * Next two bytes are the namedcurve value */ MBEDTLS_PUT_UINT16_BE(curve_info->tls_id, buf, 0); return 0; } /* * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. * See the documentation of struct mbedtls_ecp_group. * * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. */ static int ecp_modp(mbedtls_mpi *N, const mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (grp->modp == NULL) { return mbedtls_mpi_mod_mpi(N, N, &grp->P); } /* N->s < 0 is a much faster test, which fails only if N is 0 */ if ((N->s < 0 && mbedtls_mpi_cmp_int(N, 0) != 0) || mbedtls_mpi_bitlen(N) > 2 * grp->pbits) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MBEDTLS_MPI_CHK(grp->modp(N)); /* N->s < 0 is a much faster test, which fails only if N is 0 */ while (N->s < 0 && mbedtls_mpi_cmp_int(N, 0) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &grp->P)); } while (mbedtls_mpi_cmp_mpi(N, &grp->P) >= 0) { /* we known P, N and the result are positive */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(N, N, &grp->P)); } cleanup: return ret; } /* * Fast mod-p functions expect their argument to be in the 0..p^2 range. * * In order to guarantee that, we need to ensure that operands of * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will * bring the result back to this range. * * The following macros are shortcuts for doing that. */ /* * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi */ #if defined(MBEDTLS_SELF_TEST) #define INC_MUL_COUNT mul_count++; #else #define INC_MUL_COUNT #endif #define MOD_MUL(N) \ do \ { \ MBEDTLS_MPI_CHK(ecp_modp(&(N), grp)); \ INC_MUL_COUNT \ } while (0) static inline int mbedtls_mpi_mul_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(X, A, B)); MOD_MUL(*X); cleanup: return ret; } /* * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi * N->s < 0 is a very fast test, which fails only if N is 0 */ #define MOD_SUB(N) \ do { \ while ((N)->s < 0 && mbedtls_mpi_cmp_int((N), 0) != 0) \ MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi((N), (N), &grp->P)); \ } while (0) MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_sub_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(X, A, B)); MOD_SUB(X); cleanup: return ret; } /* * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. * We known P, N and the result are positive, so sub_abs is correct, and * a bit faster. */ #define MOD_ADD(N) \ while (mbedtls_mpi_cmp_mpi((N), &grp->P) >= 0) \ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs((N), (N), &grp->P)) static inline int mbedtls_mpi_add_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, A, B)); MOD_ADD(X); cleanup: return ret; } MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_mul_int_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint c) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(X, A, c)); MOD_ADD(X); cleanup: return ret; } MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_sub_int_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint c) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(X, A, c)); MOD_SUB(X); cleanup: return ret; } #define MPI_ECP_SUB_INT(X, A, c) \ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int_mod(grp, X, A, c)) MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_shift_l_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, size_t count) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, count)); MOD_ADD(X); cleanup: return ret; } /* * Macro wrappers around ECP modular arithmetic * * Currently, these wrappers are defined via the bignum module. */ #define MPI_ECP_ADD(X, A, B) \ MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, X, A, B)) #define MPI_ECP_SUB(X, A, B) \ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, X, A, B)) #define MPI_ECP_MUL(X, A, B) \ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, B)) #define MPI_ECP_SQR(X, A) \ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, A)) #define MPI_ECP_MUL_INT(X, A, c) \ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int_mod(grp, X, A, c)) #define MPI_ECP_INV(dst, src) \ MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod((dst), (src), &grp->P)) #define MPI_ECP_MOV(X, A) \ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)) #define MPI_ECP_SHIFT_L(X, count) \ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, X, count)) #define MPI_ECP_LSET(X, c) \ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, c)) #define MPI_ECP_CMP_INT(X, c) \ mbedtls_mpi_cmp_int(X, c) #define MPI_ECP_CMP(X, Y) \ mbedtls_mpi_cmp_mpi(X, Y) /* Needs f_rng, p_rng to be defined. */ #define MPI_ECP_RAND(X) \ MBEDTLS_MPI_CHK(mbedtls_mpi_random((X), 2, &grp->P, f_rng, p_rng)) /* Conditional negation * Needs grp and a temporary MPI tmp to be defined. */ #define MPI_ECP_COND_NEG(X, cond) \ do \ { \ unsigned char nonzero = mbedtls_mpi_cmp_int((X), 0) != 0; \ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&tmp, &grp->P, (X))); \ MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), &tmp, \ nonzero & cond)); \ } while (0) #define MPI_ECP_NEG(X) MPI_ECP_COND_NEG((X), 1) #define MPI_ECP_VALID(X) \ ((X)->p != NULL) #define MPI_ECP_COND_ASSIGN(X, Y, cond) \ MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), (Y), (cond))) #define MPI_ECP_COND_SWAP(X, Y, cond) \ MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap((X), (Y), (cond))) #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * Computes the right-hand side of the Short Weierstrass equation * RHS = X^3 + A X + B */ static int ecp_sw_rhs(const mbedtls_ecp_group *grp, mbedtls_mpi *rhs, const mbedtls_mpi *X) { int ret; /* Compute X^3 + A X + B as X (X^2 + A) + B */ MPI_ECP_SQR(rhs, X); /* Special case for A = -3 */ if (mbedtls_ecp_group_a_is_minus_3(grp)) { MPI_ECP_SUB_INT(rhs, rhs, 3); } else { MPI_ECP_ADD(rhs, rhs, &grp->A); } MPI_ECP_MUL(rhs, rhs, X); MPI_ECP_ADD(rhs, rhs, &grp->B); cleanup: return ret; } /* * Derive Y from X and a parity bit */ static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp, const mbedtls_mpi *X, mbedtls_mpi *Y, int parity_bit) { /* w = y^2 = x^3 + ax + b * y = sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) * * Note: this method for extracting square root does not validate that w * was indeed a square so this function will return garbage in Y if X * does not correspond to a point on the curve. */ /* Check prerequisite p = 3 mod 4 */ if (mbedtls_mpi_get_bit(&grp->P, 0) != 1 || mbedtls_mpi_get_bit(&grp->P, 1) != 1) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } int ret; mbedtls_mpi exp; mbedtls_mpi_init(&exp); /* use Y to store intermediate result, actually w above */ MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, Y, X)); /* w = y^2 */ /* Y contains y^2 intermediate result */ /* exp = ((p+1)/4) */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&exp, &grp->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 2)); /* sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(Y, Y /*y^2*/, &exp, &grp->P, NULL)); /* check parity bit match or else invert Y */ /* This quick inversion implementation is valid because Y != 0 for all * Short Weierstrass curves supported by mbedtls, as each supported curve * has an order that is a large prime, so each supported curve does not * have any point of order 2, and a point with Y == 0 would be of order 2 */ if (mbedtls_mpi_get_bit(Y, 0) != parity_bit) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(Y, &grp->P, Y)); } cleanup: mbedtls_mpi_free(&exp); return ret; } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * For curves in short Weierstrass form, we do all the internal operations in * Jacobian coordinates. * * For multiplication, we'll use a comb method with countermeasures against * SPA, hence timing attacks. */ /* * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) * Cost: 1N := 1I + 3M + 1S */ static int ecp_normalize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt) { if (MPI_ECP_CMP_INT(&pt->Z, 0) == 0) { return 0; } #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_normalize_jac(grp, pt); } #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi T; mbedtls_mpi_init(&T); MPI_ECP_INV(&T, &pt->Z); /* T <- 1 / Z */ MPI_ECP_MUL(&pt->Y, &pt->Y, &T); /* Y' <- Y*T = Y / Z */ MPI_ECP_SQR(&T, &T); /* T <- T^2 = 1 / Z^2 */ MPI_ECP_MUL(&pt->X, &pt->X, &T); /* X <- X * T = X / Z^2 */ MPI_ECP_MUL(&pt->Y, &pt->Y, &T); /* Y'' <- Y' * T = Y / Z^3 */ MPI_ECP_LSET(&pt->Z, 1); cleanup: mbedtls_mpi_free(&T); return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) */ } /* * Normalize jacobian coordinates of an array of (pointers to) points, * using Montgomery's trick to perform only one inversion mod P. * (See for example Cohen's "A Course in Computational Algebraic Number * Theory", Algorithm 10.3.4.) * * Warning: fails (returning an error) if one of the points is zero! * This should never happen, see choice of w in ecp_mul_comb(). * * Cost: 1N(t) := 1I + (6t - 3)M + 1S */ static int ecp_normalize_jac_many(const mbedtls_ecp_group *grp, mbedtls_ecp_point *T[], size_t T_size) { if (T_size < 2) { return ecp_normalize_jac(grp, *T); } #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_normalize_jac_many(grp, T, T_size); } #endif #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_mpi *c, t; if ((c = mbedtls_calloc(T_size, sizeof(mbedtls_mpi))) == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } mbedtls_mpi_init(&t); mpi_init_many(c, T_size); /* * c[i] = Z_0 * ... * Z_i, i = 0,..,n := T_size-1 */ MPI_ECP_MOV(&c[0], &T[0]->Z); for (i = 1; i < T_size; i++) { MPI_ECP_MUL(&c[i], &c[i-1], &T[i]->Z); } /* * c[n] = 1 / (Z_0 * ... * Z_n) mod P */ MPI_ECP_INV(&c[T_size-1], &c[T_size-1]); for (i = T_size - 1;; i--) { /* At the start of iteration i (note that i decrements), we have * - c[j] = Z_0 * .... * Z_j for j < i, * - c[j] = 1 / (Z_0 * .... * Z_j) for j == i, * * This is maintained via * - c[i-1] <- c[i] * Z_i * * We also derive 1/Z_i = c[i] * c[i-1] for i>0 and use that * to do the actual normalization. For i==0, we already have * c[0] = 1 / Z_0. */ if (i > 0) { /* Compute 1/Z_i and establish invariant for the next iteration. */ MPI_ECP_MUL(&t, &c[i], &c[i-1]); MPI_ECP_MUL(&c[i-1], &c[i], &T[i]->Z); } else { MPI_ECP_MOV(&t, &c[0]); } /* Now t holds 1 / Z_i; normalize as in ecp_normalize_jac() */ MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t); MPI_ECP_SQR(&t, &t); MPI_ECP_MUL(&T[i]->X, &T[i]->X, &t); MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t); /* * Post-precessing: reclaim some memory by shrinking coordinates * - not storing Z (always 1) * - shrinking other coordinates, but still keeping the same number of * limbs as P, as otherwise it will too likely be regrown too fast. */ MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->X, grp->P.n)); MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->Y, grp->P.n)); MPI_ECP_LSET(&T[i]->Z, 1); if (i == 0) { break; } } cleanup: mbedtls_mpi_free(&t); mpi_free_many(c, T_size); mbedtls_free(c); return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) */ } /* * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid */ static int ecp_safe_invert_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *Q, unsigned char inv) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi tmp; mbedtls_mpi_init(&tmp); MPI_ECP_COND_NEG(&Q->Y, inv); cleanup: mbedtls_mpi_free(&tmp); return ret; } /* * Point doubling R = 2 P, Jacobian coordinates * * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . * * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. * * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. * * Cost: 1D := 3M + 4S (A == 0) * 4M + 4S (A == -3) * 3M + 6S + 1a otherwise */ static int ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P, mbedtls_mpi tmp[4]) { #if defined(MBEDTLS_SELF_TEST) dbl_count++; #endif #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_double_jac(grp, R, P); } #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Special case for A = -3 */ if (mbedtls_ecp_group_a_is_minus_3(grp)) { /* tmp[0] <- M = 3(X + Z^2)(X - Z^2) */ MPI_ECP_SQR(&tmp[1], &P->Z); MPI_ECP_ADD(&tmp[2], &P->X, &tmp[1]); MPI_ECP_SUB(&tmp[3], &P->X, &tmp[1]); MPI_ECP_MUL(&tmp[1], &tmp[2], &tmp[3]); MPI_ECP_MUL_INT(&tmp[0], &tmp[1], 3); } else { /* tmp[0] <- M = 3.X^2 + A.Z^4 */ MPI_ECP_SQR(&tmp[1], &P->X); MPI_ECP_MUL_INT(&tmp[0], &tmp[1], 3); /* Optimize away for "koblitz" curves with A = 0 */ if (MPI_ECP_CMP_INT(&grp->A, 0) != 0) { /* M += A.Z^4 */ MPI_ECP_SQR(&tmp[1], &P->Z); MPI_ECP_SQR(&tmp[2], &tmp[1]); MPI_ECP_MUL(&tmp[1], &tmp[2], &grp->A); MPI_ECP_ADD(&tmp[0], &tmp[0], &tmp[1]); } } /* tmp[1] <- S = 4.X.Y^2 */ MPI_ECP_SQR(&tmp[2], &P->Y); MPI_ECP_SHIFT_L(&tmp[2], 1); MPI_ECP_MUL(&tmp[1], &P->X, &tmp[2]); MPI_ECP_SHIFT_L(&tmp[1], 1); /* tmp[3] <- U = 8.Y^4 */ MPI_ECP_SQR(&tmp[3], &tmp[2]); MPI_ECP_SHIFT_L(&tmp[3], 1); /* tmp[2] <- T = M^2 - 2.S */ MPI_ECP_SQR(&tmp[2], &tmp[0]); MPI_ECP_SUB(&tmp[2], &tmp[2], &tmp[1]); MPI_ECP_SUB(&tmp[2], &tmp[2], &tmp[1]); /* tmp[1] <- S = M(S - T) - U */ MPI_ECP_SUB(&tmp[1], &tmp[1], &tmp[2]); MPI_ECP_MUL(&tmp[1], &tmp[1], &tmp[0]); MPI_ECP_SUB(&tmp[1], &tmp[1], &tmp[3]); /* tmp[3] <- U = 2.Y.Z */ MPI_ECP_MUL(&tmp[3], &P->Y, &P->Z); MPI_ECP_SHIFT_L(&tmp[3], 1); /* Store results */ MPI_ECP_MOV(&R->X, &tmp[2]); MPI_ECP_MOV(&R->Y, &tmp[1]); MPI_ECP_MOV(&R->Z, &tmp[3]); cleanup: return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) */ } /* * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) * * The coordinates of Q must be normalized (= affine), * but those of P don't need to. R is not normalized. * * P,Q,R may alias, but only at the level of EC points: they must be either * equal as pointers, or disjoint (including the coordinate data buffers). * Fine-grained aliasing at the level of coordinates is not supported. * * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. * None of these cases can happen as intermediate step in ecp_mul_comb(): * - at each step, P, Q and R are multiples of the base point, the factor * being less than its order, so none of them is zero; * - Q is an odd multiple of the base point, P an even multiple, * due to the choice of precomputed points in the modified comb method. * So branches for these cases do not leak secret information. * * Cost: 1A := 8M + 3S */ static int ecp_add_mixed(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, mbedtls_mpi tmp[4]) { #if defined(MBEDTLS_SELF_TEST) add_count++; #endif #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_add_mixed(grp, R, P, Q); } #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_ADD_MIXED_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* NOTE: Aliasing between input and output is allowed, so one has to make * sure that at the point X,Y,Z are written, {P,Q}->{X,Y,Z} are no * longer read from. */ mbedtls_mpi * const X = &R->X; mbedtls_mpi * const Y = &R->Y; mbedtls_mpi * const Z = &R->Z; if (!MPI_ECP_VALID(&Q->Z)) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Trivial cases: P == 0 or Q == 0 (case 1) */ if (MPI_ECP_CMP_INT(&P->Z, 0) == 0) { return mbedtls_ecp_copy(R, Q); } if (MPI_ECP_CMP_INT(&Q->Z, 0) == 0) { return mbedtls_ecp_copy(R, P); } /* * Make sure Q coordinates are normalized */ if (MPI_ECP_CMP_INT(&Q->Z, 1) != 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MPI_ECP_SQR(&tmp[0], &P->Z); MPI_ECP_MUL(&tmp[1], &tmp[0], &P->Z); MPI_ECP_MUL(&tmp[0], &tmp[0], &Q->X); MPI_ECP_MUL(&tmp[1], &tmp[1], &Q->Y); MPI_ECP_SUB(&tmp[0], &tmp[0], &P->X); MPI_ECP_SUB(&tmp[1], &tmp[1], &P->Y); /* Special cases (2) and (3) */ if (MPI_ECP_CMP_INT(&tmp[0], 0) == 0) { if (MPI_ECP_CMP_INT(&tmp[1], 0) == 0) { ret = ecp_double_jac(grp, R, P, tmp); goto cleanup; } else { ret = mbedtls_ecp_set_zero(R); goto cleanup; } } /* {P,Q}->Z no longer used, so OK to write to Z even if there's aliasing. */ MPI_ECP_MUL(Z, &P->Z, &tmp[0]); MPI_ECP_SQR(&tmp[2], &tmp[0]); MPI_ECP_MUL(&tmp[3], &tmp[2], &tmp[0]); MPI_ECP_MUL(&tmp[2], &tmp[2], &P->X); MPI_ECP_MOV(&tmp[0], &tmp[2]); MPI_ECP_SHIFT_L(&tmp[0], 1); /* {P,Q}->X no longer used, so OK to write to X even if there's aliasing. */ MPI_ECP_SQR(X, &tmp[1]); MPI_ECP_SUB(X, X, &tmp[0]); MPI_ECP_SUB(X, X, &tmp[3]); MPI_ECP_SUB(&tmp[2], &tmp[2], X); MPI_ECP_MUL(&tmp[2], &tmp[2], &tmp[1]); MPI_ECP_MUL(&tmp[3], &tmp[3], &P->Y); /* {P,Q}->Y no longer used, so OK to write to Y even if there's aliasing. */ MPI_ECP_SUB(Y, &tmp[2], &tmp[3]); cleanup: return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_ADD_MIXED_ALT) */ } /* * Randomize jacobian coordinates: * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l * This is sort of the reverse operation of ecp_normalize_jac(). * * This countermeasure was first suggested in [2]. */ static int ecp_randomize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_randomize_jac(grp, pt, f_rng, p_rng); } #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi l; mbedtls_mpi_init(&l); /* Generate l such that 1 < l < p */ MPI_ECP_RAND(&l); /* Z' = l * Z */ MPI_ECP_MUL(&pt->Z, &pt->Z, &l); /* Y' = l * Y */ MPI_ECP_MUL(&pt->Y, &pt->Y, &l); /* X' = l^2 * X */ MPI_ECP_SQR(&l, &l); MPI_ECP_MUL(&pt->X, &pt->X, &l); /* Y'' = l^2 * Y' = l^3 * Y */ MPI_ECP_MUL(&pt->Y, &pt->Y, &l); cleanup: mbedtls_mpi_free(&l); if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; } return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) */ } /* * Check and define parameters used by the comb method (see below for details) */ #if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 #error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" #endif /* d = ceil( n / w ) */ #define COMB_MAX_D (MBEDTLS_ECP_MAX_BITS + 1) / 2 /* number of precomputed points */ #define COMB_MAX_PRE (1 << (MBEDTLS_ECP_WINDOW_SIZE - 1)) /* * Compute the representation of m that will be used with our comb method. * * The basic comb method is described in GECC 3.44 for example. We use a * modified version that provides resistance to SPA by avoiding zero * digits in the representation as in [3]. We modify the method further by * requiring that all K_i be odd, which has the small cost that our * representation uses one more K_i, due to carries, but saves on the size of * the precomputed table. * * Summary of the comb method and its modifications: * * - The goal is to compute m*P for some w*d-bit integer m. * * - The basic comb method splits m into the w-bit integers * x[0] .. x[d-1] where x[i] consists of the bits in m whose * index has residue i modulo d, and computes m * P as * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. * * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., * thereby successively converting it into a form where all summands * are nonzero, at the cost of negative summands. This is the basic idea of [3]. * * - More generally, even if x[i+1] != 0, we can first transform the sum as * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. * Performing and iterating this procedure for those x[i] that are even * (keeping track of carry), we can transform the original sum into one of the form * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] * with all x'[i] odd. It is therefore only necessary to know S at odd indices, * which is why we are only computing half of it in the first place in * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. * * - For the sake of compactness, only the seven low-order bits of x[i] * are used to represent its absolute value (K_i in the paper), and the msb * of x[i] encodes the sign (s_i in the paper): it is set if and only if * if s_i == -1; * * Calling conventions: * - x is an array of size d + 1 * - w is the size, ie number of teeth, of the comb, and must be between * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d * (the result will be incorrect if these assumptions are not satisfied) */ static void ecp_comb_recode_core(unsigned char x[], size_t d, unsigned char w, const mbedtls_mpi *m) { size_t i, j; unsigned char c, cc, adjust; memset(x, 0, d+1); /* First get the classical comb values (except for x_d = 0) */ for (i = 0; i < d; i++) { for (j = 0; j < w; j++) { x[i] |= mbedtls_mpi_get_bit(m, i + d * j) << j; } } /* Now make sure x_1 .. x_d are odd */ c = 0; for (i = 1; i <= d; i++) { /* Add carry and update it */ cc = x[i] & c; x[i] = x[i] ^ c; c = cc; /* Adjust if needed, avoiding branches */ adjust = 1 - (x[i] & 0x01); c |= x[i] & (x[i-1] * adjust); x[i] = x[i] ^ (x[i-1] * adjust); x[i-1] |= adjust << 7; } } /* * Precompute points for the adapted comb method * * Assumption: T must be able to hold 2^{w - 1} elements. * * Operation: If i = i_{w-1} ... i_1 is the binary representation of i, * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. * * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) * * Note: Even comb values (those where P would be omitted from the * sum defining T[i] above) are not needed in our adaption * the comb method. See ecp_comb_recode_core(). * * This function currently works in four steps: * (1) [dbl] Computation of intermediate T[i] for 2-power values of i * (2) [norm_dbl] Normalization of coordinates of these T[i] * (3) [add] Computation of all T[i] * (4) [norm_add] Normalization of all T[i] * * Step 1 can be interrupted but not the others; together with the final * coordinate normalization they are the largest steps done at once, depending * on the window size. Here are operation counts for P-256: * * step (2) (3) (4) * w = 5 142 165 208 * w = 4 136 77 160 * w = 3 130 33 136 * w = 2 124 11 124 * * So if ECC operations are blocking for too long even with a low max_ops * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order * to minimize maximum blocking time. */ static int ecp_precompute_comb(const mbedtls_ecp_group *grp, mbedtls_ecp_point T[], const mbedtls_ecp_point *P, unsigned char w, size_t d, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char i; size_t j = 0; const unsigned char T_size = 1U << (w - 1); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1] = { NULL }; mbedtls_mpi tmp[4]; mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { if (rs_ctx->rsm->state == ecp_rsm_pre_dbl) { goto dbl; } if (rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl) { goto norm_dbl; } if (rs_ctx->rsm->state == ecp_rsm_pre_add) { goto add; } if (rs_ctx->rsm->state == ecp_rsm_pre_norm_add) { goto norm_add; } } #else (void) rs_ctx; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_pre_dbl; /* initial state for the loop */ rs_ctx->rsm->i = 0; } dbl: #endif /* * Set T[0] = P and * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) */ MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&T[0], P)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0) { j = rs_ctx->rsm->i; } else #endif j = 0; for (; j < d * (w - 1); j++) { MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_DBL); i = 1U << (j / d); cur = T + i; if (j % d == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_copy(cur, T + (i >> 1))); } MBEDTLS_MPI_CHK(ecp_double_jac(grp, cur, cur, tmp)); } #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; } norm_dbl: #endif /* * Normalize current elements in T to allow them to be used in * ecp_add_mixed() below, which requires one normalized input. * * As T has holes, use an auxiliary array of pointers to elements in T. * */ j = 0; for (i = 1; i < T_size; i <<= 1) { TT[j++] = T + i; } MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV + 6 * j - 2); MBEDTLS_MPI_CHK(ecp_normalize_jac_many(grp, TT, j)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_pre_add; } add: #endif /* * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ MBEDTLS_ECP_BUDGET((T_size - 1) * MBEDTLS_ECP_OPS_ADD); for (i = 1; i < T_size; i <<= 1) { j = i; while (j--) { MBEDTLS_MPI_CHK(ecp_add_mixed(grp, &T[i + j], &T[j], &T[i], tmp)); } } #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_pre_norm_add; } norm_add: #endif /* * Normalize final elements in T. Even though there are no holes now, we * still need the auxiliary array for homogeneity with the previous * call. Also, skip T[0] which is already normalised, being a copy of P. */ for (j = 0; j + 1 < T_size; j++) { TT[j] = T + j + 1; } MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV + 6 * j - 2); MBEDTLS_MPI_CHK(ecp_normalize_jac_many(grp, TT, j)); /* Free Z coordinate (=1 after normalization) to save RAM. * This makes T[i] invalid as mbedtls_ecp_points, but this is OK * since from this point onwards, they are only accessed indirectly * via the getter function ecp_select_comb() which does set the * target's Z coordinate to 1. */ for (i = 0; i < T_size; i++) { mbedtls_mpi_free(&T[i].Z); } cleanup: mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { if (rs_ctx->rsm->state == ecp_rsm_pre_dbl) { rs_ctx->rsm->i = j; } } #endif return ret; } /* * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] * * See ecp_comb_recode_core() for background */ static int ecp_select_comb(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point T[], unsigned char T_size, unsigned char i) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char ii, j; /* Ignore the "sign" bit and scale down */ ii = (i & 0x7Fu) >> 1; /* Read the whole table to thwart cache-based timing attacks */ for (j = 0; j < T_size; j++) { MPI_ECP_COND_ASSIGN(&R->X, &T[j].X, j == ii); MPI_ECP_COND_ASSIGN(&R->Y, &T[j].Y, j == ii); } /* Safely invert result if i is "negative" */ MBEDTLS_MPI_CHK(ecp_safe_invert_jac(grp, R, i >> 7)); MPI_ECP_LSET(&R->Z, 1); cleanup: return ret; } /* * Core multiplication algorithm for the (modified) comb method. * This part is actually common with the basic comb method (GECC 3.44) * * Cost: d A + d D + 1 R */ static int ecp_mul_comb_core(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point T[], unsigned char T_size, const unsigned char x[], size_t d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point Txi; mbedtls_mpi tmp[4]; size_t i; mbedtls_ecp_point_init(&Txi); mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if !defined(MBEDTLS_ECP_RESTARTABLE) (void) rs_ctx; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->state != ecp_rsm_comb_core) { rs_ctx->rsm->i = 0; rs_ctx->rsm->state = ecp_rsm_comb_core; } /* new 'if' instead of nested for the sake of the 'else' branch */ if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0) { /* restore current index (R already pointing to rs_ctx->rsm->R) */ i = rs_ctx->rsm->i; } else #endif { /* Start with a non-zero point and randomize its coordinates */ i = d; MBEDTLS_MPI_CHK(ecp_select_comb(grp, R, T, T_size, x[i])); if (f_rng != 0) { MBEDTLS_MPI_CHK(ecp_randomize_jac(grp, R, f_rng, p_rng)); } } while (i != 0) { MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD); --i; MBEDTLS_MPI_CHK(ecp_double_jac(grp, R, R, tmp)); MBEDTLS_MPI_CHK(ecp_select_comb(grp, &Txi, T, T_size, x[i])); MBEDTLS_MPI_CHK(ecp_add_mixed(grp, R, R, &Txi, tmp)); } cleanup: mbedtls_ecp_point_free(&Txi); mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { rs_ctx->rsm->i = i; /* no need to save R, already pointing to rs_ctx->rsm->R */ } #endif return ret; } /* * Recode the scalar to get constant-time comb multiplication * * As the actual scalar recoding needs an odd scalar as a starting point, * this wrapper ensures that by replacing m by N - m if necessary, and * informs the caller that the result of multiplication will be negated. * * This works because we only support large prime order for Short Weierstrass * curves, so N is always odd hence either m or N - m is. * * See ecp_comb_recode_core() for background. */ static int ecp_comb_recode_scalar(const mbedtls_ecp_group *grp, const mbedtls_mpi *m, unsigned char k[COMB_MAX_D + 1], size_t d, unsigned char w, unsigned char *parity_trick) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi M, mm; mbedtls_mpi_init(&M); mbedtls_mpi_init(&mm); /* N is always odd (see above), just make extra sure */ if (mbedtls_mpi_get_bit(&grp->N, 0) != 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* do we need the parity trick? */ *parity_trick = (mbedtls_mpi_get_bit(m, 0) == 0); /* execute parity fix in constant time */ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&M, m)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&mm, &grp->N, m)); MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(&M, &mm, *parity_trick)); /* actual scalar recoding */ ecp_comb_recode_core(k, d, w, &M); cleanup: mbedtls_mpi_free(&mm); mbedtls_mpi_free(&M); return ret; } /* * Perform comb multiplication (for short Weierstrass curves) * once the auxiliary table has been pre-computed. * * Scalar recoding may use a parity trick that makes us compute -m * P, * if that is the case we'll need to recover m * P at the end. */ static int ecp_mul_comb_after_precomp(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *T, unsigned char T_size, unsigned char w, size_t d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char parity_trick; unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *RR = R; #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { RR = &rs_ctx->rsm->R; if (rs_ctx->rsm->state == ecp_rsm_final_norm) { goto final_norm; } } #endif MBEDTLS_MPI_CHK(ecp_comb_recode_scalar(grp, m, k, d, w, &parity_trick)); MBEDTLS_MPI_CHK(ecp_mul_comb_core(grp, RR, T, T_size, k, d, f_rng, p_rng, rs_ctx)); MBEDTLS_MPI_CHK(ecp_safe_invert_jac(grp, RR, parity_trick)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_final_norm; } final_norm: MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV); #endif /* * Knowledge of the jacobian coordinates may leak the last few bits of the * scalar [1], and since our MPI implementation isn't constant-flow, * inversion (used for coordinate normalization) may leak the full value * of its input via side-channels [2]. * * [1] https://eprint.iacr.org/2003/191 * [2] https://eprint.iacr.org/2020/055 * * Avoid the leak by randomizing coordinates before we normalize them. */ if (f_rng != 0) { MBEDTLS_MPI_CHK(ecp_randomize_jac(grp, RR, f_rng, p_rng)); } MBEDTLS_MPI_CHK(ecp_normalize_jac(grp, RR)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, RR)); } #endif cleanup: return ret; } /* * Pick window size based on curve size and whether we optimize for base point */ static unsigned char ecp_pick_window_size(const mbedtls_ecp_group *grp, unsigned char p_eq_g) { unsigned char w; /* * Minimize the number of multiplications, that is minimize * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) * (see costs of the various parts, with 1S = 1M) */ w = grp->nbits >= 384 ? 5 : 4; /* * If P == G, pre-compute a bit more, since this may be re-used later. * Just adding one avoids upping the cost of the first mul too much, * and the memory cost too. */ if (p_eq_g) { w++; } /* * If static comb table may not be used (!p_eq_g) or static comb table does * not exists, make sure w is within bounds. * (The last test is useful only for very small curves in the test suite.) * * The user reduces MBEDTLS_ECP_WINDOW_SIZE does not changes the size of * static comb table, because the size of static comb table is fixed when * it is generated. */ #if (MBEDTLS_ECP_WINDOW_SIZE < 6) if ((!p_eq_g || !ecp_group_is_static_comb_table(grp)) && w > MBEDTLS_ECP_WINDOW_SIZE) { w = MBEDTLS_ECP_WINDOW_SIZE; } #endif if (w >= grp->nbits) { w = 2; } return w; } /* * Multiplication using the comb method - for curves in short Weierstrass form * * This function is mainly responsible for administrative work: * - managing the restart context if enabled * - managing the table of precomputed points (passed between the below two * functions): allocation, computation, ownership transfer, freeing. * * It delegates the actual arithmetic work to: * ecp_precompute_comb() and ecp_mul_comb_with_precomp() * * See comments on ecp_comb_recode_core() regarding the computation strategy. */ static int ecp_mul_comb(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char w, p_eq_g, i; size_t d; unsigned char T_size = 0, T_ok = 0; mbedtls_ecp_point *T = NULL; ECP_RS_ENTER(rsm); /* Is P the base point ? */ #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 p_eq_g = (MPI_ECP_CMP(&P->Y, &grp->G.Y) == 0 && MPI_ECP_CMP(&P->X, &grp->G.X) == 0); #else p_eq_g = 0; #endif /* Pick window size and deduce related sizes */ w = ecp_pick_window_size(grp, p_eq_g); T_size = 1U << (w - 1); d = (grp->nbits + w - 1) / w; /* Pre-computed table: do we have it already for the base point? */ if (p_eq_g && grp->T != NULL) { /* second pointer to the same table, will be deleted on exit */ T = grp->T; T_ok = 1; } else #if defined(MBEDTLS_ECP_RESTARTABLE) /* Pre-computed table: do we have one in progress? complete? */ if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL) { /* transfer ownership of T from rsm to local function */ T = rs_ctx->rsm->T; rs_ctx->rsm->T = NULL; rs_ctx->rsm->T_size = 0; /* This effectively jumps to the call to mul_comb_after_precomp() */ T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; } else #endif /* Allocate table if we didn't have any */ { T = mbedtls_calloc(T_size, sizeof(mbedtls_ecp_point)); if (T == NULL) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } for (i = 0; i < T_size; i++) { mbedtls_ecp_point_init(&T[i]); } T_ok = 0; } /* Compute table (or finish computing it) if not done already */ if (!T_ok) { MBEDTLS_MPI_CHK(ecp_precompute_comb(grp, T, P, w, d, rs_ctx)); if (p_eq_g) { /* almost transfer ownership of T to the group, but keep a copy of * the pointer to use for calling the next function more easily */ grp->T = T; grp->T_size = T_size; } } /* Actual comb multiplication using precomputed points */ MBEDTLS_MPI_CHK(ecp_mul_comb_after_precomp(grp, R, m, T, T_size, w, d, f_rng, p_rng, rs_ctx)); cleanup: /* does T belong to the group? */ if (T == grp->T) { T = NULL; } /* does T belong to the restart context? */ #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL) { /* transfer ownership of T from local function to rsm */ rs_ctx->rsm->T_size = T_size; rs_ctx->rsm->T = T; T = NULL; } #endif /* did T belong to us? then let's destroy it! */ if (T != NULL) { for (i = 0; i < T_size; i++) { mbedtls_ecp_point_free(&T[i]); } mbedtls_free(T); } /* prevent caller from using invalid value */ int should_free_R = (ret != 0); #if defined(MBEDTLS_ECP_RESTARTABLE) /* don't free R while in progress in case R == P */ if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { should_free_R = 0; } #endif if (should_free_R) { mbedtls_ecp_point_free(R); } ECP_RS_LEAVE(rsm); return ret; } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) /* * For Montgomery curves, we do all the internal arithmetic in projective * coordinates. Import/export of points uses only the x coordinates, which is * internally represented as X / Z. * * For scalar multiplication, we'll use a Montgomery ladder. */ /* * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 * Cost: 1M + 1I */ static int ecp_normalize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P) { #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_normalize_mxz(grp, P); } #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MPI_ECP_INV(&P->Z, &P->Z); MPI_ECP_MUL(&P->X, &P->X, &P->Z); MPI_ECP_LSET(&P->Z, 1); cleanup: return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) */ } /* * Randomize projective x/z coordinates: * (X, Z) -> (l X, l Z) for random l * This is sort of the reverse operation of ecp_normalize_mxz(). * * This countermeasure was first suggested in [2]. * Cost: 2M */ static int ecp_randomize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_randomize_mxz(grp, P, f_rng, p_rng); } #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi l; mbedtls_mpi_init(&l); /* Generate l such that 1 < l < p */ MPI_ECP_RAND(&l); MPI_ECP_MUL(&P->X, &P->X, &l); MPI_ECP_MUL(&P->Z, &P->Z, &l); cleanup: mbedtls_mpi_free(&l); if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; } return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) */ } /* * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), * for Montgomery curves in x/z coordinates. * * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 * with * d = X1 * P = (X2, Z2) * Q = (X3, Z3) * R = (X4, Z4) * S = (X5, Z5) * and eliminating temporary variables tO, ..., t4. * * Cost: 5M + 4S */ static int ecp_double_add_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, mbedtls_mpi T[4]) { #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_double_add_mxz(grp, R, S, P, Q, d); } #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MPI_ECP_ADD(&T[0], &P->X, &P->Z); /* Pp := PX + PZ */ MPI_ECP_SUB(&T[1], &P->X, &P->Z); /* Pm := PX - PZ */ MPI_ECP_ADD(&T[2], &Q->X, &Q->Z); /* Qp := QX + XZ */ MPI_ECP_SUB(&T[3], &Q->X, &Q->Z); /* Qm := QX - QZ */ MPI_ECP_MUL(&T[3], &T[3], &T[0]); /* Qm * Pp */ MPI_ECP_MUL(&T[2], &T[2], &T[1]); /* Qp * Pm */ MPI_ECP_SQR(&T[0], &T[0]); /* Pp^2 */ MPI_ECP_SQR(&T[1], &T[1]); /* Pm^2 */ MPI_ECP_MUL(&R->X, &T[0], &T[1]); /* Pp^2 * Pm^2 */ MPI_ECP_SUB(&T[0], &T[0], &T[1]); /* Pp^2 - Pm^2 */ MPI_ECP_MUL(&R->Z, &grp->A, &T[0]); /* A * (Pp^2 - Pm^2) */ MPI_ECP_ADD(&R->Z, &T[1], &R->Z); /* [ A * (Pp^2-Pm^2) ] + Pm^2 */ MPI_ECP_ADD(&S->X, &T[3], &T[2]); /* Qm*Pp + Qp*Pm */ MPI_ECP_SQR(&S->X, &S->X); /* (Qm*Pp + Qp*Pm)^2 */ MPI_ECP_SUB(&S->Z, &T[3], &T[2]); /* Qm*Pp - Qp*Pm */ MPI_ECP_SQR(&S->Z, &S->Z); /* (Qm*Pp - Qp*Pm)^2 */ MPI_ECP_MUL(&S->Z, d, &S->Z); /* d * ( Qm*Pp - Qp*Pm )^2 */ MPI_ECP_MUL(&R->Z, &T[0], &R->Z); /* [A*(Pp^2-Pm^2)+Pm^2]*(Pp^2-Pm^2) */ cleanup: return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) */ } /* * Multiplication with Montgomery ladder in x/z coordinates, * for curves in Montgomery form */ static int ecp_mul_mxz(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; unsigned char b; mbedtls_ecp_point RP; mbedtls_mpi PX; mbedtls_mpi tmp[4]; mbedtls_ecp_point_init(&RP); mbedtls_mpi_init(&PX); mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); if (f_rng == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Save PX and read from P before writing to R, in case P == R */ MPI_ECP_MOV(&PX, &P->X); MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&RP, P)); /* Set R to zero in modified x/z coordinates */ MPI_ECP_LSET(&R->X, 1); MPI_ECP_LSET(&R->Z, 0); mbedtls_mpi_free(&R->Y); /* RP.X might be slightly larger than P, so reduce it */ MOD_ADD(&RP.X); /* Randomize coordinates of the starting point */ MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, &RP, f_rng, p_rng)); /* Loop invariant: R = result so far, RP = R + P */ i = grp->nbits + 1; /* one past the (zero-based) required msb for private keys */ while (i-- > 0) { b = mbedtls_mpi_get_bit(m, i); /* * if (b) R = 2R + P else R = 2R, * which is: * if (b) double_add( RP, R, RP, R ) * else double_add( R, RP, R, RP ) * but using safe conditional swaps to avoid leaks */ MPI_ECP_COND_SWAP(&R->X, &RP.X, b); MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b); MBEDTLS_MPI_CHK(ecp_double_add_mxz(grp, R, &RP, R, &RP, &PX, tmp)); MPI_ECP_COND_SWAP(&R->X, &RP.X, b); MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b); } /* * Knowledge of the projective coordinates may leak the last few bits of the * scalar [1], and since our MPI implementation isn't constant-flow, * inversion (used for coordinate normalization) may leak the full value * of its input via side-channels [2]. * * [1] https://eprint.iacr.org/2003/191 * [2] https://eprint.iacr.org/2020/055 * * Avoid the leak by randomizing coordinates before we normalize them. */ MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, R, f_rng, p_rng)); MBEDTLS_MPI_CHK(ecp_normalize_mxz(grp, R)); cleanup: mbedtls_ecp_point_free(&RP); mbedtls_mpi_free(&PX); mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); return ret; } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ /* * Restartable multiplication R = m * P * * This internal function can be called without an RNG in case where we know * the inputs are not sensitive. */ static int ecp_mul_restartable_internal(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(MBEDTLS_ECP_INTERNAL_ALT) char is_grp_capable = 0; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) /* reset ops count for this call if top-level */ if (rs_ctx != NULL && rs_ctx->depth++ == 0) { rs_ctx->ops_done = 0; } #else (void) rs_ctx; #endif #if defined(MBEDTLS_ECP_INTERNAL_ALT) if ((is_grp_capable = mbedtls_internal_ecp_grp_capable(grp))) { MBEDTLS_MPI_CHK(mbedtls_internal_ecp_init(grp)); } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ int restarting = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL); #endif /* skip argument check when restarting */ if (!restarting) { /* check_privkey is free */ MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_CHK); /* Common sanity checks */ MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(grp, m)); MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); } ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { MBEDTLS_MPI_CHK(ecp_mul_mxz(grp, R, m, P, f_rng, p_rng)); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { MBEDTLS_MPI_CHK(ecp_mul_comb(grp, R, m, P, f_rng, p_rng, rs_ctx)); } #endif cleanup: #if defined(MBEDTLS_ECP_INTERNAL_ALT) if (is_grp_capable) { mbedtls_internal_ecp_free(grp); } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL) { rs_ctx->depth--; } #endif return ret; } /* * Restartable multiplication R = m * P */ int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { if (f_rng == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return ecp_mul_restartable_internal(grp, R, m, P, f_rng, p_rng, rs_ctx); } /* * Multiplication R = m * P */ int mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecp_mul_restartable(grp, R, m, P, f_rng, p_rng, NULL); } #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * Check that an affine point is valid as a public key, * short weierstrass curves (SEC1 3.2.3.1) */ static int ecp_check_pubkey_sw(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi YY, RHS; /* pt coordinates must be normalized for our checks */ if (mbedtls_mpi_cmp_int(&pt->X, 0) < 0 || mbedtls_mpi_cmp_int(&pt->Y, 0) < 0 || mbedtls_mpi_cmp_mpi(&pt->X, &grp->P) >= 0 || mbedtls_mpi_cmp_mpi(&pt->Y, &grp->P) >= 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } mbedtls_mpi_init(&YY); mbedtls_mpi_init(&RHS); /* * YY = Y^2 * RHS = X^3 + A X + B */ MPI_ECP_SQR(&YY, &pt->Y); MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, &RHS, &pt->X)); if (MPI_ECP_CMP(&YY, &RHS) != 0) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; } cleanup: mbedtls_mpi_free(&YY); mbedtls_mpi_free(&RHS); return ret; } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * R = m * P with shortcuts for m == 0, m == 1 and m == -1 * NOT constant-time - ONLY for short Weierstrass! */ static int mbedtls_ecp_mul_shortcuts(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi tmp; mbedtls_mpi_init(&tmp); if (mbedtls_mpi_cmp_int(m, 0) == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R)); } else if (mbedtls_mpi_cmp_int(m, 1) == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P)); } else if (mbedtls_mpi_cmp_int(m, -1) == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P)); MPI_ECP_NEG(&R->Y); } else { MBEDTLS_MPI_CHK(ecp_mul_restartable_internal(grp, R, m, P, NULL, NULL, rs_ctx)); } cleanup: mbedtls_mpi_free(&tmp); return ret; } /* * Restartable linear combination * NOT constant-time */ int mbedtls_ecp_muladd_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point mP; mbedtls_ecp_point *pmP = &mP; mbedtls_ecp_point *pR = R; mbedtls_mpi tmp[4]; #if defined(MBEDTLS_ECP_INTERNAL_ALT) char is_grp_capable = 0; #endif if (mbedtls_ecp_get_type(grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } mbedtls_ecp_point_init(&mP); mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); ECP_RS_ENTER(ma); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { /* redirect intermediate results to restart context */ pmP = &rs_ctx->ma->mP; pR = &rs_ctx->ma->R; /* jump to next operation */ if (rs_ctx->ma->state == ecp_rsma_mul2) { goto mul2; } if (rs_ctx->ma->state == ecp_rsma_add) { goto add; } if (rs_ctx->ma->state == ecp_rsma_norm) { goto norm; } } #endif /* MBEDTLS_ECP_RESTARTABLE */ MBEDTLS_MPI_CHK(mbedtls_ecp_mul_shortcuts(grp, pmP, m, P, rs_ctx)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { rs_ctx->ma->state = ecp_rsma_mul2; } mul2: #endif MBEDTLS_MPI_CHK(mbedtls_ecp_mul_shortcuts(grp, pR, n, Q, rs_ctx)); #if defined(MBEDTLS_ECP_INTERNAL_ALT) if ((is_grp_capable = mbedtls_internal_ecp_grp_capable(grp))) { MBEDTLS_MPI_CHK(mbedtls_internal_ecp_init(grp)); } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { rs_ctx->ma->state = ecp_rsma_add; } add: #endif MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_ADD); MBEDTLS_MPI_CHK(ecp_add_mixed(grp, pR, pmP, pR, tmp)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { rs_ctx->ma->state = ecp_rsma_norm; } norm: #endif MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV); MBEDTLS_MPI_CHK(ecp_normalize_jac(grp, pR)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, pR)); } #endif cleanup: mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_INTERNAL_ALT) if (is_grp_capable) { mbedtls_internal_ecp_free(grp); } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ mbedtls_ecp_point_free(&mP); ECP_RS_LEAVE(ma); return ret; } /* * Linear combination * NOT constant-time */ int mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q) { return mbedtls_ecp_muladd_restartable(grp, R, m, P, n, Q, NULL); } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) } #define ECP_MPI_INIT_ARRAY(x) \ ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) /* * Constants for the two points other than 0, 1, -1 (mod p) in * https://cr.yp.to/ecdh.html#validate * See ecp_check_pubkey_x25519(). */ static const mbedtls_mpi_uint x25519_bad_point_1[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a), MBEDTLS_BYTES_TO_T_UINT_8(0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00), }; static const mbedtls_mpi_uint x25519_bad_point_2[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57), }; static const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY( x25519_bad_point_1); static const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY( x25519_bad_point_2); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ /* * Check that the input point is not one of the low-order points. * This is recommended by the "May the Fourth" paper: * https://eprint.iacr.org/2017/806.pdf * Those points are never sent by an honest peer. */ static int ecp_check_bad_points_mx(const mbedtls_mpi *X, const mbedtls_mpi *P, const mbedtls_ecp_group_id grp_id) { int ret; mbedtls_mpi XmP; mbedtls_mpi_init(&XmP); /* Reduce X mod P so that we only need to check values less than P. * We know X < 2^256 so we can proceed by subtraction. */ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&XmP, X)); while (mbedtls_mpi_cmp_mpi(&XmP, P) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&XmP, &XmP, P)); } /* Check against the known bad values that are less than P. For Curve448 * these are 0, 1 and -1. For Curve25519 we check the values less than P * from the following list: https://cr.yp.to/ecdh.html#validate */ if (mbedtls_mpi_cmp_int(&XmP, 1) <= 0) { /* takes care of 0 and 1 */ ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) if (grp_id == MBEDTLS_ECP_DP_CURVE25519) { if (mbedtls_mpi_cmp_mpi(&XmP, &ecp_x25519_bad_point_1) == 0) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } if (mbedtls_mpi_cmp_mpi(&XmP, &ecp_x25519_bad_point_2) == 0) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } } #else (void) grp_id; #endif /* Final check: check if XmP + 1 is P (final because it changes XmP!) */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&XmP, &XmP, 1)); if (mbedtls_mpi_cmp_mpi(&XmP, P) == 0) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } ret = 0; cleanup: mbedtls_mpi_free(&XmP); return ret; } /* * Check validity of a public key for Montgomery curves with x-only schemes */ static int ecp_check_pubkey_mx(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt) { /* [Curve25519 p. 5] Just check X is the correct number of bytes */ /* Allow any public value, if it's too big then we'll just reduce it mod p * (RFC 7748 sec. 5 para. 3). */ if (mbedtls_mpi_size(&pt->X) > (grp->nbits + 7) / 8) { return MBEDTLS_ERR_ECP_INVALID_KEY; } /* Implicit in all standards (as they don't consider negative numbers): * X must be non-negative. This is normally ensured by the way it's * encoded for transmission, but let's be extra sure. */ if (mbedtls_mpi_cmp_int(&pt->X, 0) < 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } return ecp_check_bad_points_mx(&pt->X, &grp->P, grp->id); } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ /* * Check that a point is valid as a public key */ int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt) { /* Must use affine coordinates */ if (mbedtls_mpi_cmp_int(&pt->Z, 1) != 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { return ecp_check_pubkey_mx(grp, pt); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { return ecp_check_pubkey_sw(grp, pt); } #endif return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Check that an mbedtls_mpi is valid as a private key */ int mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp, const mbedtls_mpi *d) { #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { /* see RFC 7748 sec. 5 para. 5 */ if (mbedtls_mpi_get_bit(d, 0) != 0 || mbedtls_mpi_get_bit(d, 1) != 0 || mbedtls_mpi_bitlen(d) - 1 != grp->nbits) { /* mbedtls_mpi_bitlen is one-based! */ return MBEDTLS_ERR_ECP_INVALID_KEY; } /* see [Curve25519] page 5 */ if (grp->nbits == 254 && mbedtls_mpi_get_bit(d, 2) != 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } return 0; } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { /* see SEC1 3.2 */ if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } else { return 0; } } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_gen_privkey_mx(size_t high_bit, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; size_t n_random_bytes = high_bit / 8 + 1; /* [Curve25519] page 5 */ /* Generate a (high_bit+1)-bit random number by generating just enough * random bytes, then shifting out extra bits from the top (necessary * when (high_bit+1) is not a multiple of 8). */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(d, n_random_bytes, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(d, 8 * n_random_bytes - high_bit - 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, high_bit, 1)); /* Make sure the last two bits are unset for Curve448, three bits for Curve25519 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 0, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 1, 0)); if (high_bit == 254) { MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 2, 0)); } cleanup: return ret; } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) static int mbedtls_ecp_gen_privkey_sw( const mbedtls_mpi *N, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = mbedtls_mpi_random(d, 1, N, f_rng, p_rng); switch (ret) { case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: return MBEDTLS_ERR_ECP_RANDOM_FAILED; default: return ret; } } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ /* * Generate a private key */ int mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { return mbedtls_ecp_gen_privkey_mx(grp->nbits, d, f_rng, p_rng); } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { return mbedtls_ecp_gen_privkey_sw(&grp->N, d, f_rng, p_rng); } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_C) /* * Generate a keypair with configurable base point */ int mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group *grp, const mbedtls_ecp_point *G, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, Q, d, G, f_rng, p_rng)); cleanup: return ret; } /* * Generate key pair, wrapper for conventional base point */ int mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecp_gen_keypair_base(grp, &grp->G, d, Q, f_rng, p_rng); } /* * Generate a keypair, prettier wrapper */ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) { return ret; } return mbedtls_ecp_gen_keypair(&key->grp, &key->d, &key->Q, f_rng, p_rng); } #endif /* MBEDTLS_ECP_C */ int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const mbedtls_ecp_point *Q) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (key->grp.id == MBEDTLS_ECP_DP_NONE) { /* Group not set yet */ if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) { return ret; } } else if (key->grp.id != grp_id) { /* Group mismatch */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return mbedtls_ecp_copy(&key->Q, Q); } #define ECP_CURVE25519_KEY_SIZE 32 #define ECP_CURVE448_KEY_SIZE 56 /* * Read a private key. */ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const unsigned char *buf, size_t buflen) { int ret = 0; if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) { return ret; } ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { /* * Mask the key as mandated by RFC7748 for Curve25519 and Curve448. */ if (grp_id == MBEDTLS_ECP_DP_CURVE25519) { if (buflen != ECP_CURVE25519_KEY_SIZE) { return MBEDTLS_ERR_ECP_INVALID_KEY; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen)); /* Set the three least significant bits to 0 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 0, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 1, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 2, 0)); /* Set the most significant bit to 0 */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit(&key->d, ECP_CURVE25519_KEY_SIZE * 8 - 1, 0) ); /* Set the second most significant bit to 1 */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit(&key->d, ECP_CURVE25519_KEY_SIZE * 8 - 2, 1) ); } else if (grp_id == MBEDTLS_ECP_DP_CURVE448) { if (buflen != ECP_CURVE448_KEY_SIZE) { return MBEDTLS_ERR_ECP_INVALID_KEY; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen)); /* Set the two least significant bits to 0 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 0, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 1, 0)); /* Set the most significant bit to 1 */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit(&key->d, ECP_CURVE448_KEY_SIZE * 8 - 1, 1) ); } } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&key->d, buf, buflen)); } #endif if (ret == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(&key->grp, &key->d)); } cleanup: if (ret != 0) { mbedtls_mpi_free(&key->d); } return ret; } /* * Write a private key. */ #if !defined MBEDTLS_DEPRECATED_REMOVED int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { if (key->grp.id == MBEDTLS_ECP_DP_CURVE25519) { if (buflen < ECP_CURVE25519_KEY_SIZE) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } } else if (key->grp.id == MBEDTLS_ECP_DP_CURVE448) { if (buflen < ECP_CURVE448_KEY_SIZE) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } } MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&key->d, buf, buflen)); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&key->d, buf, buflen)); } #endif cleanup: return ret; } #endif /* MBEDTLS_DEPRECATED_REMOVED */ int mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key, size_t *olen, unsigned char *buf, size_t buflen) { size_t len = (key->grp.nbits + 7) / 8; if (len > buflen) { /* For robustness, ensure *olen <= buflen even on error. */ *olen = 0; return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } *olen = len; /* Private key not set */ if (key->d.n == 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { return mbedtls_mpi_write_binary_le(&key->d, buf, len); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { return mbedtls_mpi_write_binary(&key->d, buf, len); } #endif /* Private key set but no recognized curve type? This shouldn't happen. */ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } /* * Write a public key. */ int mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key, int format, size_t *olen, unsigned char *buf, size_t buflen) { return mbedtls_ecp_point_write_binary(&key->grp, &key->Q, format, olen, buf, buflen); } #if defined(MBEDTLS_ECP_C) /* * Check a public-private key pair */ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point Q; mbedtls_ecp_group grp; if (pub->grp.id == MBEDTLS_ECP_DP_NONE || pub->grp.id != prv->grp.id || mbedtls_mpi_cmp_mpi(&pub->Q.X, &prv->Q.X) || mbedtls_mpi_cmp_mpi(&pub->Q.Y, &prv->Q.Y) || mbedtls_mpi_cmp_mpi(&pub->Q.Z, &prv->Q.Z)) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } mbedtls_ecp_point_init(&Q); mbedtls_ecp_group_init(&grp); /* mbedtls_ecp_mul() needs a non-const group... */ mbedtls_ecp_group_copy(&grp, &prv->grp); /* Also checks d is valid */ MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &Q, &prv->d, &prv->grp.G, f_rng, p_rng)); if (mbedtls_mpi_cmp_mpi(&Q.X, &prv->Q.X) || mbedtls_mpi_cmp_mpi(&Q.Y, &prv->Q.Y) || mbedtls_mpi_cmp_mpi(&Q.Z, &prv->Q.Z)) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } cleanup: mbedtls_ecp_point_free(&Q); mbedtls_ecp_group_free(&grp); return ret; } int mbedtls_ecp_keypair_calc_public(mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecp_mul(&key->grp, &key->Q, &key->d, &key->grp.G, f_rng, p_rng); } #endif /* MBEDTLS_ECP_C */ mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id( const mbedtls_ecp_keypair *key) { return key->grp.id; } /* * Export generic key-pair parameters. */ int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (grp != NULL && (ret = mbedtls_ecp_group_copy(grp, &key->grp)) != 0) { return ret; } if (d != NULL && (ret = mbedtls_mpi_copy(d, &key->d)) != 0) { return ret; } if (Q != NULL && (ret = mbedtls_ecp_copy(Q, &key->Q)) != 0) { return ret; } return 0; } #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_ECP_C) /* * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! * * This is the linear congruential generator from numerical recipes, * except we only use the low byte as the output. See * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use */ static int self_test_rng(void *ctx, unsigned char *out, size_t len) { static uint32_t state = 42; (void) ctx; for (size_t i = 0; i < len; i++) { state = state * 1664525u + 1013904223u; out[i] = (unsigned char) state; } return 0; } /* Adjust the exponent to be a valid private point for the specified curve. * This is sometimes necessary because we use a single set of exponents * for all curves but the validity of values depends on the curve. */ static int self_test_adjust_exponent(const mbedtls_ecp_group *grp, mbedtls_mpi *m) { int ret = 0; switch (grp->id) { /* If Curve25519 is available, then that's what we use for the * Montgomery test, so we don't need the adjustment code. */ #if !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) case MBEDTLS_ECP_DP_CURVE448: /* Move highest bit from 254 to N-1. Setting bit N-1 is * necessary to enforce the highest-bit-set constraint. */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(m, 254, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(m, grp->nbits, 1)); /* Copy second-highest bit from 253 to N-2. This is not * necessary but improves the test variety a bit. */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit(m, grp->nbits - 1, mbedtls_mpi_get_bit(m, 253))); break; #endif #endif /* ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) */ default: /* Non-Montgomery curves and Curve25519 need no adjustment. */ (void) grp; (void) m; goto cleanup; } cleanup: return ret; } /* Calculate R = m.P for each m in exponents. Check that the number of * basic operations doesn't depend on the value of m. */ static int self_test_point(int verbose, mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_mpi *m, const mbedtls_ecp_point *P, const char *const *exponents, size_t n_exponents) { int ret = 0; size_t i = 0; unsigned long add_c_prev, dbl_c_prev, mul_c_prev; add_count = 0; dbl_count = 0; mul_count = 0; MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[0])); MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL)); for (i = 1; i < n_exponents; i++) { add_c_prev = add_count; dbl_c_prev = dbl_count; mul_c_prev = mul_count; add_count = 0; dbl_count = 0; mul_count = 0; MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[i])); MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL)); if (add_count != add_c_prev || dbl_count != dbl_c_prev || mul_count != mul_c_prev) { ret = 1; break; } } cleanup: if (verbose != 0) { if (ret != 0) { mbedtls_printf("failed (%u)\n", (unsigned int) i); } else { mbedtls_printf("passed\n"); } } return ret; } #endif /* MBEDTLS_ECP_C */ /* * Checkup routine */ int mbedtls_ecp_self_test(int verbose) { #if defined(MBEDTLS_ECP_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group grp; mbedtls_ecp_point R, P; mbedtls_mpi m; #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* Exponents especially adapted for secp192k1, which has the lowest * order n of all supported curves (secp192r1 is in a slightly larger * field but the order of its base point is slightly smaller). */ const char *sw_exponents[] = { "000000000000000000000000000000000000000000000001", /* one */ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8C", /* n - 1 */ "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ "400000000000000000000000000000000000000000000000", /* one and zeros */ "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ "555555555555555555555555555555555555555555555555", /* 101010... */ }; #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) const char *m_exponents[] = { /* Valid private values for Curve25519. In a build with Curve448 * but not Curve25519, they will be adjusted in * self_test_adjust_exponent(). */ "4000000000000000000000000000000000000000000000000000000000000000", "5C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C30", "5715ECCE24583F7A7023C24164390586842E816D7280A49EF6DF4EAE6B280BF8", "41A2B017516F6D254E1F002BCCBADD54BE30F8CEC737A0E912B4963B6BA74460", "5555555555555555555555555555555555555555555555555555555555555550", "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8", }; #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ mbedtls_ecp_group_init(&grp); mbedtls_ecp_point_init(&R); mbedtls_ecp_point_init(&P); mbedtls_mpi_init(&m); #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* Use secp192r1 if available, or any available curve */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP192R1)); #else MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, mbedtls_ecp_curve_list()->grp_id)); #endif if (verbose != 0) { mbedtls_printf(" ECP SW test #1 (constant op_count, base point G): "); } /* Do a dummy multiplication first to trigger precomputation */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&m, 2)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &P, &m, &grp.G, self_test_rng, NULL)); ret = self_test_point(verbose, &grp, &R, &m, &grp.G, sw_exponents, sizeof(sw_exponents) / sizeof(sw_exponents[0])); if (ret != 0) { goto cleanup; } if (verbose != 0) { mbedtls_printf(" ECP SW test #2 (constant op_count, other point): "); } /* We computed P = 2G last time, use it */ ret = self_test_point(verbose, &grp, &R, &m, &P, sw_exponents, sizeof(sw_exponents) / sizeof(sw_exponents[0])); if (ret != 0) { goto cleanup; } mbedtls_ecp_group_free(&grp); mbedtls_ecp_point_free(&R); #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (verbose != 0) { mbedtls_printf(" ECP Montgomery test (constant op_count): "); } #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519)); #elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE448)); #else #error "MBEDTLS_ECP_MONTGOMERY_ENABLED is defined, but no curve is supported for self-test" #endif ret = self_test_point(verbose, &grp, &R, &m, &grp.G, m_exponents, sizeof(m_exponents) / sizeof(m_exponents[0])); if (ret != 0) { goto cleanup; } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ cleanup: if (ret < 0 && verbose != 0) { mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret); } mbedtls_ecp_group_free(&grp); mbedtls_ecp_point_free(&R); mbedtls_ecp_point_free(&P); mbedtls_mpi_free(&m); if (verbose != 0) { mbedtls_printf("\n"); } return ret; #else /* MBEDTLS_ECP_C */ (void) verbose; return 0; #endif /* MBEDTLS_ECP_C */ } #endif /* MBEDTLS_SELF_TEST */ #endif /* !MBEDTLS_ECP_ALT */ #endif /* MBEDTLS_ECP_LIGHT */ webfakes/src/mbedtls/library/cipher_wrap.h0000644000176200001440000001405714740737024020421 0ustar liggesusers/** * \file cipher_wrap.h * * \brief Cipher wrappers. * * \author Adriaan de Jong */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CIPHER_WRAP_H #define MBEDTLS_CIPHER_WRAP_H #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ #ifdef __cplusplus extern "C" { #endif /* Support for GCM either through Mbed TLS SW implementation or PSA */ #if defined(MBEDTLS_GCM_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM)) #define MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA #endif #if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM) && defined(PSA_WANT_KEY_TYPE_AES)) #define MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA #endif #if defined(MBEDTLS_CCM_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM)) #define MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA #endif #if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM) && defined(PSA_WANT_KEY_TYPE_AES)) #define MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA #endif #if defined(MBEDTLS_CCM_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)) #define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA #endif #if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && \ defined(PSA_WANT_KEY_TYPE_AES)) #define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA #endif #if defined(MBEDTLS_CHACHAPOLY_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305)) #define MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA #endif #if defined(MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA) #define MBEDTLS_CIPHER_HAVE_SOME_AEAD_VIA_LEGACY_OR_USE_PSA #endif /** * Base cipher information. The non-mode specific functions and values. */ struct mbedtls_cipher_base_t { /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ mbedtls_cipher_id_t cipher; /** Encrypt using ECB */ int (*ecb_func)(void *ctx, mbedtls_operation_t mode, const unsigned char *input, unsigned char *output); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** Encrypt using CBC */ int (*cbc_func)(void *ctx, mbedtls_operation_t mode, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) /** Encrypt using CFB (Full length) */ int (*cfb_func)(void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) /** Encrypt using OFB (Full length) */ int (*ofb_func)(void *ctx, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) /** Encrypt using CTR */ int (*ctr_func)(void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) /** Encrypt or decrypt using XTS. */ int (*xts_func)(void *ctx, mbedtls_operation_t mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) /** Encrypt using STREAM */ int (*stream_func)(void *ctx, size_t length, const unsigned char *input, unsigned char *output); #endif /** Set key for encryption purposes */ int (*setkey_enc_func)(void *ctx, const unsigned char *key, unsigned int key_bitlen); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** Set key for decryption purposes */ int (*setkey_dec_func)(void *ctx, const unsigned char *key, unsigned int key_bitlen); #endif /** Allocate a new context */ void * (*ctx_alloc_func)(void); /** Free the given context */ void (*ctx_free_func)(void *ctx); }; typedef struct { mbedtls_cipher_type_t type; const mbedtls_cipher_info_t *info; } mbedtls_cipher_definition_t; #if defined(MBEDTLS_USE_PSA_CRYPTO) typedef enum { MBEDTLS_CIPHER_PSA_KEY_UNSET = 0, MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */ /* use raw key material internally imported */ /* as a volatile key, and which hence need */ /* to destroy that key when the context is */ /* freed. */ MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */ /* which use a key provided by the */ /* user, and which hence will not be */ /* destroyed when the context is freed. */ } mbedtls_cipher_psa_key_ownership; typedef struct { psa_algorithm_t alg; mbedtls_svc_key_id_t slot; mbedtls_cipher_psa_key_ownership slot_state; } mbedtls_cipher_context_psa; #endif /* MBEDTLS_USE_PSA_CRYPTO */ extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; extern int mbedtls_cipher_supported[]; extern const mbedtls_cipher_base_t *mbedtls_cipher_base_lookup_table[]; #ifdef __cplusplus } #endif #endif /* MBEDTLS_CIPHER_WRAP_H */ webfakes/src/mbedtls/library/md5.c0000644000176200001440000003040114740737024016565 0ustar liggesusers/* * RFC 1321 compliant MD5 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The MD5 algorithm was designed by Ron Rivest in 1991. * * http://www.ietf.org/rfc/rfc1321.txt */ #include "common.h" #if defined(MBEDTLS_MD5_C) #include "mbedtls/md5.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_MD5_ALT) void mbedtls_md5_init(mbedtls_md5_context *ctx) { memset(ctx, 0, sizeof(mbedtls_md5_context)); } void mbedtls_md5_free(mbedtls_md5_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md5_context)); } void mbedtls_md5_clone(mbedtls_md5_context *dst, const mbedtls_md5_context *src) { *dst = *src; } /* * MD5 context setup */ int mbedtls_md5_starts(mbedtls_md5_context *ctx) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; return 0; } #if !defined(MBEDTLS_MD5_PROCESS_ALT) int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, const unsigned char data[64]) { struct { uint32_t X[16], A, B, C, D; } local; local.X[0] = MBEDTLS_GET_UINT32_LE(data, 0); local.X[1] = MBEDTLS_GET_UINT32_LE(data, 4); local.X[2] = MBEDTLS_GET_UINT32_LE(data, 8); local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12); local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16); local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20); local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24); local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28); local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32); local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36); local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40); local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44); local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48); local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52); local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56); local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60); #define S(x, n) \ (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) #define P(a, b, c, d, k, s, t) \ do \ { \ (a) += F((b), (c), (d)) + local.X[(k)] + (t); \ (a) = S((a), (s)) + (b); \ } while (0) local.A = ctx->state[0]; local.B = ctx->state[1]; local.C = ctx->state[2]; local.D = ctx->state[3]; #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) P(local.A, local.B, local.C, local.D, 0, 7, 0xD76AA478); P(local.D, local.A, local.B, local.C, 1, 12, 0xE8C7B756); P(local.C, local.D, local.A, local.B, 2, 17, 0x242070DB); P(local.B, local.C, local.D, local.A, 3, 22, 0xC1BDCEEE); P(local.A, local.B, local.C, local.D, 4, 7, 0xF57C0FAF); P(local.D, local.A, local.B, local.C, 5, 12, 0x4787C62A); P(local.C, local.D, local.A, local.B, 6, 17, 0xA8304613); P(local.B, local.C, local.D, local.A, 7, 22, 0xFD469501); P(local.A, local.B, local.C, local.D, 8, 7, 0x698098D8); P(local.D, local.A, local.B, local.C, 9, 12, 0x8B44F7AF); P(local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1); P(local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE); P(local.A, local.B, local.C, local.D, 12, 7, 0x6B901122); P(local.D, local.A, local.B, local.C, 13, 12, 0xFD987193); P(local.C, local.D, local.A, local.B, 14, 17, 0xA679438E); P(local.B, local.C, local.D, local.A, 15, 22, 0x49B40821); #undef F #define F(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) P(local.A, local.B, local.C, local.D, 1, 5, 0xF61E2562); P(local.D, local.A, local.B, local.C, 6, 9, 0xC040B340); P(local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51); P(local.B, local.C, local.D, local.A, 0, 20, 0xE9B6C7AA); P(local.A, local.B, local.C, local.D, 5, 5, 0xD62F105D); P(local.D, local.A, local.B, local.C, 10, 9, 0x02441453); P(local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681); P(local.B, local.C, local.D, local.A, 4, 20, 0xE7D3FBC8); P(local.A, local.B, local.C, local.D, 9, 5, 0x21E1CDE6); P(local.D, local.A, local.B, local.C, 14, 9, 0xC33707D6); P(local.C, local.D, local.A, local.B, 3, 14, 0xF4D50D87); P(local.B, local.C, local.D, local.A, 8, 20, 0x455A14ED); P(local.A, local.B, local.C, local.D, 13, 5, 0xA9E3E905); P(local.D, local.A, local.B, local.C, 2, 9, 0xFCEFA3F8); P(local.C, local.D, local.A, local.B, 7, 14, 0x676F02D9); P(local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A); #undef F #define F(x, y, z) ((x) ^ (y) ^ (z)) P(local.A, local.B, local.C, local.D, 5, 4, 0xFFFA3942); P(local.D, local.A, local.B, local.C, 8, 11, 0x8771F681); P(local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122); P(local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C); P(local.A, local.B, local.C, local.D, 1, 4, 0xA4BEEA44); P(local.D, local.A, local.B, local.C, 4, 11, 0x4BDECFA9); P(local.C, local.D, local.A, local.B, 7, 16, 0xF6BB4B60); P(local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70); P(local.A, local.B, local.C, local.D, 13, 4, 0x289B7EC6); P(local.D, local.A, local.B, local.C, 0, 11, 0xEAA127FA); P(local.C, local.D, local.A, local.B, 3, 16, 0xD4EF3085); P(local.B, local.C, local.D, local.A, 6, 23, 0x04881D05); P(local.A, local.B, local.C, local.D, 9, 4, 0xD9D4D039); P(local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5); P(local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8); P(local.B, local.C, local.D, local.A, 2, 23, 0xC4AC5665); #undef F #define F(x, y, z) ((y) ^ ((x) | ~(z))) P(local.A, local.B, local.C, local.D, 0, 6, 0xF4292244); P(local.D, local.A, local.B, local.C, 7, 10, 0x432AFF97); P(local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7); P(local.B, local.C, local.D, local.A, 5, 21, 0xFC93A039); P(local.A, local.B, local.C, local.D, 12, 6, 0x655B59C3); P(local.D, local.A, local.B, local.C, 3, 10, 0x8F0CCC92); P(local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D); P(local.B, local.C, local.D, local.A, 1, 21, 0x85845DD1); P(local.A, local.B, local.C, local.D, 8, 6, 0x6FA87E4F); P(local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0); P(local.C, local.D, local.A, local.B, 6, 15, 0xA3014314); P(local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1); P(local.A, local.B, local.C, local.D, 4, 6, 0xF7537E82); P(local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235); P(local.C, local.D, local.A, local.B, 2, 15, 0x2AD7D2BB); P(local.B, local.C, local.D, local.A, 9, 21, 0xEB86D391); #undef F ctx->state[0] += local.A; ctx->state[1] += local.B; ctx->state[2] += local.C; ctx->state[3] += local.D; /* Zeroise variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_MD5_PROCESS_ALT */ /* * MD5 process buffer */ int mbedtls_md5_update(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; if (ilen == 0) { return 0; } left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if (ctx->total[0] < (uint32_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= 64) { if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0) { return ret; } input += 64; ilen -= 64; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } /* * MD5 final digest */ int mbedtls_md5_finish(mbedtls_md5_context *ctx, unsigned char output[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t used; uint32_t high, low; /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ used = ctx->total[0] & 0x3F; ctx->buffer[used++] = 0x80; if (used <= 56) { /* Enough room for padding + length in current block */ memset(ctx->buffer + used, 0, 56 - used); } else { /* We'll need an extra block */ memset(ctx->buffer + used, 0, 64 - used); if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { goto exit; } memset(ctx->buffer, 0, 56); } /* * Add message length */ high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); MBEDTLS_PUT_UINT32_LE(low, ctx->buffer, 56); MBEDTLS_PUT_UINT32_LE(high, ctx->buffer, 60); if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { goto exit; } /* * Output final state */ MBEDTLS_PUT_UINT32_LE(ctx->state[0], output, 0); MBEDTLS_PUT_UINT32_LE(ctx->state[1], output, 4); MBEDTLS_PUT_UINT32_LE(ctx->state[2], output, 8); MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12); ret = 0; exit: mbedtls_md5_free(ctx); return ret; } #endif /* !MBEDTLS_MD5_ALT */ /* * output = MD5( input buffer ) */ int mbedtls_md5(const unsigned char *input, size_t ilen, unsigned char output[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md5_context ctx; mbedtls_md5_init(&ctx); if ((ret = mbedtls_md5_starts(&ctx)) != 0) { goto exit; } if ((ret = mbedtls_md5_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_md5_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_md5_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * RFC 1321 test vectors */ static const unsigned char md5_test_buf[7][81] = { { "" }, { "a" }, { "abc" }, { "message digest" }, { "abcdefghijklmnopqrstuvwxyz" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } }; static const size_t md5_test_buflen[7] = { 0, 1, 3, 14, 26, 62, 80 }; static const unsigned char md5_test_sum[7][16] = { { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } }; /* * Checkup routine */ int mbedtls_md5_self_test(int verbose) { int i, ret = 0; unsigned char md5sum[16]; for (i = 0; i < 7; i++) { if (verbose != 0) { mbedtls_printf(" MD5 test #%d: ", i + 1); } ret = mbedtls_md5(md5_test_buf[i], md5_test_buflen[i], md5sum); if (ret != 0) { goto fail; } if (memcmp(md5sum, md5_test_sum[i], 16) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_MD5_C */ webfakes/src/mbedtls/library/ssl_cookie.c0000644000176200001440000002473614740737024020250 0ustar liggesusers/* * DTLS cookie callbacks implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * These session callbacks use a simple chained list * to store and retrieve the session information. */ #include "common.h" #if defined(MBEDTLS_SSL_COOKIE_C) #include "mbedtls/platform.h" #include "mbedtls/ssl_cookie.h" #include "ssl_misc.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/psa_util.h" /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif /* * If DTLS is in use, then at least one of SHA-256 or SHA-384 is * available. Try SHA-256 first as 384 wastes resources */ #if defined(MBEDTLS_MD_CAN_SHA256) #define COOKIE_MD MBEDTLS_MD_SHA256 #define COOKIE_MD_OUTLEN 32 #define COOKIE_HMAC_LEN 28 #elif defined(MBEDTLS_MD_CAN_SHA384) #define COOKIE_MD MBEDTLS_MD_SHA384 #define COOKIE_MD_OUTLEN 48 #define COOKIE_HMAC_LEN 28 #else #error "DTLS hello verify needs SHA-256 or SHA-384" #endif /* * Cookies are formed of a 4-bytes timestamp (or serial number) and * an HMAC of timestamp and client ID. */ #define COOKIE_LEN (4 + COOKIE_HMAC_LEN) void mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx) { #if defined(MBEDTLS_USE_PSA_CRYPTO) ctx->psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_md_init(&ctx->hmac_ctx); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_HAVE_TIME) ctx->serial = 0; #endif ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; #if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay) { ctx->timeout = delay; } void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_destroy_key(ctx->psa_hmac_key); #else mbedtls_md_free(&ctx->hmac_ctx); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&ctx->mutex); #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_cookie_ctx)); } int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_algorithm_t alg; (void) f_rng; (void) p_rng; alg = mbedtls_md_psa_alg_from_type(COOKIE_MD); if (alg == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ctx->psa_hmac_alg = PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(alg), COOKIE_HMAC_LEN); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_SIGN_MESSAGE); psa_set_key_algorithm(&attributes, ctx->psa_hmac_alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(COOKIE_MD_OUTLEN)); if ((status = psa_generate_key(&attributes, &ctx->psa_hmac_key)) != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char key[COOKIE_MD_OUTLEN]; if ((ret = f_rng(p_rng, key, sizeof(key))) != 0) { return ret; } ret = mbedtls_md_setup(&ctx->hmac_ctx, mbedtls_md_info_from_type(COOKIE_MD), 1); if (ret != 0) { return ret; } ret = mbedtls_md_hmac_starts(&ctx->hmac_ctx, key, sizeof(key)); if (ret != 0) { return ret; } mbedtls_platform_zeroize(key, sizeof(key)); #endif /* MBEDTLS_USE_PSA_CRYPTO */ return 0; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) /* * Generate the HMAC part of a cookie */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cookie_hmac(mbedtls_md_context_t *hmac_ctx, const unsigned char time[4], unsigned char **p, unsigned char *end, const unsigned char *cli_id, size_t cli_id_len) { unsigned char hmac_out[COOKIE_MD_OUTLEN]; MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_HMAC_LEN); if (mbedtls_md_hmac_reset(hmac_ctx) != 0 || mbedtls_md_hmac_update(hmac_ctx, time, 4) != 0 || mbedtls_md_hmac_update(hmac_ctx, cli_id, cli_id_len) != 0 || mbedtls_md_hmac_finish(hmac_ctx, hmac_out) != 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(*p, hmac_out, COOKIE_HMAC_LEN); *p += COOKIE_HMAC_LEN; return 0; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ /* * Generate cookie for DTLS ClientHello verification */ int mbedtls_ssl_cookie_write(void *p_ctx, unsigned char **p, unsigned char *end, const unsigned char *cli_id, size_t cli_id_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t sign_mac_length = 0; #endif int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; unsigned long t; if (ctx == NULL || cli_id == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_LEN); #if defined(MBEDTLS_HAVE_TIME) t = (unsigned long) mbedtls_time(NULL); #else t = ctx->serial++; #endif MBEDTLS_PUT_UINT32_BE(t, *p, 0); *p += 4; #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_sign_setup(&operation, ctx->psa_hmac_key, ctx->psa_hmac_alg); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_update(&operation, *p - 4, 4); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_update(&operation, cli_id, cli_id_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_sign_finish(&operation, *p, COOKIE_MD_OUTLEN, &sign_mac_length); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } *p += COOKIE_HMAC_LEN; ret = 0; #else #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret); } #endif ret = ssl_cookie_hmac(&ctx->hmac_ctx, *p - 4, p, end, cli_id, cli_id_len); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, MBEDTLS_ERR_THREADING_MUTEX_ERROR); } #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) exit: status = psa_mac_abort(&operation); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return ret; } /* * Check a cookie */ int mbedtls_ssl_cookie_check(void *p_ctx, const unsigned char *cookie, size_t cookie_len, const unsigned char *cli_id, size_t cli_id_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #else unsigned char ref_hmac[COOKIE_HMAC_LEN]; unsigned char *p = ref_hmac; #endif int ret = 0; mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; unsigned long cur_time, cookie_time; if (ctx == NULL || cli_id == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (cookie_len != COOKIE_LEN) { return -1; } #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_verify_setup(&operation, ctx->psa_hmac_key, ctx->psa_hmac_alg); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_update(&operation, cookie, 4); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_update(&operation, cli_id, cli_id_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_verify_finish(&operation, cookie + 4, COOKIE_HMAC_LEN); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } ret = 0; #else #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret); } #endif if (ssl_cookie_hmac(&ctx->hmac_ctx, cookie, &p, p + sizeof(ref_hmac), cli_id, cli_id_len) != 0) { ret = -1; } #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, MBEDTLS_ERR_THREADING_MUTEX_ERROR); } #endif if (ret != 0) { goto exit; } if (mbedtls_ct_memcmp(cookie + 4, ref_hmac, sizeof(ref_hmac)) != 0) { ret = -1; goto exit; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_HAVE_TIME) cur_time = (unsigned long) mbedtls_time(NULL); #else cur_time = ctx->serial; #endif cookie_time = (unsigned long) MBEDTLS_GET_UINT32_BE(cookie, 0); if (ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout) { ret = -1; goto exit; } exit: #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_abort(&operation); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #else mbedtls_platform_zeroize(ref_hmac, sizeof(ref_hmac)); #endif /* MBEDTLS_USE_PSA_CRYPTO */ return ret; } #endif /* MBEDTLS_SSL_COOKIE_C */ webfakes/src/mbedtls/library/debug_internal.h0000644000176200001440000001603314740737024021074 0ustar liggesusers/** * \file debug_internal.h * * \brief Internal part of the public "debug.h". */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_DEBUG_INTERNAL_H #define MBEDTLS_DEBUG_INTERNAL_H #include "mbedtls/debug.h" /** * \brief Print a message to the debug output. This function is always used * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl * context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the message has occurred in * \param line line number the message has occurred at * \param format format specifier, in printf format * \param ... variables used by the format specifier * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *format, ...) MBEDTLS_PRINTF_ATTRIBUTE(5, 6); /** * \brief Print the return value of a function to the debug output. This * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, * which supplies the ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text the name of the function that returned the error * \param ret the return code value * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, int ret); /** * \brief Output a buffer of size len bytes to the debug output. This function * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, * which supplies the ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text a name or label for the buffer being dumped. Normally the * variable or buffer name * \param buf the buffer to be outputted * \param len length of the buffer * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const unsigned char *buf, size_t len); #if defined(MBEDTLS_BIGNUM_C) /** * \brief Print a MPI variable to the debug output. This function is always * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the * ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text a name or label for the MPI being output. Normally the * variable name * \param X the MPI variable * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_mpi *X); #endif #if defined(MBEDTLS_ECP_LIGHT) /** * \brief Print an ECP point to the debug output. This function is always * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the * ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text a name or label for the ECP point being output. Normally the * variable name * \param X the ECP point * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_ecp_point *X); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Print a X.509 certificate structure to the debug output. This * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, * which supplies the ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text a name or label for the certificate being output * \param crt X.509 certificate structure * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_x509_crt *crt); #endif /* Note: the MBEDTLS_ECDH_C guard here is mandatory because this debug function only works for the built-in implementation. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \ defined(MBEDTLS_ECDH_C) typedef enum { MBEDTLS_DEBUG_ECDH_Q, MBEDTLS_DEBUG_ECDH_QP, MBEDTLS_DEBUG_ECDH_Z, } mbedtls_debug_ecdh_attr; /** * \brief Print a field of the ECDH structure in the SSL context to the debug * output. This function is always used through the * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file * and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param ecdh the ECDH context * \param attr the identifier of the attribute being output * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const mbedtls_ecdh_context *ecdh, mbedtls_debug_ecdh_attr attr); #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED && MBEDTLS_ECDH_C */ #endif /* MBEDTLS_DEBUG_INTERNAL_H */ webfakes/src/mbedtls/library/pkcs5.c0000644000176200001440000003617714740737024017145 0ustar liggesusers/** * \file pkcs5.c * * \brief PKCS#5 functions * * \author Mathias Olsson * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * PKCS#5 includes PBKDF2 and more * * http://tools.ietf.org/html/rfc2898 (Specification) * http://tools.ietf.org/html/rfc6070 (Test vectors) */ #include "common.h" #if defined(MBEDTLS_PKCS5_C) #include "mbedtls/pkcs5.h" #include "mbedtls/error.h" #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif /* MBEDTLS_CIPHER_C */ #include "mbedtls/oid.h" #endif /* MBEDTLS_ASN1_PARSE_C */ #include #include "mbedtls/platform.h" #include "psa_util_internal.h" #if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations, int *keylen, mbedtls_md_type_t *md_type) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_asn1_buf prf_alg_oid; unsigned char *p = params->p; const unsigned char *end = params->p + params->len; if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } /* * PBKDF2-params ::= SEQUENCE { * salt OCTET STRING, * iterationCount INTEGER, * keyLength INTEGER OPTIONAL * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 * } * */ if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } salt->p = p; p += salt->len; if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } if (p == end) { return 0; } if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) { if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } } if (p == end) { return 0; } if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } if (p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output, size_t output_size, size_t *output_len); #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output) { size_t output_len = 0; /* We assume caller of the function is providing a big enough output buffer * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees * for the output size actually being correct. */ return mbedtls_pkcs5_pbes2_ext(pbe_params, mode, pwd, pwdlen, data, datalen, output, SIZE_MAX, &output_len); } #endif int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output, size_t output_size, size_t *output_len) { int ret, iterations = 0, keylen = 0; unsigned char *p, *end; mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; mbedtls_asn1_buf salt; mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; unsigned char key[32], iv[32]; const mbedtls_cipher_info_t *cipher_info; mbedtls_cipher_type_t cipher_alg; mbedtls_cipher_context_t cipher_ctx; unsigned int padlen = 0; p = pbe_params->p; end = p + pbe_params->len; /* * PBES2-params ::= SEQUENCE { * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} * } */ if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid, &kdf_alg_params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } // Only PBKDF2 supported at the moment // if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params, &salt, &iterations, &keylen, &md_type)) != 0) { return ret; } if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid, &enc_scheme_params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } cipher_info = mbedtls_cipher_info_from_type(cipher_alg); if (cipher_info == NULL) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } /* * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored * since it is optional and we don't know if it was set or not */ keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || enc_scheme_params.len != mbedtls_cipher_info_get_iv_size(cipher_info)) { return MBEDTLS_ERR_PKCS5_INVALID_FORMAT; } if (mode == MBEDTLS_PKCS5_DECRYPT) { if (output_size < datalen) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } } if (mode == MBEDTLS_PKCS5_ENCRYPT) { padlen = cipher_info->block_size - (datalen % cipher_info->block_size); if (output_size < (datalen + padlen)) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } } mbedtls_cipher_init(&cipher_ctx); memcpy(iv, enc_scheme_params.p, enc_scheme_params.len); if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pwd, pwdlen, salt.p, salt.len, iterations, keylen, key)) != 0) { goto exit; } if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) { goto exit; } if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode)) != 0) { goto exit; } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) { /* PKCS5 uses CBC with PKCS7 padding (which is the same as * "PKCS5 padding" except that it's typically only called PKCS5 * with 64-bit-block ciphers). */ mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) /* For historical reasons, when decrypting, this function works when * decrypting even when support for PKCS7 padding is disabled. In this * case, it ignores the padding, and so will never report a * password mismatch. */ if (mode == MBEDTLS_DECRYPT) { padding = MBEDTLS_PADDING_NONE; } #endif if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { goto exit; } } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len, data, datalen, output, output_len)) != 0) { ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; } exit: mbedtls_cipher_free(&cipher_ctx); return ret; } #endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ static int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned int i; unsigned char md1[MBEDTLS_MD_MAX_SIZE]; unsigned char work[MBEDTLS_MD_MAX_SIZE]; unsigned char md_size = mbedtls_md_get_size(ctx->md_info); size_t use_len; unsigned char *out_p = output; unsigned char counter[4]; memset(counter, 0, 4); counter[3] = 1; #if UINT_MAX > 0xFFFFFFFF if (iteration_count > 0xFFFFFFFF) { return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA; } #endif if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) { return ret; } while (key_length) { // U1 ends up in work // if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) { goto cleanup; } memcpy(md1, work, md_size); for (i = 1; i < iteration_count; i++) { // U2 ends up in md1 // if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) { goto cleanup; } // U1 xor U2 // mbedtls_xor(work, work, md1, md_size); } use_len = (key_length < md_size) ? key_length : md_size; memcpy(out_p, work, use_len); key_length -= (uint32_t) use_len; out_p += use_len; for (i = 4; i > 0; i--) { if (++counter[i - 1] != 0) { break; } } } cleanup: /* Zeroise buffers to clear sensitive data from memory. */ mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE); mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE); return ret; } #if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output) { return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count, key_length, output); } #endif int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output) { mbedtls_md_context_t md_ctx; const mbedtls_md_info_t *md_info = NULL; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } mbedtls_md_init(&md_ctx); if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { goto exit; } ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen, iteration_count, key_length, output); exit: mbedtls_md_free(&md_ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) #if !defined(MBEDTLS_MD_CAN_SHA1) int mbedtls_pkcs5_self_test(int verbose) { if (verbose != 0) { mbedtls_printf(" PBKDF2 (SHA1): skipped\n\n"); } return 0; } #else #define MAX_TESTS 6 static const size_t plen_test_data[MAX_TESTS] = { 8, 8, 8, 24, 9 }; static const unsigned char password_test_data[MAX_TESTS][32] = { "password", "password", "password", "passwordPASSWORDpassword", "pass\0word", }; static const size_t slen_test_data[MAX_TESTS] = { 4, 4, 4, 36, 5 }; static const unsigned char salt_test_data[MAX_TESTS][40] = { "salt", "salt", "salt", "saltSALTsaltSALTsaltSALTsaltSALTsalt", "sa\0lt", }; static const uint32_t it_cnt_test_data[MAX_TESTS] = { 1, 2, 4096, 4096, 4096 }; static const uint32_t key_len_test_data[MAX_TESTS] = { 20, 20, 20, 25, 16 }; static const unsigned char result_key_test_data[MAX_TESTS][32] = { { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6 }, { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57 }, { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 0x65, 0xa4, 0x29, 0xc1 }, { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 0x38 }, { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, }; int mbedtls_pkcs5_self_test(int verbose) { int ret, i; unsigned char key[64]; for (i = 0; i < MAX_TESTS; i++) { if (verbose != 0) { mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i); } ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password_test_data[i], plen_test_data[i], salt_test_data[i], slen_test_data[i], it_cnt_test_data[i], key_len_test_data[i], key); if (ret != 0 || memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } exit: return ret; } #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_PKCS5_C */ webfakes/src/mbedtls/library/psa_crypto_core_common.h0000644000176200001440000000335214740737024022655 0ustar liggesusers/** * \file psa_crypto_core_common.h * * \brief Utility macros for internal use in the PSA cryptography core. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CORE_COMMON_H #define PSA_CRYPTO_CORE_COMMON_H /** Return an offset into a buffer. * * This is just the addition of an offset to a pointer, except that this * function also accepts an offset of 0 into a buffer whose pointer is null. * (`p + n` has undefined behavior when `p` is null, even when `n == 0`. * A null pointer is a valid buffer pointer when the size is 0, for example * as the result of `malloc(0)` on some platforms.) * * \param p Pointer to a buffer of at least n bytes. * This may be \p NULL if \p n is zero. * \param n An offset in bytes. * \return Pointer to offset \p n in the buffer \p p. * Note that this is only a valid pointer if the size of the * buffer is at least \p n + 1. */ static inline unsigned char *psa_crypto_buffer_offset( unsigned char *p, size_t n) { return p == NULL ? NULL : p + n; } /** Return an offset into a read-only buffer. * * Similar to mbedtls_buffer_offset(), but for const pointers. * * \param p Pointer to a buffer of at least n bytes. * This may be \p NULL if \p n is zero. * \param n An offset in bytes. * \return Pointer to offset \p n in the buffer \p p. * Note that this is only a valid pointer if the size of the * buffer is at least \p n + 1. */ static inline const unsigned char *psa_crypto_buffer_offset_const( const unsigned char *p, size_t n) { return p == NULL ? NULL : p + n; } #endif /* PSA_CRYPTO_CORE_COMMON_H */ webfakes/src/mbedtls/library/psa_its_file.c0000644000176200001440000001623114740737024020546 0ustar liggesusers/* * PSA ITS simulator over stdio files. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_ITS_FILE_C) #include "mbedtls/platform.h" #if defined(_WIN32) #include #endif #include "psa_crypto_its.h" #include #include #include #include #if !defined(PSA_ITS_STORAGE_PREFIX) #define PSA_ITS_STORAGE_PREFIX "" #endif #define PSA_ITS_STORAGE_FILENAME_PATTERN "%08x%08x" #define PSA_ITS_STORAGE_SUFFIX ".psa_its" #define PSA_ITS_STORAGE_FILENAME_LENGTH \ (sizeof(PSA_ITS_STORAGE_PREFIX) - 1 + /*prefix without terminating 0*/ \ 16 + /*UID (64-bit number in hex)*/ \ sizeof(PSA_ITS_STORAGE_SUFFIX) - 1 + /*suffix without terminating 0*/ \ 1 /*terminating null byte*/) #define PSA_ITS_STORAGE_TEMP \ PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX /* The maximum value of psa_storage_info_t.size */ #define PSA_ITS_MAX_SIZE 0xffffffff #define PSA_ITS_MAGIC_STRING "PSA\0ITS\0" #define PSA_ITS_MAGIC_LENGTH 8 /* As rename fails on Windows if the new filepath already exists, * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead. * Returns 0 on success, nonzero on failure. */ #if defined(_WIN32) #define rename_replace_existing(oldpath, newpath) \ (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) #else #define rename_replace_existing(oldpath, newpath) rename(oldpath, newpath) #endif typedef struct { uint8_t magic[PSA_ITS_MAGIC_LENGTH]; uint8_t size[sizeof(uint32_t)]; uint8_t flags[sizeof(psa_storage_create_flags_t)]; } psa_its_file_header_t; static void psa_its_fill_filename(psa_storage_uid_t uid, char *filename) { /* Break up the UID into two 32-bit pieces so as not to rely on * long long support in snprintf. */ mbedtls_snprintf(filename, PSA_ITS_STORAGE_FILENAME_LENGTH, "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s", PSA_ITS_STORAGE_PREFIX, (unsigned) (uid >> 32), (unsigned) (uid & 0xffffffff), PSA_ITS_STORAGE_SUFFIX); } static psa_status_t psa_its_read_file(psa_storage_uid_t uid, struct psa_storage_info_t *p_info, FILE **p_stream) { char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; psa_its_file_header_t header; size_t n; *p_stream = NULL; psa_its_fill_filename(uid, filename); *p_stream = fopen(filename, "rb"); if (*p_stream == NULL) { return PSA_ERROR_DOES_NOT_EXIST; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(*p_stream, NULL); n = fread(&header, 1, sizeof(header), *p_stream); if (n != sizeof(header)) { return PSA_ERROR_DATA_CORRUPT; } if (memcmp(header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH) != 0) { return PSA_ERROR_DATA_CORRUPT; } p_info->size = MBEDTLS_GET_UINT32_LE(header.size, 0); p_info->flags = MBEDTLS_GET_UINT32_LE(header.flags, 0); return PSA_SUCCESS; } psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) { psa_status_t status; FILE *stream = NULL; status = psa_its_read_file(uid, p_info, &stream); if (stream != NULL) { fclose(stream); } return status; } psa_status_t psa_its_get(psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data, size_t *p_data_length) { psa_status_t status; FILE *stream = NULL; size_t n; struct psa_storage_info_t info; status = psa_its_read_file(uid, &info, &stream); if (status != PSA_SUCCESS) { goto exit; } status = PSA_ERROR_INVALID_ARGUMENT; if (data_offset + data_length < data_offset) { goto exit; } #if SIZE_MAX < 0xffffffff if (data_offset + data_length > SIZE_MAX) { goto exit; } #endif if (data_offset + data_length > info.size) { goto exit; } status = PSA_ERROR_STORAGE_FAILURE; #if LONG_MAX < 0xffffffff while (data_offset > LONG_MAX) { if (fseek(stream, LONG_MAX, SEEK_CUR) != 0) { goto exit; } data_offset -= LONG_MAX; } #endif if (fseek(stream, data_offset, SEEK_CUR) != 0) { goto exit; } n = fread(p_data, 1, data_length, stream); if (n != data_length) { goto exit; } status = PSA_SUCCESS; if (p_data_length != NULL) { *p_data_length = n; } exit: if (stream != NULL) { fclose(stream); } return status; } psa_status_t psa_its_set(psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) { if (uid == 0) { return PSA_ERROR_INVALID_HANDLE; } psa_status_t status = PSA_ERROR_STORAGE_FAILURE; char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; FILE *stream = NULL; psa_its_file_header_t header; size_t n; memcpy(header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH); MBEDTLS_PUT_UINT32_LE(data_length, header.size, 0); MBEDTLS_PUT_UINT32_LE(create_flags, header.flags, 0); psa_its_fill_filename(uid, filename); stream = fopen(PSA_ITS_STORAGE_TEMP, "wb"); if (stream == NULL) { goto exit; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(stream, NULL); status = PSA_ERROR_INSUFFICIENT_STORAGE; n = fwrite(&header, 1, sizeof(header), stream); if (n != sizeof(header)) { goto exit; } if (data_length != 0) { n = fwrite(p_data, 1, data_length, stream); if (n != data_length) { goto exit; } } status = PSA_SUCCESS; exit: if (stream != NULL) { int ret = fclose(stream); if (status == PSA_SUCCESS && ret != 0) { status = PSA_ERROR_INSUFFICIENT_STORAGE; } } if (status == PSA_SUCCESS) { if (rename_replace_existing(PSA_ITS_STORAGE_TEMP, filename) != 0) { status = PSA_ERROR_STORAGE_FAILURE; } } /* The temporary file may still exist, but only in failure cases where * we're already reporting an error. So there's nothing we can do on * failure. If the function succeeded, and in some error cases, the * temporary file doesn't exist and so remove() is expected to fail. * Thus we just ignore the return status of remove(). */ (void) remove(PSA_ITS_STORAGE_TEMP); return status; } psa_status_t psa_its_remove(psa_storage_uid_t uid) { char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; FILE *stream; psa_its_fill_filename(uid, filename); stream = fopen(filename, "rb"); if (stream == NULL) { return PSA_ERROR_DOES_NOT_EXIST; } fclose(stream); if (remove(filename) != 0) { return PSA_ERROR_STORAGE_FAILURE; } return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_ITS_FILE_C */ webfakes/src/mbedtls/library/psa_crypto_driver_wrappers_no_static.h0000644000176200001440000000175614740737024025644 0ustar liggesusers/* * Function signatures for functionality that can be provided by * cryptographic accelerators. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H #define PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H #include "psa/crypto.h" #include "psa/crypto_driver_common.h" psa_status_t psa_driver_wrapper_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); psa_status_t psa_driver_wrapper_get_key_buffer_size( const psa_key_attributes_t *attributes, size_t *key_buffer_size); psa_status_t psa_driver_wrapper_get_builtin_key( psa_drv_slot_number_t slot_number, psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); #endif /* PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H */ /* End of automatically generated file. */ webfakes/src/mbedtls/library/platform.c0000644000176200001440000002525314740737024017735 0ustar liggesusers/* * Platform abstraction layer * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" /* The compile time configuration of memory allocation via the macros * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime * configuration via mbedtls_platform_set_calloc_free(). So, omit everything * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ #if defined(MBEDTLS_PLATFORM_MEMORY) && \ !(defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ defined(MBEDTLS_PLATFORM_FREE_MACRO)) #if !defined(MBEDTLS_PLATFORM_STD_CALLOC) static void *platform_calloc_uninit(size_t n, size_t size) { ((void) n); ((void) size); return NULL; } #define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit #endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ #if !defined(MBEDTLS_PLATFORM_STD_FREE) static void platform_free_uninit(void *ptr) { ((void) ptr); } #define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit #endif /* !MBEDTLS_PLATFORM_STD_FREE */ static void * (*mbedtls_calloc_func)(size_t, size_t) = MBEDTLS_PLATFORM_STD_CALLOC; static void (*mbedtls_free_func)(void *) = MBEDTLS_PLATFORM_STD_FREE; void *mbedtls_calloc(size_t nmemb, size_t size) { return (*mbedtls_calloc_func)(nmemb, size); } void mbedtls_free(void *ptr) { (*mbedtls_free_func)(ptr); } int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t), void (*free_func)(void *)) { mbedtls_calloc_func = calloc_func; mbedtls_free_func = free_func; return 0; } #endif /* MBEDTLS_PLATFORM_MEMORY && !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) #include int mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; va_list argp; va_start(argp, fmt); ret = mbedtls_vsnprintf(s, n, fmt, argp); va_end(argp); return ret; } #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_snprintf_uninit(char *s, size_t n, const char *format, ...) { ((void) s); ((void) n); ((void) format); return 0; } #define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit #endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ int (*mbedtls_snprintf)(char *s, size_t n, const char *format, ...) = MBEDTLS_PLATFORM_STD_SNPRINTF; int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n, const char *format, ...)) { mbedtls_snprintf = snprintf_func; return 0; } #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) #include int mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, va_list arg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Avoid calling the invalid parameter handler by checking ourselves */ if (s == NULL || n == 0 || fmt == NULL) { return -1; } #if defined(_TRUNCATE) ret = vsnprintf_s(s, n, _TRUNCATE, fmt, arg); #else ret = vsnprintf(s, n, fmt, arg); if (ret < 0 || (size_t) ret == n) { s[n-1] = '\0'; ret = -1; } #endif return ret; } #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_vsnprintf_uninit(char *s, size_t n, const char *format, va_list arg) { ((void) s); ((void) n); ((void) format); ((void) arg); return -1; } #define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit #endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */ int (*mbedtls_vsnprintf)(char *s, size_t n, const char *format, va_list arg) = MBEDTLS_PLATFORM_STD_VSNPRINTF; int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n, const char *format, va_list arg)) { mbedtls_vsnprintf = vsnprintf_func; return 0; } #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_PRINTF) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_printf_uninit(const char *format, ...) { ((void) format); return 0; } #define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit #endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ int (*mbedtls_printf)(const char *, ...) = MBEDTLS_PLATFORM_STD_PRINTF; int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...)) { mbedtls_printf = printf_func; return 0; } #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_fprintf_uninit(FILE *stream, const char *format, ...) { ((void) stream); ((void) format); return 0; } #define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit #endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ int (*mbedtls_fprintf)(FILE *, const char *, ...) = MBEDTLS_PLATFORM_STD_FPRINTF; int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *, const char *, ...)) { mbedtls_fprintf = fprintf_func; return 0; } #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_SETBUF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_SETBUF) /* * Make dummy function to prevent NULL pointer dereferences */ static void platform_setbuf_uninit(FILE *stream, char *buf) { ((void) stream); ((void) buf); } #define MBEDTLS_PLATFORM_STD_SETBUF platform_setbuf_uninit #endif /* !MBEDTLS_PLATFORM_STD_SETBUF */ void (*mbedtls_setbuf)(FILE *stream, char *buf) = MBEDTLS_PLATFORM_STD_SETBUF; int mbedtls_platform_set_setbuf(void (*setbuf_func)(FILE *stream, char *buf)) { mbedtls_setbuf = setbuf_func; return 0; } #endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ #if defined(MBEDTLS_PLATFORM_EXIT_ALT) #if !defined(MBEDTLS_PLATFORM_STD_EXIT) /* * Make dummy function to prevent NULL pointer dereferences */ static void platform_exit_uninit(int status) { ((void) status); } #define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit #endif /* !MBEDTLS_PLATFORM_STD_EXIT */ void (*mbedtls_exit)(int status) = MBEDTLS_PLATFORM_STD_EXIT; int mbedtls_platform_set_exit(void (*exit_func)(int status)) { mbedtls_exit = exit_func; return 0; } #endif /* MBEDTLS_PLATFORM_EXIT_ALT */ #if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_PLATFORM_TIME_ALT) #if !defined(MBEDTLS_PLATFORM_STD_TIME) /* * Make dummy function to prevent NULL pointer dereferences */ static mbedtls_time_t platform_time_uninit(mbedtls_time_t *timer) { ((void) timer); return 0; } #define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit #endif /* !MBEDTLS_PLATFORM_STD_TIME */ mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *timer) = MBEDTLS_PLATFORM_STD_TIME; int mbedtls_platform_set_time(mbedtls_time_t (*time_func)(mbedtls_time_t *timer)) { mbedtls_time = time_func; return 0; } #endif /* MBEDTLS_PLATFORM_TIME_ALT */ #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_ENTROPY_NV_SEED) #if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) /* Default implementations for the platform independent seed functions use * standard libc file functions to read from and write to a pre-defined filename */ int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len) { FILE *file; size_t n; if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb")) == NULL) { return -1; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(file, NULL); if ((n = fread(buf, 1, buf_len, file)) != buf_len) { fclose(file); mbedtls_platform_zeroize(buf, buf_len); return -1; } fclose(file); return (int) n; } int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len) { FILE *file; size_t n; if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w")) == NULL) { return -1; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(file, NULL); if ((n = fwrite(buf, 1, buf_len, file)) != buf_len) { fclose(file); return -1; } fclose(file); return (int) n; } #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_nv_seed_read_uninit(unsigned char *buf, size_t buf_len) { ((void) buf); ((void) buf_len); return -1; } #define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit #endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_nv_seed_write_uninit(unsigned char *buf, size_t buf_len) { ((void) buf); ((void) buf_len); return -1; } #define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit #endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len) = MBEDTLS_PLATFORM_STD_NV_SEED_READ; int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len) = MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; int mbedtls_platform_set_nv_seed( int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len), int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len)) { mbedtls_nv_seed_read = nv_seed_read_func; mbedtls_nv_seed_write = nv_seed_write_func; return 0; } #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) /* * Placeholder platform setup that does nothing by default */ int mbedtls_platform_setup(mbedtls_platform_context *ctx) { (void) ctx; return 0; } /* * Placeholder platform teardown that does nothing by default */ void mbedtls_platform_teardown(mbedtls_platform_context *ctx) { (void) ctx; } #endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ #endif /* MBEDTLS_PLATFORM_C */ webfakes/src/mbedtls/library/ecdsa.c0000644000176200001440000006515614740737024017176 0ustar liggesusers/* * Elliptic curve DSA * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * SEC1 https://www.secg.org/sec1-v2.pdf */ #include "common.h" #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #include "mbedtls/asn1write.h" #include #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #include "mbedtls/hmac_drbg.h" #endif #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Sub-context for ecdsa_verify() */ struct mbedtls_ecdsa_restart_ver { mbedtls_mpi u1, u2; /* intermediate values */ enum { /* what to do next? */ ecdsa_ver_init = 0, /* getting started */ ecdsa_ver_muladd, /* muladd step */ } state; }; /* * Init verify restart sub-context */ static void ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx *ctx) { mbedtls_mpi_init(&ctx->u1); mbedtls_mpi_init(&ctx->u2); ctx->state = ecdsa_ver_init; } /* * Free the components of a verify restart sub-context */ static void ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_mpi_free(&ctx->u1); mbedtls_mpi_free(&ctx->u2); ecdsa_restart_ver_init(ctx); } /* * Sub-context for ecdsa_sign() */ struct mbedtls_ecdsa_restart_sig { int sign_tries; int key_tries; mbedtls_mpi k; /* per-signature random */ mbedtls_mpi r; /* r value */ enum { /* what to do next? */ ecdsa_sig_init = 0, /* getting started */ ecdsa_sig_mul, /* doing ecp_mul() */ ecdsa_sig_modn, /* mod N computations */ } state; }; /* * Init verify sign sub-context */ static void ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx *ctx) { ctx->sign_tries = 0; ctx->key_tries = 0; mbedtls_mpi_init(&ctx->k); mbedtls_mpi_init(&ctx->r); ctx->state = ecdsa_sig_init; } /* * Free the components of a sign restart sub-context */ static void ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_mpi_free(&ctx->k); mbedtls_mpi_free(&ctx->r); } #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* * Sub-context for ecdsa_sign_det() */ struct mbedtls_ecdsa_restart_det { mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ enum { /* what to do next? */ ecdsa_det_init = 0, /* getting started */ ecdsa_det_sign, /* make signature */ } state; }; /* * Init verify sign_det sub-context */ static void ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx *ctx) { mbedtls_hmac_drbg_init(&ctx->rng_ctx); ctx->state = ecdsa_det_init; } /* * Free the components of a sign_det restart sub-context */ static void ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_hmac_drbg_free(&ctx->rng_ctx); ecdsa_restart_det_init(ctx); } #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #define ECDSA_RS_ECP (rs_ctx == NULL ? NULL : &rs_ctx->ecp) /* Utility macro for checking and updating ops budget */ #define ECDSA_BUDGET(ops) \ MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, ECDSA_RS_ECP, ops)); /* Call this when entering a function that needs its own sub-context */ #define ECDSA_RS_ENTER(SUB) do { \ /* reset ops count for this call if top-level */ \ if (rs_ctx != NULL && rs_ctx->ecp.depth++ == 0) \ rs_ctx->ecp.ops_done = 0; \ \ /* set up our own sub-context if needed */ \ if (mbedtls_ecp_restart_is_enabled() && \ rs_ctx != NULL && rs_ctx->SUB == NULL) \ { \ rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB)); \ if (rs_ctx->SUB == NULL) \ return MBEDTLS_ERR_ECP_ALLOC_FAILED; \ \ ecdsa_restart_## SUB ##_init(rs_ctx->SUB); \ } \ } while (0) /* Call this when leaving a function that needs its own sub-context */ #define ECDSA_RS_LEAVE(SUB) do { \ /* clear our sub-context when not in progress (done or error) */ \ if (rs_ctx != NULL && rs_ctx->SUB != NULL && \ ret != MBEDTLS_ERR_ECP_IN_PROGRESS) \ { \ ecdsa_restart_## SUB ##_free(rs_ctx->SUB); \ mbedtls_free(rs_ctx->SUB); \ rs_ctx->SUB = NULL; \ } \ \ if (rs_ctx != NULL) \ rs_ctx->ecp.depth--; \ } while (0) #else /* MBEDTLS_ECP_RESTARTABLE */ #define ECDSA_RS_ECP NULL #define ECDSA_BUDGET(ops) /* no-op; for compatibility */ #define ECDSA_RS_ENTER(SUB) (void) rs_ctx #define ECDSA_RS_LEAVE(SUB) (void) rs_ctx #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \ !defined(MBEDTLS_ECDSA_SIGN_ALT) || \ !defined(MBEDTLS_ECDSA_VERIFY_ALT) /* * Derive a suitable integer for group grp from a buffer of length len * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 */ static int derive_mpi(const mbedtls_ecp_group *grp, mbedtls_mpi *x, const unsigned char *buf, size_t blen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n_size = (grp->nbits + 7) / 8; size_t use_size = blen > n_size ? n_size : blen; MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(x, buf, use_size)); if (use_size * 8 > grp->nbits) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(x, use_size * 8 - grp->nbits)); } /* While at it, reduce modulo N */ if (mbedtls_mpi_cmp_mpi(x, &grp->N) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(x, x, &grp->N)); } cleanup: return ret; } #endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */ int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid) { switch (gid) { #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED case MBEDTLS_ECP_DP_CURVE25519: return 0; #endif #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED case MBEDTLS_ECP_DP_CURVE448: return 0; #endif default: return 1; } } #if !defined(MBEDTLS_ECDSA_SIGN_ALT) /* * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) */ int mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret, key_tries, sign_tries; int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; mbedtls_mpi *pk = &k, *pr = r; /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Make sure d is in range 1..n-1 */ if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } mbedtls_ecp_point_init(&R); mbedtls_mpi_init(&k); mbedtls_mpi_init(&e); mbedtls_mpi_init(&t); ECDSA_RS_ENTER(sig); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->sig != NULL) { /* redirect to our context */ p_sign_tries = &rs_ctx->sig->sign_tries; p_key_tries = &rs_ctx->sig->key_tries; pk = &rs_ctx->sig->k; pr = &rs_ctx->sig->r; /* jump to current step */ if (rs_ctx->sig->state == ecdsa_sig_mul) { goto mul; } if (rs_ctx->sig->state == ecdsa_sig_modn) { goto modn; } } #endif /* MBEDTLS_ECP_RESTARTABLE */ *p_sign_tries = 0; do { if ((*p_sign_tries)++ > 10) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } /* * Steps 1-3: generate a suitable ephemeral keypair * and set r = xR mod n */ *p_key_tries = 0; do { if ((*p_key_tries)++ > 10) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, pk, f_rng, p_rng)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->sig != NULL) { rs_ctx->sig->state = ecdsa_sig_mul; } mul: #endif MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &R, pk, &grp->G, f_rng_blind, p_rng_blind, ECDSA_RS_ECP)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pr, &R.X, &grp->N)); } while (mbedtls_mpi_cmp_int(pr, 0) == 0); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->sig != NULL) { rs_ctx->sig->state = ecdsa_sig_modn; } modn: #endif /* * Accounting for everything up to the end of the loop * (step 6, but checking now avoids saving e and t) */ ECDSA_BUDGET(MBEDTLS_ECP_OPS_INV + 4); /* * Step 5: derive MPI from hashed message */ MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen)); /* * Generate a random value to blind inv_mod in next step, * avoiding a potential timing leak. */ MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, &t, f_rng_blind, p_rng_blind)); /* * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, pr, d)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&e, &e, s)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&e, &e, &t)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pk, pk, &t)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pk, pk, &grp->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(s, pk, &grp->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, s, &e)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(s, s, &grp->N)); } while (mbedtls_mpi_cmp_int(s, 0) == 0); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->sig != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr)); } #endif cleanup: mbedtls_ecp_point_free(&R); mbedtls_mpi_free(&k); mbedtls_mpi_free(&e); mbedtls_mpi_free(&t); ECDSA_RS_LEAVE(sig); return ret; } /* * Compute ECDSA signature of a hashed message */ int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { /* Use the same RNG for both blinding and ephemeral key generation */ return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, f_rng, p_rng, f_rng, p_rng, NULL); } #endif /* !MBEDTLS_ECDSA_SIGN_ALT */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* * Deterministic signature wrapper * * note: The f_rng_blind parameter must not be NULL. * */ int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_hmac_drbg_context rng_ctx; mbedtls_hmac_drbg_context *p_rng = &rng_ctx; unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; size_t grp_len = (grp->nbits + 7) / 8; const mbedtls_md_info_t *md_info; mbedtls_mpi h; if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } mbedtls_mpi_init(&h); mbedtls_hmac_drbg_init(&rng_ctx); ECDSA_RS_ENTER(det); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->det != NULL) { /* redirect to our context */ p_rng = &rs_ctx->det->rng_ctx; /* jump to current step */ if (rs_ctx->det->state == ecdsa_det_sign) { goto sign; } } #endif /* MBEDTLS_ECP_RESTARTABLE */ /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len)); MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len)); MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->det != NULL) { rs_ctx->det->state = ecdsa_det_sign; } sign: #endif #if defined(MBEDTLS_ECDSA_SIGN_ALT) (void) f_rng_blind; (void) p_rng_blind; ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, p_rng); #else ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, p_rng, f_rng_blind, p_rng_blind, rs_ctx); #endif /* MBEDTLS_ECDSA_SIGN_ALT */ cleanup: mbedtls_hmac_drbg_free(&rng_ctx); mbedtls_mpi_free(&h); ECDSA_RS_LEAVE(det); return ret; } /* * Deterministic signature wrapper */ int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind) { return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg, f_rng_blind, p_rng_blind, NULL); } #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #if !defined(MBEDTLS_ECDSA_VERIFY_ALT) /* * Verify ECDSA signature of hashed message (SEC1 4.1.4) * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) */ int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi e, s_inv, u1, u2; mbedtls_ecp_point R; mbedtls_mpi *pu1 = &u1, *pu2 = &u2; mbedtls_ecp_point_init(&R); mbedtls_mpi_init(&e); mbedtls_mpi_init(&s_inv); mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2); /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } ECDSA_RS_ENTER(ver); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ver != NULL) { /* redirect to our context */ pu1 = &rs_ctx->ver->u1; pu2 = &rs_ctx->ver->u2; /* jump to current step */ if (rs_ctx->ver->state == ecdsa_ver_muladd) { goto muladd; } } #endif /* MBEDTLS_ECP_RESTARTABLE */ /* * Step 1: make sure r and s are in range 1..n-1 */ if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 || mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } /* * Step 3: derive MPI from hashed message */ MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen)); /* * Step 4: u1 = e / s mod n, u2 = r / s mod n */ ECDSA_BUDGET(MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2); MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&s_inv, s, &grp->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu1, &e, &s_inv)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu1, pu1, &grp->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu2, r, &s_inv)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu2, pu2, &grp->N)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ver != NULL) { rs_ctx->ver->state = ecdsa_ver_muladd; } muladd: #endif /* * Step 5: R = u1 G + u2 Q */ MBEDTLS_MPI_CHK(mbedtls_ecp_muladd_restartable(grp, &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP)); if (mbedtls_ecp_is_zero(&R)) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } /* * Step 6: convert xR to an integer (no-op) * Step 7: reduce xR mod n (gives v) */ MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&R.X, &R.X, &grp->N)); /* * Step 8: check if v (that is, R.X) is equal to r */ if (mbedtls_mpi_cmp_mpi(&R.X, r) != 0) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } cleanup: mbedtls_ecp_point_free(&R); mbedtls_mpi_free(&e); mbedtls_mpi_free(&s_inv); mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2); ECDSA_RS_LEAVE(ver); return ret; } /* * Verify ECDSA signature of hashed message */ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) { return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL); } #endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ /* * Convert a signature (given by context) to ASN.1 */ static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, unsigned char *sig, size_t sig_size, size_t *slen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 }; unsigned char *p = buf + sizeof(buf); size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); if (len > sig_size) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } memcpy(sig, p, len); *slen = len; return 0; } /* * Compute and write signature */ int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi r, s; if (f_rng == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); #if defined(MBEDTLS_ECDSA_DETERMINISTIC) MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d, hash, hlen, md_alg, f_rng, p_rng, rs_ctx)); #else (void) md_alg; #if defined(MBEDTLS_ECDSA_SIGN_ALT) (void) rs_ctx; MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng)); #else /* Use the same RNG for both blinding and ephemeral key generation */ MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng, f_rng, p_rng, rs_ctx)); #endif /* MBEDTLS_ECDSA_SIGN_ALT */ #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen)); cleanup: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); return ret; } /* * Compute and write signature */ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecdsa_write_signature_restartable( ctx, md_alg, hash, hlen, sig, sig_size, slen, f_rng, p_rng, NULL); } /* * Read and check signature */ int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen) { return mbedtls_ecdsa_read_signature_restartable( ctx, hash, hlen, sig, slen, NULL); } /* * Restartable read and check signature */ int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = (unsigned char *) sig; const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } if (p + len != end) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); goto cleanup; } if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 || (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } #if defined(MBEDTLS_ECDSA_VERIFY_ALT) (void) rs_ctx; if ((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen, &ctx->Q, &r, &s)) != 0) { goto cleanup; } #else if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen, &ctx->Q, &r, &s, rs_ctx)) != 0) { goto cleanup; } #endif /* MBEDTLS_ECDSA_VERIFY_ALT */ /* At this point we know that the buffer starts with a valid signature. * Return 0 if the buffer just contains the signature, and a specific * error code if the valid signature is followed by more data. */ if (p != end) { ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; } cleanup: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); return ret; } #if !defined(MBEDTLS_ECDSA_GENKEY_ALT) /* * Generate key pair */ int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = 0; ret = mbedtls_ecp_group_load(&ctx->grp, gid); if (ret != 0) { return ret; } return mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng); } #endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ /* * Set context from an mbedtls_ecp_keypair */ int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 || (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 || (ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) { mbedtls_ecdsa_free(ctx); } return ret; } /* * Initialize context */ void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx) { mbedtls_ecp_keypair_init(ctx); } /* * Free context */ void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx) { if (ctx == NULL) { return; } mbedtls_ecp_keypair_free(ctx); } #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Initialize a restart context */ void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx) { mbedtls_ecp_restart_init(&ctx->ecp); ctx->ver = NULL; ctx->sig = NULL; #if defined(MBEDTLS_ECDSA_DETERMINISTIC) ctx->det = NULL; #endif } /* * Free the components of a restart context */ void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_ecp_restart_free(&ctx->ecp); ecdsa_restart_ver_free(ctx->ver); mbedtls_free(ctx->ver); ctx->ver = NULL; ecdsa_restart_sig_free(ctx->sig); mbedtls_free(ctx->sig); ctx->sig = NULL; #if defined(MBEDTLS_ECDSA_DETERMINISTIC) ecdsa_restart_det_free(ctx->det); mbedtls_free(ctx->det); ctx->det = NULL; #endif } #endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECDSA_C */ webfakes/src/mbedtls/library/gcm.c0000644000176200001440000012703414740737024016657 0ustar liggesusers/* * NIST SP800-38D compliant GCM implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf * * See also: * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf * * We use the algorithm described as Shoup's method with 4-bit tables in * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. */ #include "common.h" #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #include "block_cipher_internal.h" #endif #include #if defined(MBEDTLS_AESNI_C) #include "aesni.h" #endif #if defined(MBEDTLS_AESCE_C) #include "aesce.h" #endif #if !defined(MBEDTLS_GCM_ALT) /* Used to select the acceleration mechanism */ #define MBEDTLS_GCM_ACC_SMALLTABLE 0 #define MBEDTLS_GCM_ACC_LARGETABLE 1 #define MBEDTLS_GCM_ACC_AESNI 2 #define MBEDTLS_GCM_ACC_AESCE 3 /* * Initialize a context */ void mbedtls_gcm_init(mbedtls_gcm_context *ctx) { memset(ctx, 0, sizeof(mbedtls_gcm_context)); } static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx) { #if defined(MBEDTLS_GCM_LARGE_TABLE) ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE; #else ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE; #endif #if defined(MBEDTLS_AESNI_HAVE_CODE) /* With CLMUL support, we need only h, not the rest of the table */ if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { ctx->acceleration = MBEDTLS_GCM_ACC_AESNI; } #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { ctx->acceleration = MBEDTLS_GCM_ACC_AESCE; } #endif } static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2]) { uint8_t *u8Dst = (uint8_t *) dst; uint8_t *u8Src = (uint8_t *) src; MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0); u8Dst[8] |= (u8Src[7] & 0x01) << 7; MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0); u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0; } /* * Precompute small multiples of H, that is set * HH[i] || HL[i] = H times i, * where i is seen as a field element as in [MGV], ie high-order bits * correspond to low powers of P. The result is stored in the same way, that * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL * corresponds to P^127. */ static int gcm_gen_table(mbedtls_gcm_context *ctx) { int ret, i, j; uint64_t u64h[2] = { 0 }; uint8_t *h = (uint8_t *) u64h; #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h); #else size_t olen = 0; ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen); #endif if (ret != 0) { return ret; } gcm_set_acceleration(ctx); /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */ ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0]; ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1]; switch (ctx->acceleration) { #if defined(MBEDTLS_AESNI_HAVE_CODE) case MBEDTLS_GCM_ACC_AESNI: return 0; #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) case MBEDTLS_GCM_ACC_AESCE: return 0; #endif default: /* 0 corresponds to 0 in GF(2^128) */ ctx->H[0][0] = 0; ctx->H[0][1] = 0; for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) { gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]); } #if !defined(MBEDTLS_GCM_LARGE_TABLE) /* pack elements of H as 64-bits ints, big-endian */ for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) { MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0); MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0); } #endif for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) { for (j = 1; j < i; j++) { mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j], (unsigned char *) ctx->H[i], (unsigned char *) ctx->H[j], 16); } } } return 0; } int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (keybits != 128 && keybits != 192 && keybits != 256) { return MBEDTLS_ERR_GCM_BAD_INPUT; } #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_free(&ctx->block_cipher_ctx); if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) { return ret; } if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) { return ret; } #else const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, MBEDTLS_MODE_ECB); if (cipher_info == NULL) { return MBEDTLS_ERR_GCM_BAD_INPUT; } if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { return MBEDTLS_ERR_GCM_BAD_INPUT; } mbedtls_cipher_free(&ctx->cipher_ctx); if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { return ret; } if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, MBEDTLS_ENCRYPT)) != 0) { return ret; } #endif if ((ret = gcm_gen_table(ctx)) != 0) { return ret; } return 0; } #if defined(MBEDTLS_GCM_LARGE_TABLE) static const uint16_t last8[256] = { 0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05, 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b, 0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19, 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17, 0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d, 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33, 0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21, 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f, 0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75, 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b, 0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69, 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67, 0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d, 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43, 0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51, 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f, 0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4, 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea, 0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8, 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6, 0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc, 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2, 0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0, 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece, 0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94, 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a, 0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88, 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86, 0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac, 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2, 0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0, 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe }; static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2]) { int i; uint64_t u64z[2]; uint16_t *u16z = (uint16_t *) u64z; uint8_t *u8z = (uint8_t *) u64z; uint8_t rem; u64z[0] = 0; u64z[1] = 0; if (MBEDTLS_IS_BIG_ENDIAN) { for (i = 15; i > 0; i--) { mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16); rem = u8z[15]; u64z[1] >>= 8; u8z[8] = u8z[7]; u64z[0] >>= 8; u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0); } } else { for (i = 15; i > 0; i--) { mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16); rem = u8z[15]; u64z[1] <<= 8; u8z[8] = u8z[7]; u64z[0] <<= 8; u16z[0] ^= last8[rem]; } } mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16); } #else /* * Shoup's method for multiplication use this table with * last4[x] = x times P^128 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] */ static const uint16_t last4[16] = { 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0 }; static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2]) { int i = 0; unsigned char lo, hi, rem; uint64_t u64z[2]; const uint64_t *pu64z = NULL; uint8_t *u8z = (uint8_t *) u64z; lo = x[15] & 0xf; hi = (x[15] >> 4) & 0xf; pu64z = H[lo]; rem = (unsigned char) pu64z[1] & 0xf; u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4); u64z[0] = (pu64z[0] >> 4); u64z[0] ^= (uint64_t) last4[rem] << 48; mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16); for (i = 14; i >= 0; i--) { lo = x[i] & 0xf; hi = (x[i] >> 4) & 0xf; rem = (unsigned char) u64z[1] & 0xf; u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4); u64z[0] = (u64z[0] >> 4); u64z[0] ^= (uint64_t) last4[rem] << 48; mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16); rem = (unsigned char) u64z[1] & 0xf; u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4); u64z[0] = (u64z[0] >> 4); u64z[0] ^= (uint64_t) last4[rem] << 48; mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16); } MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0); MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8); } #endif /* * Sets output to x times H using the precomputed tables. * x and output are seen as elements of GF(2^128) as in [MGV]. */ static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16], unsigned char output[16]) { switch (ctx->acceleration) { #if defined(MBEDTLS_AESNI_HAVE_CODE) case MBEDTLS_GCM_ACC_AESNI: mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]); break; #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) case MBEDTLS_GCM_ACC_AESCE: mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]); break; #endif #if defined(MBEDTLS_GCM_LARGE_TABLE) case MBEDTLS_GCM_ACC_LARGETABLE: gcm_mult_largetable(output, x, ctx->H); break; #else case MBEDTLS_GCM_ACC_SMALLTABLE: gcm_mult_smalltable(output, x, ctx->H); break; #endif } return; } int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, int mode, const unsigned char *iv, size_t iv_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char work_buf[16]; const unsigned char *p; size_t use_len; uint64_t iv_bits; #if !defined(MBEDTLS_BLOCK_CIPHER_C) size_t olen = 0; #endif /* IV is limited to 2^64 bits, so 2^61 bytes */ /* IV is not allowed to be zero length */ if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) { return MBEDTLS_ERR_GCM_BAD_INPUT; } memset(ctx->y, 0x00, sizeof(ctx->y)); memset(ctx->buf, 0x00, sizeof(ctx->buf)); ctx->mode = mode; ctx->len = 0; ctx->add_len = 0; if (iv_len == 12) { memcpy(ctx->y, iv, iv_len); ctx->y[15] = 1; } else { memset(work_buf, 0x00, 16); iv_bits = (uint64_t) iv_len * 8; MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8); p = iv; while (iv_len > 0) { use_len = (iv_len < 16) ? iv_len : 16; #if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110) #pragma GCC diagnostic push #pragma GCC diagnostic warning "-Wstringop-overflow=0" #endif mbedtls_xor(ctx->y, ctx->y, p, use_len); #if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110) #pragma GCC diagnostic pop #endif gcm_mult(ctx, ctx->y, ctx->y); iv_len -= use_len; p += use_len; } mbedtls_xor(ctx->y, ctx->y, work_buf, 16); gcm_mult(ctx, ctx->y, ctx->y); } #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen); #endif if (ret != 0) { return ret; } return 0; } /** * mbedtls_gcm_context::buf contains the partial state of the computation of * the authentication tag. * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate * different stages of the computation: * * len == 0 && add_len == 0: initial state * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have * a partial block of AD that has been * xored in but not yet multiplied in. * * len == 0 && add_len % 16 == 0: the authentication tag is correct if * the data ends now. * * len % 16 != 0: the first `len % 16` bytes have * a partial block of ciphertext that has * been xored in but not yet multiplied in. * * len > 0 && len % 16 == 0: the authentication tag is correct if * the data ends now. */ int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx, const unsigned char *add, size_t add_len) { const unsigned char *p; size_t use_len, offset; uint64_t new_add_len; /* AD is limited to 2^64 bits, ie 2^61 bytes * Also check for possible overflow */ #if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL if (add_len > 0xFFFFFFFFFFFFFFFFULL) { return MBEDTLS_ERR_GCM_BAD_INPUT; } #endif new_add_len = ctx->add_len + (uint64_t) add_len; if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) { return MBEDTLS_ERR_GCM_BAD_INPUT; } offset = ctx->add_len % 16; p = add; if (offset != 0) { use_len = 16 - offset; if (use_len > add_len) { use_len = add_len; } mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len); if (offset + use_len == 16) { gcm_mult(ctx, ctx->buf, ctx->buf); } ctx->add_len += use_len; add_len -= use_len; p += use_len; } ctx->add_len += add_len; while (add_len >= 16) { mbedtls_xor(ctx->buf, ctx->buf, p, 16); gcm_mult(ctx, ctx->buf, ctx->buf); add_len -= 16; p += 16; } if (add_len > 0) { mbedtls_xor(ctx->buf, ctx->buf, p, add_len); } return 0; } /* Increment the counter. */ static void gcm_incr(unsigned char y[16]) { uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12); x++; MBEDTLS_PUT_UINT32_BE(x, y, 12); } /* Calculate and apply the encryption mask. Process use_len bytes of data, * starting at position offset in the mask block. */ static int gcm_mask(mbedtls_gcm_context *ctx, unsigned char ectr[16], size_t offset, size_t use_len, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr); #else size_t olen = 0; ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen); #endif if (ret != 0) { mbedtls_platform_zeroize(ectr, 16); return ret; } if (ctx->mode == MBEDTLS_GCM_DECRYPT) { mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len); } mbedtls_xor(output, ectr + offset, input, use_len); if (ctx->mode == MBEDTLS_GCM_ENCRYPT) { mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len); } return 0; } int mbedtls_gcm_update(mbedtls_gcm_context *ctx, const unsigned char *input, size_t input_length, unsigned char *output, size_t output_size, size_t *output_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = input; unsigned char *out_p = output; size_t offset; unsigned char ectr[16] = { 0 }; if (output_size < input_length) { return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL; } *output_length = input_length; /* Exit early if input_length==0 so that we don't do any pointer arithmetic * on a potentially null pointer. * Returning early also means that the last partial block of AD remains * untouched for mbedtls_gcm_finish */ if (input_length == 0) { return 0; } if (output > input && (size_t) (output - input) < input_length) { return MBEDTLS_ERR_GCM_BAD_INPUT; } /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes * Also check for possible overflow */ if (ctx->len + input_length < ctx->len || (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) { return MBEDTLS_ERR_GCM_BAD_INPUT; } if (ctx->len == 0 && ctx->add_len % 16 != 0) { gcm_mult(ctx, ctx->buf, ctx->buf); } offset = ctx->len % 16; if (offset != 0) { size_t use_len = 16 - offset; if (use_len > input_length) { use_len = input_length; } if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) { return ret; } if (offset + use_len == 16) { gcm_mult(ctx, ctx->buf, ctx->buf); } ctx->len += use_len; input_length -= use_len; p += use_len; out_p += use_len; } ctx->len += input_length; while (input_length >= 16) { gcm_incr(ctx->y); if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) { return ret; } gcm_mult(ctx, ctx->buf, ctx->buf); input_length -= 16; p += 16; out_p += 16; } if (input_length > 0) { gcm_incr(ctx->y); if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) { return ret; } } mbedtls_platform_zeroize(ectr, sizeof(ectr)); return 0; } int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, unsigned char *output, size_t output_size, size_t *output_length, unsigned char *tag, size_t tag_len) { unsigned char work_buf[16]; uint64_t orig_len; uint64_t orig_add_len; /* We never pass any output in finish(). The output parameter exists only * for the sake of alternative implementations. */ (void) output; (void) output_size; *output_length = 0; /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of * the two multiplications would overflow. */ orig_len = ctx->len * 8; orig_add_len = ctx->add_len * 8; if (ctx->len == 0 && ctx->add_len % 16 != 0) { gcm_mult(ctx, ctx->buf, ctx->buf); } if (tag_len > 16 || tag_len < 4) { return MBEDTLS_ERR_GCM_BAD_INPUT; } if (ctx->len % 16 != 0) { gcm_mult(ctx, ctx->buf, ctx->buf); } memcpy(tag, ctx->base_ectr, tag_len); if (orig_len || orig_add_len) { memset(work_buf, 0x00, 16); MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0); MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4); MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8); MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12); mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16); gcm_mult(ctx, ctx->buf, ctx->buf); mbedtls_xor(tag, tag, ctx->buf, tag_len); } return 0; } int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx, int mode, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, size_t tag_len, unsigned char *tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) { return ret; } if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) { return ret; } if ((ret = mbedtls_gcm_update(ctx, input, length, output, length, &olen)) != 0) { return ret; } if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) { return ret; } return 0; } int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *tag, size_t tag_len, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char check_tag[16]; int diff; if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag)) != 0) { return ret; } /* Check tag in "constant-time" */ diff = mbedtls_ct_memcmp(tag, check_tag, tag_len); if (diff != 0) { mbedtls_platform_zeroize(output, length); return MBEDTLS_ERR_GCM_AUTH_FAILED; } return 0; } void mbedtls_gcm_free(mbedtls_gcm_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_free(&ctx->block_cipher_ctx); #else mbedtls_cipher_free(&ctx->cipher_ctx); #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context)); } #endif /* !MBEDTLS_GCM_ALT */ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) /* * AES-GCM test vectors from: * * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip */ #define MAX_TESTS 6 static const int key_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 }; static const unsigned char key_test_data[][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, }; static const size_t iv_len_test_data[MAX_TESTS] = { 12, 12, 12, 12, 8, 60 }; static const int iv_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 2 }; static const unsigned char iv_test_data[][64] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }, { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, 0xa6, 0x37, 0xb3, 0x9b }, }; static const size_t add_len_test_data[MAX_TESTS] = { 0, 0, 0, 20, 20, 20 }; static const int add_index_test_data[MAX_TESTS] = { 0, 0, 0, 1, 1, 1 }; static const unsigned char additional_test_data[][64] = { { 0x00 }, { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }, }; static const size_t pt_len_test_data[MAX_TESTS] = { 0, 16, 64, 60, 60, 60 }; static const int pt_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 }; static const unsigned char pt_test_data[][64] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, }; static const unsigned char ct_test_data[][64] = { { 0x00 }, { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91 }, { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, 0xc2, 0x3f, 0x45, 0x98 }, { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, 0x4c, 0x34, 0xae, 0xe5 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x00 }, { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 0xcc, 0xda, 0x27, 0x10 }, { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, 0xa0, 0xf0, 0x62, 0xf7 }, { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, 0xe9, 0xb7, 0x37, 0x3b }, { 0x00 }, { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62 }, { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, 0xf4, 0x7c, 0x9b, 0x1f }, { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, 0x44, 0xae, 0x7e, 0x3f }, #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ }; static const unsigned char tag_test_data[][16] = { { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ }; int mbedtls_gcm_self_test(int verbose) { mbedtls_gcm_context ctx; unsigned char buf[64]; unsigned char tag_buf[16]; int i, j, ret; mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; size_t olen; if (verbose != 0) { #if defined(MBEDTLS_GCM_ALT) mbedtls_printf(" GCM note: alternative implementation.\n"); #else /* MBEDTLS_GCM_ALT */ #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { mbedtls_printf(" GCM note: using AESNI.\n"); } else #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { mbedtls_printf(" GCM note: using AESCE.\n"); } else #endif mbedtls_printf(" GCM note: built-in implementation.\n"); #endif /* MBEDTLS_GCM_ALT */ } static const int loop_limit = (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS; for (j = 0; j < loop_limit; j++) { int key_len = 128 + 64 * j; for (i = 0; i < MAX_TESTS; i++) { if (verbose != 0) { mbedtls_printf(" AES-GCM-%3d #%d (%s): ", key_len, i, "enc"); } mbedtls_gcm_init(&ctx); ret = mbedtls_gcm_setkey(&ctx, cipher, key_test_data[key_index_test_data[i]], key_len); /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) { mbedtls_printf("skipped\n"); break; } else if (ret != 0) { goto exit; } ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT, pt_len_test_data[i], iv_test_data[iv_index_test_data[i]], iv_len_test_data[i], additional_test_data[add_index_test_data[i]], add_len_test_data[i], pt_test_data[pt_index_test_data[i]], buf, 16, tag_buf); #if defined(MBEDTLS_GCM_ALT) /* Allow alternative implementations to only support 12-byte nonces. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && iv_len_test_data[i] != 12) { mbedtls_printf("skipped\n"); break; } #endif /* defined(MBEDTLS_GCM_ALT) */ if (ret != 0) { goto exit; } if (memcmp(buf, ct_test_data[j * 6 + i], pt_len_test_data[i]) != 0 || memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { ret = 1; goto exit; } mbedtls_gcm_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } mbedtls_gcm_init(&ctx); if (verbose != 0) { mbedtls_printf(" AES-GCM-%3d #%d (%s): ", key_len, i, "dec"); } ret = mbedtls_gcm_setkey(&ctx, cipher, key_test_data[key_index_test_data[i]], key_len); if (ret != 0) { goto exit; } ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT, pt_len_test_data[i], iv_test_data[iv_index_test_data[i]], iv_len_test_data[i], additional_test_data[add_index_test_data[i]], add_len_test_data[i], ct_test_data[j * 6 + i], buf, 16, tag_buf); if (ret != 0) { goto exit; } if (memcmp(buf, pt_test_data[pt_index_test_data[i]], pt_len_test_data[i]) != 0 || memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { ret = 1; goto exit; } mbedtls_gcm_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } mbedtls_gcm_init(&ctx); if (verbose != 0) { mbedtls_printf(" AES-GCM-%3d #%d split (%s): ", key_len, i, "enc"); } ret = mbedtls_gcm_setkey(&ctx, cipher, key_test_data[key_index_test_data[i]], key_len); if (ret != 0) { goto exit; } ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT, iv_test_data[iv_index_test_data[i]], iv_len_test_data[i]); if (ret != 0) { goto exit; } ret = mbedtls_gcm_update_ad(&ctx, additional_test_data[add_index_test_data[i]], add_len_test_data[i]); if (ret != 0) { goto exit; } if (pt_len_test_data[i] > 32) { size_t rest_len = pt_len_test_data[i] - 32; ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]], 32, buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } if (olen != 32) { goto exit; } ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]] + 32, rest_len, buf + 32, sizeof(buf) - 32, &olen); if (ret != 0) { goto exit; } if (olen != rest_len) { goto exit; } } else { ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]], pt_len_test_data[i], buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } if (olen != pt_len_test_data[i]) { goto exit; } } ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16); if (ret != 0) { goto exit; } if (memcmp(buf, ct_test_data[j * 6 + i], pt_len_test_data[i]) != 0 || memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { ret = 1; goto exit; } mbedtls_gcm_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } mbedtls_gcm_init(&ctx); if (verbose != 0) { mbedtls_printf(" AES-GCM-%3d #%d split (%s): ", key_len, i, "dec"); } ret = mbedtls_gcm_setkey(&ctx, cipher, key_test_data[key_index_test_data[i]], key_len); if (ret != 0) { goto exit; } ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv_test_data[iv_index_test_data[i]], iv_len_test_data[i]); if (ret != 0) { goto exit; } ret = mbedtls_gcm_update_ad(&ctx, additional_test_data[add_index_test_data[i]], add_len_test_data[i]); if (ret != 0) { goto exit; } if (pt_len_test_data[i] > 32) { size_t rest_len = pt_len_test_data[i] - 32; ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i], 32, buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } if (olen != 32) { goto exit; } ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i] + 32, rest_len, buf + 32, sizeof(buf) - 32, &olen); if (ret != 0) { goto exit; } if (olen != rest_len) { goto exit; } } else { ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i], pt_len_test_data[i], buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } if (olen != pt_len_test_data[i]) { goto exit; } } ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16); if (ret != 0) { goto exit; } if (memcmp(buf, pt_test_data[pt_index_test_data[i]], pt_len_test_data[i]) != 0 || memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { ret = 1; goto exit; } mbedtls_gcm_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } } } if (verbose != 0) { mbedtls_printf("\n"); } ret = 0; exit: if (ret != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } mbedtls_gcm_free(&ctx); } return ret; } #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_GCM_C */ webfakes/src/mbedtls/library/psa_crypto_client.c0000644000176200001440000000066214740737024021627 0ustar liggesusers/* * PSA crypto client code */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "psa/crypto.h" #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include #include "mbedtls/platform.h" void psa_reset_key_attributes(psa_key_attributes_t *attributes) { memset(attributes, 0, sizeof(*attributes)); } #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ webfakes/src/mbedtls/library/pkwrite.c0000644000176200001440000005035514740737024017577 0ustar liggesusers/* * Public Key layer for writing key files and structures * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PK_WRITE_C) #include "mbedtls/pk.h" #include "mbedtls/asn1write.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "pk_internal.h" #include #if defined(MBEDTLS_ECP_C) #include "mbedtls/bignum.h" #include "mbedtls/ecp.h" #include "mbedtls/platform_util.h" #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #include "pk_internal.h" #endif #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS) #include "pkwrite.h" #endif #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_RSA_C) #include "rsa_internal.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "psa_util_internal.h" #endif #include "mbedtls/platform.h" /* Helpers for properly sizing buffers aimed at holding public keys or * key-pairs based on build symbols. */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) #define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH #elif defined(MBEDTLS_USE_PSA_CRYPTO) #define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH #else #define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_ECP_MAX_PT_LEN #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_ECP_MAX_BYTES #endif /****************************************************************************** * Internal functions for RSA keys. ******************************************************************************/ #if defined(MBEDTLS_RSA_C) static int pk_write_rsa_der(unsigned char **p, unsigned char *buf, const mbedtls_pk_context *pk) { #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE]; size_t tmp_len = 0; if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } /* Ensure there's enough space in the provided buffer before copying data into it. */ if (tmp_len > (size_t) (*p - buf)) { mbedtls_platform_zeroize(tmp, sizeof(tmp)); return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *p -= tmp_len; memcpy(*p, tmp, tmp_len); mbedtls_platform_zeroize(tmp, sizeof(tmp)); return (int) tmp_len; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p); } #endif /* MBEDTLS_RSA_C */ /****************************************************************************** * Internal functions for EC keys. ******************************************************************************/ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t len = 0; uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE]; if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } } else { len = pk->pub_raw_len; memcpy(buf, pk->pub_raw, len); } if (*p < start || (size_t) (*p - start) < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *p -= len; memcpy(*p, buf, len); return (int) len; } #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t len = 0; unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE]; mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk); int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } /* Ensure there's enough space in the provided buffer before copying data into it. */ if (len > (size_t) (*p - start)) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *p -= len; memcpy(*p, buf, len); return (int) len; } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ { if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &len, buf, sizeof(buf))) != 0) { return ret; } } if (*p < start || (size_t) (*p - start) < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *p -= len; memcpy(*p, buf, len); return (int) len; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ /* * privateKey OCTET STRING -- always of length ceil(log2(n)/8) */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static int pk_write_ec_private(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t byte_length; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE]; psa_status_t status; if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); if (status != PSA_SUCCESS) { ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); return ret; } } else { status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); if (status != PSA_SUCCESS) { ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); goto exit; } } ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); exit: mbedtls_platform_zeroize(tmp, sizeof(tmp)); return ret; } #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int pk_write_ec_private(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t byte_length; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE]; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); if (status != PSA_SUCCESS) { ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); return ret; } } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ { mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); byte_length = (ec->grp.pbits + 7) / 8; ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp)); if (ret != 0) { goto exit; } } ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); exit: mbedtls_platform_zeroize(tmp, sizeof(tmp)); return ret; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ /* * ECParameters ::= CHOICE { * namedCurve OBJECT IDENTIFIER * } */ static int pk_write_ec_param(unsigned char **p, unsigned char *start, mbedtls_ecp_group_id grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; const char *oid; size_t oid_len; if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) { return ret; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); return (int) len; } #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) /* * RFC8410 section 7 * * OneAsymmetricKey ::= SEQUENCE { * version Version, * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, * privateKey PrivateKey, * attributes [0] IMPLICIT Attributes OPTIONAL, * ..., * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]], * ... * } * ... * CurvePrivateKey ::= OCTET STRING */ static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf, const mbedtls_pk_context *pk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; size_t oid_len = 0; const char *oid; mbedtls_ecp_group_id grp_id; /* privateKey */ MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING)); grp_id = mbedtls_pk_get_ec_group_id(pk); /* privateKeyAlgorithm */ if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) { return ret; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0)); /* version */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ /* * RFC 5915, or SEC1 Appendix C.4 * * ECPrivateKey ::= SEQUENCE { * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), * privateKey OCTET STRING, * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, * publicKey [1] BIT STRING OPTIONAL * } */ static int pk_write_ec_der(unsigned char **p, unsigned char *buf, const mbedtls_pk_context *pk) { size_t len = 0; int ret; size_t pub_len = 0, par_len = 0; mbedtls_ecp_group_id grp_id; /* publicKey */ MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk)); if (*p - buf < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } (*p)--; **p = 0; pub_len += 1; MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING)); MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1)); len += pub_len; /* parameters */ grp_id = mbedtls_pk_get_ec_group_id(pk); MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id)); MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len)); MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)); len += par_len; /* privateKey */ MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); /* version */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /****************************************************************************** * Internal functions for Opaque keys. ******************************************************************************/ #if defined(MBEDTLS_USE_PSA_CRYPTO) static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t buffer_size; size_t len = 0; if (*p < start) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } buffer_size = (size_t) (*p - start); if (psa_export_public_key(pk->priv_id, start, buffer_size, &len) != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } *p -= len; memmove(*p, start, len); return (int) len; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /****************************************************************************** * Generic helpers ******************************************************************************/ /* Extend the public mbedtls_pk_get_type() by getting key type also in case of * opaque keys. */ static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk) { mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk); #if defined(MBEDTLS_USE_PSA_CRYPTO) if (pk_type == MBEDTLS_PK_OPAQUE) { psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t opaque_key_type; if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) { return MBEDTLS_PK_NONE; } opaque_key_type = psa_get_key_type(&opaque_attrs); psa_reset_key_attributes(&opaque_attrs); if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) { return MBEDTLS_PK_ECKEY; } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) { return MBEDTLS_PK_RSA; } else { return MBEDTLS_PK_NONE; } } else #endif return pk_type; } /****************************************************************************** * Public functions for writing private/public DER keys. ******************************************************************************/ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *key) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; #if defined(MBEDTLS_RSA_C) if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p)); } else #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key)); } else #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key)); } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; return (int) len; } int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *c; int has_par = 1; size_t len = 0, par_len = 0, oid_len = 0; mbedtls_pk_type_t pk_type; const char *oid = NULL; if (size == 0) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } c = buf + size; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key)); if (c - buf < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } /* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ *--c = 0; len += 1; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); pk_type = pk_get_type_ext(key); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key); if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len); if (ret != 0) { return ret; } has_par = 0; } else { MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id)); } } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* At this point oid_len is not null only for EC Montgomery keys. */ if (oid_len == 0) { ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len); if (ret != 0) { return ret; } } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len, par_len, has_par)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { unsigned char *c; if (size == 0) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } c = buf + size; #if defined(MBEDTLS_RSA_C) if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) { return pk_write_rsa_der(&c, buf, key); } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) if (mbedtls_pk_is_rfc8410(key)) { return pk_write_ec_rfc8410_der(&c, buf, key); } #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ return pk_write_ec_der(&c, buf, key); } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } /****************************************************************************** * Public functions for wrinting private/public PEM keys. ******************************************************************************/ #if defined(MBEDTLS_PEM_WRITE_C) #define PUB_DER_MAX_BYTES \ (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \ MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) #define PRV_DER_MAX_BYTES \ (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \ MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES) int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *output_buf = NULL; output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES); if (output_buf == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } size_t olen = 0; if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, PUB_DER_MAX_BYTES)) < 0) { goto cleanup; } if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n", output_buf + PUB_DER_MAX_BYTES - ret, ret, buf, size, &olen)) != 0) { goto cleanup; } ret = 0; cleanup: mbedtls_free(output_buf); return ret; } int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *output_buf = NULL; output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES); if (output_buf == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } const char *begin, *end; size_t olen = 0; if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) { goto cleanup; } #if defined(MBEDTLS_RSA_C) if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) { begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n"; end = PEM_END_PRIVATE_KEY_RSA "\n"; } else #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { if (mbedtls_pk_is_rfc8410(key)) { begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n"; end = PEM_END_PRIVATE_KEY_PKCS8 "\n"; } else { begin = PEM_BEGIN_PRIVATE_KEY_EC "\n"; end = PEM_END_PRIVATE_KEY_EC "\n"; } } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ { ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; goto cleanup; } if ((ret = mbedtls_pem_write_buffer(begin, end, output_buf + PRV_DER_MAX_BYTES - ret, ret, buf, size, &olen)) != 0) { goto cleanup; } ret = 0; cleanup: mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES); return ret; } #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */ webfakes/src/mbedtls/library/psa_crypto_driver_wrappers_no_static.c0000644000176200001440000002025514740737024025632 0ustar liggesusers/* * Functions to delegate cryptographic operations to an available * and appropriate accelerator. * Warning: This file is now auto-generated. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* BEGIN-common headers */ #include "common.h" #include "psa_crypto_aead.h" #include "psa_crypto_cipher.h" #include "psa_crypto_core.h" #include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_hash.h" #include "psa_crypto_mac.h" #include "psa_crypto_pake.h" #include "psa_crypto_rsa.h" #include "mbedtls/platform.h" /* END-common headers */ #if defined(MBEDTLS_PSA_CRYPTO_C) /* BEGIN-driver headers */ /* Headers for mbedtls_test opaque driver */ #if defined(PSA_CRYPTO_DRIVER_TEST) #include "test/drivers/test_driver.h" #endif /* Headers for mbedtls_test transparent driver */ #if defined(PSA_CRYPTO_DRIVER_TEST) #include "test/drivers/test_driver.h" #endif /* Headers for p256 transparent driver */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) #include "../3rdparty/p256-m/p256-m_driver_entrypoints.h" #endif /* END-driver headers */ /* Auto-generated values depending on which drivers are registered. * ID 0 is reserved for unallocated operations. * ID 1 is reserved for the Mbed TLS software driver. */ /* BEGIN-driver id definition */ #define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1) #define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2) #define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3) #define P256_TRANSPARENT_DRIVER_ID (4) /* END-driver id */ /* BEGIN-Common Macro definitions */ /* END-Common Macro definitions */ /* Support the 'old' SE interface when asked to */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style * SE driver is present, to avoid unused argument errors at compile time. */ #ifndef PSA_CRYPTO_DRIVER_PRESENT #define PSA_CRYPTO_DRIVER_PRESENT #endif #include "psa_crypto_se.h" #endif /** Get the key buffer size required to store the key material of a key * associated with an opaque driver. * * \param[in] attributes The key attributes. * \param[out] key_buffer_size Minimum buffer size to contain the key material * * \retval #PSA_SUCCESS * The minimum size for a buffer to contain the key material has been * returned successfully. * \retval #PSA_ERROR_NOT_SUPPORTED * The type and/or the size in bits of the key or the combination of * the two is not supported. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key is declared with a lifetime not known to us. */ psa_status_t psa_driver_wrapper_get_key_buffer_size( const psa_key_attributes_t *attributes, size_t *key_buffer_size ) { psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); psa_key_type_t key_type = psa_get_key_type(attributes); size_t key_bits = psa_get_key_bits(attributes); *key_buffer_size = 0; switch( location ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) /* Emulate property 'builtin_key_size' */ if( psa_key_id_is_builtin( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( attributes ) ) ) ) { *key_buffer_size = sizeof( psa_drv_slot_number_t ); return( PSA_SUCCESS ); } #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ *key_buffer_size = mbedtls_test_opaque_size_function( key_type, key_bits ); return( ( *key_buffer_size != 0 ) ? PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_TEST */ default: (void)key_type; (void)key_bits; return( PSA_ERROR_INVALID_ARGUMENT ); } } psa_status_t psa_driver_wrapper_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) { psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( ( drv->key_management == NULL ) || ( drv->key_management->p_export_public == NULL ) ) { return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->key_management->p_export_public( drv_context, *( (psa_key_slot_number_t *)key_buffer ), data, data_size, data_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) status = mbedtls_test_transparent_export_public_key (attributes, key_buffer, key_buffer_size, data, data_size, data_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif #if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) ) status = p256_transparent_export_public_key (attributes, key_buffer, key_buffer_size, data, data_size, data_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( psa_export_public_key_internal( attributes, key_buffer, key_buffer_size, data, data_size, data_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_export_public_key (attributes, key_buffer, key_buffer_size, data, data_size, data_length )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ return( status ); } } psa_status_t psa_driver_wrapper_get_builtin_key( psa_drv_slot_number_t slot_number, psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) { psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_get_builtin_key (slot_number, attributes, key_buffer, key_buffer_size, key_buffer_length )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) slot_number; (void) key_buffer; (void) key_buffer_size; (void) key_buffer_length; return( PSA_ERROR_DOES_NOT_EXIST ); } } #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/aesni.c0000644000176200001440000010017014740737024017200 0ustar liggesusers/* * AES-NI support functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * [AES-WP] https://www.intel.com/content/www/us/en/developer/articles/tool/intel-advanced-encryption-standard-aes-instructions-set.html * [CLMUL-WP] https://www.intel.com/content/www/us/en/develop/download/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode.html */ #include "common.h" #if defined(MBEDTLS_AESNI_C) #include "aesni.h" #include #if defined(MBEDTLS_AESNI_HAVE_CODE) #if MBEDTLS_AESNI_HAVE_CODE == 2 #if defined(__GNUC__) #include #elif defined(_MSC_VER) #include #else #error "`__cpuid` required by MBEDTLS_AESNI_C is not supported by the compiler" #endif #include #endif #if defined(MBEDTLS_ARCH_IS_X86) #if defined(MBEDTLS_COMPILER_IS_GCC) #pragma GCC push_options #pragma GCC target ("pclmul,sse2,aes") #define MBEDTLS_POP_TARGET_PRAGMA #elif defined(__clang__) && (__clang_major__ >= 5) #pragma clang attribute push (__attribute__((target("pclmul,sse2,aes"))), apply_to=function) #define MBEDTLS_POP_TARGET_PRAGMA #endif #endif #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) /* * AES-NI support detection routine */ int mbedtls_aesni_has_support(unsigned int what) { static int done = 0; static unsigned int c = 0; if (!done) { #if MBEDTLS_AESNI_HAVE_CODE == 2 static int info[4] = { 0, 0, 0, 0 }; #if defined(_MSC_VER) __cpuid(info, 1); #else __cpuid(1, info[0], info[1], info[2], info[3]); #endif c = info[2]; #else /* AESNI using asm */ asm ("movl $1, %%eax \n\t" "cpuid \n\t" : "=c" (c) : : "eax", "ebx", "edx"); #endif /* MBEDTLS_AESNI_HAVE_CODE */ done = 1; } return (c & what) != 0; } #endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ #if MBEDTLS_AESNI_HAVE_CODE == 2 /* * AES-NI AES-ECB block en(de)cryption */ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { const __m128i *rk = (const __m128i *) (ctx->buf + ctx->rk_offset); unsigned nr = ctx->nr; // Number of remaining rounds // Load round key 0 __m128i state; memcpy(&state, input, 16); state = _mm_xor_si128(state, rk[0]); // state ^= *rk; ++rk; --nr; #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { while (nr != 0) { state = _mm_aesdec_si128(state, *rk); ++rk; --nr; } state = _mm_aesdeclast_si128(state, *rk); } else #else (void) mode; #endif { while (nr != 0) { state = _mm_aesenc_si128(state, *rk); ++rk; --nr; } state = _mm_aesenclast_si128(state, *rk); } memcpy(output, &state, 16); return 0; } /* * GCM multiplication: c = a times b in GF(2^128) * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. */ static void gcm_clmul(const __m128i aa, const __m128i bb, __m128i *cc, __m128i *dd) { /* * Caryless multiplication dd:cc = aa * bb * using [CLMUL-WP] algorithm 1 (p. 12). */ *cc = _mm_clmulepi64_si128(aa, bb, 0x00); // a0*b0 = c1:c0 *dd = _mm_clmulepi64_si128(aa, bb, 0x11); // a1*b1 = d1:d0 __m128i ee = _mm_clmulepi64_si128(aa, bb, 0x10); // a0*b1 = e1:e0 __m128i ff = _mm_clmulepi64_si128(aa, bb, 0x01); // a1*b0 = f1:f0 ff = _mm_xor_si128(ff, ee); // e1+f1:e0+f0 ee = ff; // e1+f1:e0+f0 ff = _mm_srli_si128(ff, 8); // 0:e1+f1 ee = _mm_slli_si128(ee, 8); // e0+f0:0 *dd = _mm_xor_si128(*dd, ff); // d1:d0+e1+f1 *cc = _mm_xor_si128(*cc, ee); // c1+e0+f0:c0 } static void gcm_shift(__m128i *cc, __m128i *dd) { /* [CMUCL-WP] Algorithm 5 Step 1: shift cc:dd one bit to the left, * taking advantage of [CLMUL-WP] eq 27 (p. 18). */ // // *cc = r1:r0 // // *dd = r3:r2 __m128i cc_lo = _mm_slli_epi64(*cc, 1); // r1<<1:r0<<1 __m128i dd_lo = _mm_slli_epi64(*dd, 1); // r3<<1:r2<<1 __m128i cc_hi = _mm_srli_epi64(*cc, 63); // r1>>63:r0>>63 __m128i dd_hi = _mm_srli_epi64(*dd, 63); // r3>>63:r2>>63 __m128i xmm5 = _mm_srli_si128(cc_hi, 8); // 0:r1>>63 cc_hi = _mm_slli_si128(cc_hi, 8); // r0>>63:0 dd_hi = _mm_slli_si128(dd_hi, 8); // 0:r1>>63 *cc = _mm_or_si128(cc_lo, cc_hi); // r1<<1|r0>>63:r0<<1 *dd = _mm_or_si128(_mm_or_si128(dd_lo, dd_hi), xmm5); // r3<<1|r2>>62:r2<<1|r1>>63 } static __m128i gcm_reduce(__m128i xx) { // // xx = x1:x0 /* [CLMUL-WP] Algorithm 5 Step 2 */ __m128i aa = _mm_slli_epi64(xx, 63); // x1<<63:x0<<63 = stuff:a __m128i bb = _mm_slli_epi64(xx, 62); // x1<<62:x0<<62 = stuff:b __m128i cc = _mm_slli_epi64(xx, 57); // x1<<57:x0<<57 = stuff:c __m128i dd = _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(aa, bb), cc), 8); // a+b+c:0 return _mm_xor_si128(dd, xx); // x1+a+b+c:x0 = d:x0 } static __m128i gcm_mix(__m128i dx) { /* [CLMUL-WP] Algorithm 5 Steps 3 and 4 */ __m128i ee = _mm_srli_epi64(dx, 1); // e1:x0>>1 = e1:e0' __m128i ff = _mm_srli_epi64(dx, 2); // f1:x0>>2 = f1:f0' __m128i gg = _mm_srli_epi64(dx, 7); // g1:x0>>7 = g1:g0' // e0'+f0'+g0' is almost e0+f0+g0, except for some missing // bits carried from d. Now get those bits back in. __m128i eh = _mm_slli_epi64(dx, 63); // d<<63:stuff __m128i fh = _mm_slli_epi64(dx, 62); // d<<62:stuff __m128i gh = _mm_slli_epi64(dx, 57); // d<<57:stuff __m128i hh = _mm_srli_si128(_mm_xor_si128(_mm_xor_si128(eh, fh), gh), 8); // 0:missing bits of d return _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(ee, ff), gg), hh), dx); } void mbedtls_aesni_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]) { __m128i aa = { 0 }, bb = { 0 }, cc, dd; /* The inputs are in big-endian order, so byte-reverse them */ for (size_t i = 0; i < 16; i++) { ((uint8_t *) &aa)[i] = a[15 - i]; ((uint8_t *) &bb)[i] = b[15 - i]; } gcm_clmul(aa, bb, &cc, &dd); gcm_shift(&cc, &dd); /* * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 * using [CLMUL-WP] algorithm 5 (p. 18). * Currently dd:cc holds x3:x2:x1:x0 (already shifted). */ __m128i dx = gcm_reduce(cc); __m128i xh = gcm_mix(dx); cc = _mm_xor_si128(xh, dd); // x3+h1:x2+h0 /* Now byte-reverse the outputs */ for (size_t i = 0; i < 16; i++) { c[i] = ((uint8_t *) &cc)[15 - i]; } return; } /* * Compute decryption round keys from encryption round keys */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) void mbedtls_aesni_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr) { __m128i *ik = (__m128i *) invkey; const __m128i *fk = (const __m128i *) fwdkey + nr; *ik = *fk; for (--fk, ++ik; fk > (const __m128i *) fwdkey; --fk, ++ik) { *ik = _mm_aesimc_si128(*fk); } *ik = *fk; } #endif /* * Key expansion, 128-bit case */ static __m128i aesni_set_rk_128(__m128i state, __m128i xword) { /* * Finish generating the next round key. * * On entry state is r3:r2:r1:r0 and xword is X:stuff:stuff:stuff * with X = rot( sub( r3 ) ) ^ RCON (obtained with AESKEYGENASSIST). * * On exit, xword is r7:r6:r5:r4 * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 * and this is returned, to be written to the round key buffer. */ xword = _mm_shuffle_epi32(xword, 0xff); // X:X:X:X xword = _mm_xor_si128(xword, state); // X+r3:X+r2:X+r1:r4 state = _mm_slli_si128(state, 4); // r2:r1:r0:0 xword = _mm_xor_si128(xword, state); // X+r3+r2:X+r2+r1:r5:r4 state = _mm_slli_si128(state, 4); // r1:r0:0:0 xword = _mm_xor_si128(xword, state); // X+r3+r2+r1:r6:r5:r4 state = _mm_slli_si128(state, 4); // r0:0:0:0 state = _mm_xor_si128(xword, state); // r7:r6:r5:r4 return state; } static void aesni_setkey_enc_128(unsigned char *rk_bytes, const unsigned char *key) { __m128i *rk = (__m128i *) rk_bytes; memcpy(&rk[0], key, 16); rk[1] = aesni_set_rk_128(rk[0], _mm_aeskeygenassist_si128(rk[0], 0x01)); rk[2] = aesni_set_rk_128(rk[1], _mm_aeskeygenassist_si128(rk[1], 0x02)); rk[3] = aesni_set_rk_128(rk[2], _mm_aeskeygenassist_si128(rk[2], 0x04)); rk[4] = aesni_set_rk_128(rk[3], _mm_aeskeygenassist_si128(rk[3], 0x08)); rk[5] = aesni_set_rk_128(rk[4], _mm_aeskeygenassist_si128(rk[4], 0x10)); rk[6] = aesni_set_rk_128(rk[5], _mm_aeskeygenassist_si128(rk[5], 0x20)); rk[7] = aesni_set_rk_128(rk[6], _mm_aeskeygenassist_si128(rk[6], 0x40)); rk[8] = aesni_set_rk_128(rk[7], _mm_aeskeygenassist_si128(rk[7], 0x80)); rk[9] = aesni_set_rk_128(rk[8], _mm_aeskeygenassist_si128(rk[8], 0x1B)); rk[10] = aesni_set_rk_128(rk[9], _mm_aeskeygenassist_si128(rk[9], 0x36)); } /* * Key expansion, 192-bit case */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword, unsigned char *rk) { /* * Finish generating the next 6 quarter-keys. * * On entry state0 is r3:r2:r1:r0, state1 is stuff:stuff:r5:r4 * and xword is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON * (obtained with AESKEYGENASSIST). * * On exit, state0 is r9:r8:r7:r6 and state1 is stuff:stuff:r11:r10 * and those are written to the round key buffer. */ xword = _mm_shuffle_epi32(xword, 0x55); // X:X:X:X xword = _mm_xor_si128(xword, *state0); // X+r3:X+r2:X+r1:X+r0 *state0 = _mm_slli_si128(*state0, 4); // r2:r1:r0:0 xword = _mm_xor_si128(xword, *state0); // X+r3+r2:X+r2+r1:X+r1+r0:X+r0 *state0 = _mm_slli_si128(*state0, 4); // r1:r0:0:0 xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1:X+r2+r1+r0:X+r1+r0:X+r0 *state0 = _mm_slli_si128(*state0, 4); // r0:0:0:0 xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1+r0:X+r2+r1+r0:X+r1+r0:X+r0 *state0 = xword; // = r9:r8:r7:r6 xword = _mm_shuffle_epi32(xword, 0xff); // r9:r9:r9:r9 xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5:r9+r4 *state1 = _mm_slli_si128(*state1, 4); // stuff:stuff:r4:0 xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5+r4:r9+r4 *state1 = xword; // = stuff:stuff:r11:r10 /* Store state0 and the low half of state1 into rk, which is conceptually * an array of 24-byte elements. Since 24 is not a multiple of 16, * rk is not necessarily aligned so just `*rk = *state0` doesn't work. */ memcpy(rk, state0, 16); memcpy(rk + 16, state1, 8); } static void aesni_setkey_enc_192(unsigned char *rk, const unsigned char *key) { /* First round: use original key */ memcpy(rk, key, 24); /* aes.c guarantees that rk is aligned on a 16-byte boundary. */ __m128i state0 = ((__m128i *) rk)[0]; __m128i state1 = _mm_loadl_epi64(((__m128i *) rk) + 1); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x01), rk + 24 * 1); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x02), rk + 24 * 2); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x04), rk + 24 * 3); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x08), rk + 24 * 4); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x10), rk + 24 * 5); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x20), rk + 24 * 6); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8); } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* * Key expansion, 256-bit case */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword, __m128i *rk0, __m128i *rk1) { /* * Finish generating the next two round keys. * * On entry state0 is r3:r2:r1:r0, state1 is r7:r6:r5:r4 and * xword is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON * (obtained with AESKEYGENASSIST). * * On exit, *rk0 is r11:r10:r9:r8 and *rk1 is r15:r14:r13:r12 */ xword = _mm_shuffle_epi32(xword, 0xff); xword = _mm_xor_si128(xword, state0); state0 = _mm_slli_si128(state0, 4); xword = _mm_xor_si128(xword, state0); state0 = _mm_slli_si128(state0, 4); xword = _mm_xor_si128(xword, state0); state0 = _mm_slli_si128(state0, 4); state0 = _mm_xor_si128(state0, xword); *rk0 = state0; /* Set xword to stuff:Y:stuff:stuff with Y = subword( r11 ) * and proceed to generate next round key from there */ xword = _mm_aeskeygenassist_si128(state0, 0x00); xword = _mm_shuffle_epi32(xword, 0xaa); xword = _mm_xor_si128(xword, state1); state1 = _mm_slli_si128(state1, 4); xword = _mm_xor_si128(xword, state1); state1 = _mm_slli_si128(state1, 4); xword = _mm_xor_si128(xword, state1); state1 = _mm_slli_si128(state1, 4); state1 = _mm_xor_si128(state1, xword); *rk1 = state1; } static void aesni_setkey_enc_256(unsigned char *rk_bytes, const unsigned char *key) { __m128i *rk = (__m128i *) rk_bytes; memcpy(&rk[0], key, 16); memcpy(&rk[1], key + 16, 16); /* * Main "loop" - Generating one more key than necessary, * see definition of mbedtls_aes_context.buf */ aesni_set_rk_256(rk[0], rk[1], _mm_aeskeygenassist_si128(rk[1], 0x01), &rk[2], &rk[3]); aesni_set_rk_256(rk[2], rk[3], _mm_aeskeygenassist_si128(rk[3], 0x02), &rk[4], &rk[5]); aesni_set_rk_256(rk[4], rk[5], _mm_aeskeygenassist_si128(rk[5], 0x04), &rk[6], &rk[7]); aesni_set_rk_256(rk[6], rk[7], _mm_aeskeygenassist_si128(rk[7], 0x08), &rk[8], &rk[9]); aesni_set_rk_256(rk[8], rk[9], _mm_aeskeygenassist_si128(rk[9], 0x10), &rk[10], &rk[11]); aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]); aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]); } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #if defined(MBEDTLS_POP_TARGET_PRAGMA) #if defined(__clang__) #pragma clang attribute pop #elif defined(__GNUC__) #pragma GCC pop_options #endif #undef MBEDTLS_POP_TARGET_PRAGMA #endif #else /* MBEDTLS_AESNI_HAVE_CODE == 1 */ #if defined(__has_feature) #if __has_feature(memory_sanitizer) #warning \ "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." #endif #endif /* * Binutils needs to be at least 2.19 to support AES-NI instructions. * Unfortunately, a lot of users have a lower version now (2014-04). * Emit bytecode directly in order to support "old" version of gas. * * Opcodes from the Intel architecture reference manual, vol. 3. * We always use registers, so we don't need prefixes for memory operands. * Operand macros are in gas order (src, dst) as opposed to Intel order * (dst, src) in order to blend better into the surrounding assembly code. */ #define AESDEC(regs) ".byte 0x66,0x0F,0x38,0xDE," regs "\n\t" #define AESDECLAST(regs) ".byte 0x66,0x0F,0x38,0xDF," regs "\n\t" #define AESENC(regs) ".byte 0x66,0x0F,0x38,0xDC," regs "\n\t" #define AESENCLAST(regs) ".byte 0x66,0x0F,0x38,0xDD," regs "\n\t" #define AESIMC(regs) ".byte 0x66,0x0F,0x38,0xDB," regs "\n\t" #define AESKEYGENA(regs, imm) ".byte 0x66,0x0F,0x3A,0xDF," regs "," imm "\n\t" #define PCLMULQDQ(regs, imm) ".byte 0x66,0x0F,0x3A,0x44," regs "," imm "\n\t" #define xmm0_xmm0 "0xC0" #define xmm0_xmm1 "0xC8" #define xmm0_xmm2 "0xD0" #define xmm0_xmm3 "0xD8" #define xmm0_xmm4 "0xE0" #define xmm1_xmm0 "0xC1" #define xmm1_xmm2 "0xD1" /* * AES-NI AES-ECB block en(de)cryption */ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { asm ("movdqu (%3), %%xmm0 \n\t" // load input "movdqu (%1), %%xmm1 \n\t" // load round key 0 "pxor %%xmm1, %%xmm0 \n\t" // round 0 "add $16, %1 \n\t" // point to next round key "subl $1, %0 \n\t" // normal rounds = nr - 1 "test %2, %2 \n\t" // mode? "jz 2f \n\t" // 0 = decrypt "1: \n\t" // encryption loop "movdqu (%1), %%xmm1 \n\t" // load round key AESENC(xmm1_xmm0) // do round "add $16, %1 \n\t" // point to next round key "subl $1, %0 \n\t" // loop "jnz 1b \n\t" "movdqu (%1), %%xmm1 \n\t" // load round key AESENCLAST(xmm1_xmm0) // last round #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) "jmp 3f \n\t" "2: \n\t" // decryption loop "movdqu (%1), %%xmm1 \n\t" AESDEC(xmm1_xmm0) // do round "add $16, %1 \n\t" "subl $1, %0 \n\t" "jnz 2b \n\t" "movdqu (%1), %%xmm1 \n\t" // load round key AESDECLAST(xmm1_xmm0) // last round #endif "3: \n\t" "movdqu %%xmm0, (%4) \n\t" // export output : : "r" (ctx->nr), "r" (ctx->buf + ctx->rk_offset), "r" (mode), "r" (input), "r" (output) : "memory", "cc", "xmm0", "xmm1"); return 0; } /* * GCM multiplication: c = a times b in GF(2^128) * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. */ void mbedtls_aesni_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]) { unsigned char aa[16], bb[16], cc[16]; size_t i; /* The inputs are in big-endian order, so byte-reverse them */ for (i = 0; i < 16; i++) { aa[i] = a[15 - i]; bb[i] = b[15 - i]; } asm ("movdqu (%0), %%xmm0 \n\t" // a1:a0 "movdqu (%1), %%xmm1 \n\t" // b1:b0 /* * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 * using [CLMUL-WP] algorithm 1 (p. 12). */ "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 "movdqa %%xmm1, %%xmm3 \n\t" // same "movdqa %%xmm1, %%xmm4 \n\t" // same PCLMULQDQ(xmm0_xmm1, "0x00") // a0*b0 = c1:c0 PCLMULQDQ(xmm0_xmm2, "0x11") // a1*b1 = d1:d0 PCLMULQDQ(xmm0_xmm3, "0x10") // a0*b1 = e1:e0 PCLMULQDQ(xmm0_xmm4, "0x01") // a1*b0 = f1:f0 "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 "movdqa %%xmm4, %%xmm3 \n\t" // same "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 "pslldq $8, %%xmm3 \n\t" // e0+f0:0 "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 /* * Now shift the result one bit to the left, * taking advantage of [CLMUL-WP] eq 27 (p. 18) */ "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 "pslldq $8, %%xmm3 \n\t" // r0>>63:0 "pslldq $8, %%xmm4 \n\t" // r2>>63:0 "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 /* * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 * using [CLMUL-WP] algorithm 5 (p. 18). * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). */ /* Step 2 (1) */ "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 "movdqa %%xmm1, %%xmm4 \n\t" // same "movdqa %%xmm1, %%xmm5 \n\t" // same "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c /* Step 2 (2) */ "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c "pslldq $8, %%xmm3 \n\t" // a+b+c:0 "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 /* Steps 3 and 4 */ "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 "movdqa %%xmm1,%%xmm4 \n\t" // same "movdqa %%xmm1,%%xmm5 \n\t" // same "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing // bits carried from d. Now get those\t bits back in. "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 "movdqa %%xmm1,%%xmm4 \n\t" // same "movdqa %%xmm1,%%xmm5 \n\t" // same "psllq $63, %%xmm3 \n\t" // d<<63:stuff "psllq $62, %%xmm4 \n\t" // d<<62:stuff "psllq $57, %%xmm5 \n\t" // d<<57:stuff "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 "movdqu %%xmm0, (%2) \n\t" // done : : "r" (aa), "r" (bb), "r" (cc) : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); /* Now byte-reverse the outputs */ for (i = 0; i < 16; i++) { c[i] = cc[15 - i]; } return; } /* * Compute decryption round keys from encryption round keys */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) void mbedtls_aesni_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr) { unsigned char *ik = invkey; const unsigned char *fk = fwdkey + 16 * nr; memcpy(ik, fk, 16); for (fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16) { asm ("movdqu (%0), %%xmm0 \n\t" AESIMC(xmm0_xmm0) "movdqu %%xmm0, (%1) \n\t" : : "r" (fk), "r" (ik) : "memory", "xmm0"); } memcpy(ik, fk, 16); } #endif /* * Key expansion, 128-bit case */ static void aesni_setkey_enc_128(unsigned char *rk, const unsigned char *key) { asm ("movdqu (%1), %%xmm0 \n\t" // copy the original key "movdqu %%xmm0, (%0) \n\t" // as round key 0 "jmp 2f \n\t" // skip auxiliary routine /* * Finish generating the next round key. * * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff * with X = rot( sub( r3 ) ) ^ RCON. * * On exit, xmm0 is r7:r6:r5:r4 * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 * and those are written to the round key buffer. */ "1: \n\t" "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 "pslldq $4, %%xmm0 \n\t" // etc "pxor %%xmm0, %%xmm1 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! "add $16, %0 \n\t" // point to next round key "movdqu %%xmm0, (%0) \n\t" // write it "ret \n\t" /* Main "loop" */ "2: \n\t" AESKEYGENA(xmm0_xmm1, "0x01") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x02") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x04") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x08") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x10") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x20") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x40") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x80") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x1B") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x36") "call 1b \n\t" : : "r" (rk), "r" (key) : "memory", "cc", "0"); } /* * Key expansion, 192-bit case */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_setkey_enc_192(unsigned char *rk, const unsigned char *key) { asm ("movdqu (%1), %%xmm0 \n\t" // copy original round key "movdqu %%xmm0, (%0) \n\t" "add $16, %0 \n\t" "movq 16(%1), %%xmm1 \n\t" "movq %%xmm1, (%0) \n\t" "add $8, %0 \n\t" "jmp 2f \n\t" // skip auxiliary routine /* * Finish generating the next 6 quarter-keys. * * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. * * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 * and those are written to the round key buffer. */ "1: \n\t" "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 "pslldq $4, %%xmm0 \n\t" // etc "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 "movdqu %%xmm0, (%0) \n\t" "add $16, %0 \n\t" "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 "movq %%xmm1, (%0) \n\t" "add $8, %0 \n\t" "ret \n\t" "2: \n\t" AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x80") "call 1b \n\t" : : "r" (rk), "r" (key) : "memory", "cc", "0"); } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* * Key expansion, 256-bit case */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_setkey_enc_256(unsigned char *rk, const unsigned char *key) { asm ("movdqu (%1), %%xmm0 \n\t" "movdqu %%xmm0, (%0) \n\t" "add $16, %0 \n\t" "movdqu 16(%1), %%xmm1 \n\t" "movdqu %%xmm1, (%0) \n\t" "jmp 2f \n\t" // skip auxiliary routine /* * Finish generating the next two round keys. * * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON * * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 * and those have been written to the output buffer. */ "1: \n\t" "pshufd $0xff, %%xmm2, %%xmm2 \n\t" "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm2, %%xmm0 \n\t" "add $16, %0 \n\t" "movdqu %%xmm0, (%0) \n\t" /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) * and proceed to generate next round key from there */ AESKEYGENA(xmm0_xmm2, "0x00") "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" "pxor %%xmm1, %%xmm2 \n\t" "pslldq $4, %%xmm1 \n\t" "pxor %%xmm1, %%xmm2 \n\t" "pslldq $4, %%xmm1 \n\t" "pxor %%xmm1, %%xmm2 \n\t" "pslldq $4, %%xmm1 \n\t" "pxor %%xmm2, %%xmm1 \n\t" "add $16, %0 \n\t" "movdqu %%xmm1, (%0) \n\t" "ret \n\t" /* * Main "loop" - Generating one more key than necessary, * see definition of mbedtls_aes_context.buf */ "2: \n\t" AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t" : : "r" (rk), "r" (key) : "memory", "cc", "0"); } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #endif /* MBEDTLS_AESNI_HAVE_CODE */ /* * Key expansion, wrapper */ int mbedtls_aesni_setkey_enc(unsigned char *rk, const unsigned char *key, size_t bits) { switch (bits) { case 128: aesni_setkey_enc_128(rk, key); break; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 192: aesni_setkey_enc_192(rk, key); break; case 256: aesni_setkey_enc_256(rk, key); break; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } return 0; } #endif /* MBEDTLS_AESNI_HAVE_CODE */ #endif /* MBEDTLS_AESNI_C */ webfakes/src/mbedtls/library/poly1305.c0000644000176200001440000003416114740737024017403 0ustar liggesusers/** * \file poly1305.c * * \brief Poly1305 authentication algorithm. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_POLY1305_C) #include "mbedtls/poly1305.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_POLY1305_ALT) #define POLY1305_BLOCK_SIZE_BYTES (16U) /* * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. * However we provided an alternative for platforms without such a multiplier. */ #if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) static uint64_t mul64(uint32_t a, uint32_t b) { /* a = al + 2**16 ah, b = bl + 2**16 bh */ const uint16_t al = (uint16_t) a; const uint16_t bl = (uint16_t) b; const uint16_t ah = a >> 16; const uint16_t bh = b >> 16; /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ const uint32_t lo = (uint32_t) al * bl; const uint64_t me = (uint64_t) ((uint32_t) ah * bl) + (uint32_t) al * bh; const uint32_t hi = (uint32_t) ah * bh; return lo + (me << 16) + ((uint64_t) hi << 32); } #else static inline uint64_t mul64(uint32_t a, uint32_t b) { return (uint64_t) a * b; } #endif /** * \brief Process blocks with Poly1305. * * \param ctx The Poly1305 context. * \param nblocks Number of blocks to process. Note that this * function only processes full blocks. * \param input Buffer containing the input block(s). * \param needs_padding Set to 0 if the padding bit has already been * applied to the input data before calling this * function. Otherwise, set this parameter to 1. */ static void poly1305_process(mbedtls_poly1305_context *ctx, size_t nblocks, const unsigned char *input, uint32_t needs_padding) { uint64_t d0, d1, d2, d3; uint32_t acc0, acc1, acc2, acc3, acc4; uint32_t r0, r1, r2, r3; uint32_t rs1, rs2, rs3; size_t offset = 0U; size_t i; r0 = ctx->r[0]; r1 = ctx->r[1]; r2 = ctx->r[2]; r3 = ctx->r[3]; rs1 = r1 + (r1 >> 2U); rs2 = r2 + (r2 >> 2U); rs3 = r3 + (r3 >> 2U); acc0 = ctx->acc[0]; acc1 = ctx->acc[1]; acc2 = ctx->acc[2]; acc3 = ctx->acc[3]; acc4 = ctx->acc[4]; /* Process full blocks */ for (i = 0U; i < nblocks; i++) { /* The input block is treated as a 128-bit little-endian integer */ d0 = MBEDTLS_GET_UINT32_LE(input, offset + 0); d1 = MBEDTLS_GET_UINT32_LE(input, offset + 4); d2 = MBEDTLS_GET_UINT32_LE(input, offset + 8); d3 = MBEDTLS_GET_UINT32_LE(input, offset + 12); /* Compute: acc += (padded) block as a 130-bit integer */ d0 += (uint64_t) acc0; d1 += (uint64_t) acc1 + (d0 >> 32U); d2 += (uint64_t) acc2 + (d1 >> 32U); d3 += (uint64_t) acc3 + (d2 >> 32U); acc0 = (uint32_t) d0; acc1 = (uint32_t) d1; acc2 = (uint32_t) d2; acc3 = (uint32_t) d3; acc4 += (uint32_t) (d3 >> 32U) + needs_padding; /* Compute: acc *= r */ d0 = mul64(acc0, r0) + mul64(acc1, rs3) + mul64(acc2, rs2) + mul64(acc3, rs1); d1 = mul64(acc0, r1) + mul64(acc1, r0) + mul64(acc2, rs3) + mul64(acc3, rs2) + mul64(acc4, rs1); d2 = mul64(acc0, r2) + mul64(acc1, r1) + mul64(acc2, r0) + mul64(acc3, rs3) + mul64(acc4, rs2); d3 = mul64(acc0, r3) + mul64(acc1, r2) + mul64(acc2, r1) + mul64(acc3, r0) + mul64(acc4, rs3); acc4 *= r0; /* Compute: acc %= (2^130 - 5) (partial remainder) */ d1 += (d0 >> 32); d2 += (d1 >> 32); d3 += (d2 >> 32); acc0 = (uint32_t) d0; acc1 = (uint32_t) d1; acc2 = (uint32_t) d2; acc3 = (uint32_t) d3; acc4 = (uint32_t) (d3 >> 32) + acc4; d0 = (uint64_t) acc0 + (acc4 >> 2) + (acc4 & 0xFFFFFFFCU); acc4 &= 3U; acc0 = (uint32_t) d0; d0 = (uint64_t) acc1 + (d0 >> 32U); acc1 = (uint32_t) d0; d0 = (uint64_t) acc2 + (d0 >> 32U); acc2 = (uint32_t) d0; d0 = (uint64_t) acc3 + (d0 >> 32U); acc3 = (uint32_t) d0; d0 = (uint64_t) acc4 + (d0 >> 32U); acc4 = (uint32_t) d0; offset += POLY1305_BLOCK_SIZE_BYTES; } ctx->acc[0] = acc0; ctx->acc[1] = acc1; ctx->acc[2] = acc2; ctx->acc[3] = acc3; ctx->acc[4] = acc4; } /** * \brief Compute the Poly1305 MAC * * \param ctx The Poly1305 context. * \param mac The buffer to where the MAC is written. Must be * big enough to contain the 16-byte MAC. */ static void poly1305_compute_mac(const mbedtls_poly1305_context *ctx, unsigned char mac[16]) { uint64_t d; uint32_t g0, g1, g2, g3, g4; uint32_t acc0, acc1, acc2, acc3, acc4; uint32_t mask; uint32_t mask_inv; acc0 = ctx->acc[0]; acc1 = ctx->acc[1]; acc2 = ctx->acc[2]; acc3 = ctx->acc[3]; acc4 = ctx->acc[4]; /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. * We do this by calculating acc - (2^130 - 5), then checking if * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) */ /* Calculate acc + -(2^130 - 5) */ d = ((uint64_t) acc0 + 5U); g0 = (uint32_t) d; d = ((uint64_t) acc1 + (d >> 32)); g1 = (uint32_t) d; d = ((uint64_t) acc2 + (d >> 32)); g2 = (uint32_t) d; d = ((uint64_t) acc3 + (d >> 32)); g3 = (uint32_t) d; g4 = acc4 + (uint32_t) (d >> 32U); /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ mask = (uint32_t) 0U - (g4 >> 2U); mask_inv = ~mask; /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ acc0 = (acc0 & mask_inv) | (g0 & mask); acc1 = (acc1 & mask_inv) | (g1 & mask); acc2 = (acc2 & mask_inv) | (g2 & mask); acc3 = (acc3 & mask_inv) | (g3 & mask); /* Add 's' */ d = (uint64_t) acc0 + ctx->s[0]; acc0 = (uint32_t) d; d = (uint64_t) acc1 + ctx->s[1] + (d >> 32U); acc1 = (uint32_t) d; d = (uint64_t) acc2 + ctx->s[2] + (d >> 32U); acc2 = (uint32_t) d; acc3 += ctx->s[3] + (uint32_t) (d >> 32U); /* Compute MAC (128 least significant bits of the accumulator) */ MBEDTLS_PUT_UINT32_LE(acc0, mac, 0); MBEDTLS_PUT_UINT32_LE(acc1, mac, 4); MBEDTLS_PUT_UINT32_LE(acc2, mac, 8); MBEDTLS_PUT_UINT32_LE(acc3, mac, 12); } void mbedtls_poly1305_init(mbedtls_poly1305_context *ctx) { mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context)); } void mbedtls_poly1305_free(mbedtls_poly1305_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context)); } int mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx, const unsigned char key[32]) { /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ ctx->r[0] = MBEDTLS_GET_UINT32_LE(key, 0) & 0x0FFFFFFFU; ctx->r[1] = MBEDTLS_GET_UINT32_LE(key, 4) & 0x0FFFFFFCU; ctx->r[2] = MBEDTLS_GET_UINT32_LE(key, 8) & 0x0FFFFFFCU; ctx->r[3] = MBEDTLS_GET_UINT32_LE(key, 12) & 0x0FFFFFFCU; ctx->s[0] = MBEDTLS_GET_UINT32_LE(key, 16); ctx->s[1] = MBEDTLS_GET_UINT32_LE(key, 20); ctx->s[2] = MBEDTLS_GET_UINT32_LE(key, 24); ctx->s[3] = MBEDTLS_GET_UINT32_LE(key, 28); /* Initial accumulator state */ ctx->acc[0] = 0U; ctx->acc[1] = 0U; ctx->acc[2] = 0U; ctx->acc[3] = 0U; ctx->acc[4] = 0U; /* Queue initially empty */ mbedtls_platform_zeroize(ctx->queue, sizeof(ctx->queue)); ctx->queue_len = 0U; return 0; } int mbedtls_poly1305_update(mbedtls_poly1305_context *ctx, const unsigned char *input, size_t ilen) { size_t offset = 0U; size_t remaining = ilen; size_t queue_free_len; size_t nblocks; if ((remaining > 0U) && (ctx->queue_len > 0U)) { queue_free_len = (POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len); if (ilen < queue_free_len) { /* Not enough data to complete the block. * Store this data with the other leftovers. */ memcpy(&ctx->queue[ctx->queue_len], input, ilen); ctx->queue_len += ilen; remaining = 0U; } else { /* Enough data to produce a complete block */ memcpy(&ctx->queue[ctx->queue_len], input, queue_free_len); ctx->queue_len = 0U; poly1305_process(ctx, 1U, ctx->queue, 1U); /* add padding bit */ offset += queue_free_len; remaining -= queue_free_len; } } if (remaining >= POLY1305_BLOCK_SIZE_BYTES) { nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; poly1305_process(ctx, nblocks, &input[offset], 1U); offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; remaining %= POLY1305_BLOCK_SIZE_BYTES; } if (remaining > 0U) { /* Store partial block */ ctx->queue_len = remaining; memcpy(ctx->queue, &input[offset], remaining); } return 0; } int mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx, unsigned char mac[16]) { /* Process any leftover data */ if (ctx->queue_len > 0U) { /* Add padding bit */ ctx->queue[ctx->queue_len] = 1U; ctx->queue_len++; /* Pad with zeroes */ memset(&ctx->queue[ctx->queue_len], 0, POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len); poly1305_process(ctx, 1U, /* Process 1 block */ ctx->queue, 0U); /* Already padded above */ } poly1305_compute_mac(ctx, mac); return 0; } int mbedtls_poly1305_mac(const unsigned char key[32], const unsigned char *input, size_t ilen, unsigned char mac[16]) { mbedtls_poly1305_context ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_poly1305_init(&ctx); ret = mbedtls_poly1305_starts(&ctx, key); if (ret != 0) { goto cleanup; } ret = mbedtls_poly1305_update(&ctx, input, ilen); if (ret != 0) { goto cleanup; } ret = mbedtls_poly1305_finish(&ctx, mac); cleanup: mbedtls_poly1305_free(&ctx); return ret; } #endif /* MBEDTLS_POLY1305_ALT */ #if defined(MBEDTLS_SELF_TEST) static const unsigned char test_keys[2][32] = { { 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b }, { 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 } }; static const unsigned char test_data[2][127] = { { 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70 }, { 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e } }; static const size_t test_data_len[2] = { 34U, 127U }; static const unsigned char test_mac[2][16] = { { 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 }, { 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 } }; /* Make sure no other definition is already present. */ #undef ASSERT #define ASSERT(cond, args) \ do \ { \ if (!(cond)) \ { \ if (verbose != 0) \ mbedtls_printf args; \ \ return -1; \ } \ } \ while (0) int mbedtls_poly1305_self_test(int verbose) { unsigned char mac[16]; unsigned i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; for (i = 0U; i < 2U; i++) { if (verbose != 0) { mbedtls_printf(" Poly1305 test %u ", i); } ret = mbedtls_poly1305_mac(test_keys[i], test_data[i], test_data_len[i], mac); ASSERT(0 == ret, ("error code: %i\n", ret)); ASSERT(0 == memcmp(mac, test_mac[i], 16U), ("failed (mac)\n")); if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_POLY1305_C */ webfakes/src/mbedtls/library/rsa_internal.h0000644000176200001440000001226614740737024020577 0ustar liggesusers/** * \file rsa_internal.h * * \brief Internal-only RSA public-key cryptosystem API. * * This file declares RSA-related functions that are to be used * only from within the Mbed TLS library itself. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RSA_INTERNAL_H #define MBEDTLS_RSA_INTERNAL_H #include "mbedtls/rsa.h" #include "mbedtls/asn1.h" /** * \brief Parse a PKCS#1 (ASN.1) encoded private RSA key. * * \param rsa The RSA context where parsed data will be stored. * \param key The buffer that contains the key. * \param keylen The length of the key buffer in bytes. * * \return 0 on success. * \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors. * \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while * parsing data. * \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the * provided key fail. */ int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen); /** * \brief Parse a PKCS#1 (ASN.1) encoded public RSA key. * * \param rsa The RSA context where parsed data will be stored. * \param key The buffer that contains the key. * \param keylen The length of the key buffer in bytes. * * \return 0 on success. * \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors. * \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while * parsing data. * \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the * provided key fail. */ int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen); /** * \brief Write a PKCS#1 (ASN.1) encoded private RSA key. * * \param rsa The RSA context which contains the data to be written. * \param start Beginning of the buffer that will be filled with the * private key. * \param p End of the buffer that will be filled with the private key. * On successful return, the referenced pointer will be * updated in order to point to the beginning of written data. * * \return On success, the number of bytes written to the output buffer * (i.e. a value > 0). * \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not * contain a valid key pair. * \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the * output buffer. * * \note The output buffer is filled backward, i.e. starting from its * end and moving toward its start. */ int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start, unsigned char **p); /** * \brief Parse a PKCS#1 (ASN.1) encoded public RSA key. * * \param rsa The RSA context which contains the data to be written. * \param start Beginning of the buffer that will be filled with the * private key. * \param p End of the buffer that will be filled with the private key. * On successful return, the referenced pointer will be * updated in order to point to the beginning of written data. * * \return On success, the number of bytes written to the output buffer * (i.e. a value > 0). * \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not * contain a valid public key. * \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the * output buffer. * * \note The output buffer is filled backward, i.e. starting from its * end and moving toward its start. */ int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start, unsigned char **p); #if defined(MBEDTLS_PKCS1_V21) /** * \brief This function is analogue to \c mbedtls_rsa_rsassa_pss_sign(). * The only difference between them is that this function is more flexible * on the parameters of \p ctx that are set with \c mbedtls_rsa_set_padding(). * * \note Compared to its counterpart, this function: * - does not check the padding setting of \p ctx. * - allows the hash_id of \p ctx to be MBEDTLS_MD_NONE, * in which case it uses \p md_alg as the hash_id. * * \note Refer to \c mbedtls_rsa_rsassa_pss_sign() for a description * of the functioning and parameters of this function. */ int mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); #endif /* MBEDTLS_PKCS1_V21 */ #endif /* rsa_internal.h */ webfakes/src/mbedtls/library/ccm.c0000644000176200001440000005557114740737024016661 0ustar liggesusers/* * NIST SP800-38C compliant CCM implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Definition of CCM: * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf * RFC 3610 "Counter with CBC-MAC (CCM)" * * Related: * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" */ #include "common.h" #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #include "block_cipher_internal.h" #endif #include #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #include #define mbedtls_printf printf #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_PLATFORM_C */ #if !defined(MBEDTLS_CCM_ALT) /* * Initialize context */ void mbedtls_ccm_init(mbedtls_ccm_context *ctx) { memset(ctx, 0, sizeof(mbedtls_ccm_context)); } int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_free(&ctx->block_cipher_ctx); if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) { return MBEDTLS_ERR_CCM_BAD_INPUT; } #else const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, MBEDTLS_MODE_ECB); if (cipher_info == NULL) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { return MBEDTLS_ERR_CCM_BAD_INPUT; } mbedtls_cipher_free(&ctx->cipher_ctx); if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { return ret; } if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, MBEDTLS_ENCRYPT)) != 0) { return ret; } #endif return ret; } /* * Free context */ void mbedtls_ccm_free(mbedtls_ccm_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_free(&ctx->block_cipher_ctx); #else mbedtls_cipher_free(&ctx->cipher_ctx); #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context)); } #define CCM_STATE__CLEAR 0 #define CCM_STATE__STARTED (1 << 0) #define CCM_STATE__LENGTHS_SET (1 << 1) #define CCM_STATE__AUTH_DATA_STARTED (1 << 2) #define CCM_STATE__AUTH_DATA_FINISHED (1 << 3) #define CCM_STATE__ERROR (1 << 4) /* * Encrypt or decrypt a partial block with CTR */ static int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx, size_t offset, size_t use_len, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char tmp_buf[16] = { 0 }; #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->ctr, tmp_buf); #else size_t olen = 0; ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); return ret; } mbedtls_xor(output, input, tmp_buf + offset, use_len); mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); return ret; } static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx) { ctx->state = CCM_STATE__CLEAR; memset(ctx->y, 0, 16); memset(ctx->ctr, 0, 16); } static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char i; size_t len_left; #if !defined(MBEDTLS_BLOCK_CIPHER_C) size_t olen; #endif /* length calculation can be done only after both * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed */ if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) { return 0; } /* CCM expects non-empty tag. * CCM* allows empty tag. For CCM* without tag, ignore plaintext length. */ if (ctx->tag_len == 0) { if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { ctx->plaintext_len = 0; } else { return MBEDTLS_ERR_CCM_BAD_INPUT; } } /* * First block: * 0 .. 0 flags * 1 .. iv_len nonce (aka iv) - set by: mbedtls_ccm_starts() * iv_len+1 .. 15 length * * With flags as (bits): * 7 0 * 6 add present? * 5 .. 3 (t - 2) / 2 * 2 .. 0 q - 1 */ ctx->y[0] |= (ctx->add_len > 0) << 6; ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3; ctx->y[0] |= ctx->q - 1; for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) { ctx->y[15-i] = MBEDTLS_BYTE_0(len_left); } if (len_left > 0) { ctx->state |= CCM_STATE__ERROR; return MBEDTLS_ERR_CCM_BAD_INPUT; } /* Start CBC-MAC with first block*/ #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; return ret; } return 0; } int mbedtls_ccm_starts(mbedtls_ccm_context *ctx, int mode, const unsigned char *iv, size_t iv_len) { /* Also implies q is within bounds */ if (iv_len < 7 || iv_len > 13) { return MBEDTLS_ERR_CCM_BAD_INPUT; } ctx->mode = mode; ctx->q = 16 - 1 - (unsigned char) iv_len; /* * Prepare counter block for encryption: * 0 .. 0 flags * 1 .. iv_len nonce (aka iv) * iv_len+1 .. 15 counter (initially 1) * * With flags as (bits): * 7 .. 3 0 * 2 .. 0 q - 1 */ memset(ctx->ctr, 0, 16); ctx->ctr[0] = ctx->q - 1; memcpy(ctx->ctr + 1, iv, iv_len); memset(ctx->ctr + 1 + iv_len, 0, ctx->q); ctx->ctr[15] = 1; /* * See ccm_calculate_first_block_if_ready() for block layout description */ memcpy(ctx->y + 1, iv, iv_len); ctx->state |= CCM_STATE__STARTED; return ccm_calculate_first_block_if_ready(ctx); } int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, size_t total_ad_len, size_t plaintext_len, size_t tag_len) { /* * Check length requirements: SP800-38C A.1 * Additional requirement: a < 2^16 - 2^8 to simplify the code. * 'length' checked later (when writing it to the first block) * * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). */ if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (total_ad_len >= 0xFF00) { return MBEDTLS_ERR_CCM_BAD_INPUT; } ctx->plaintext_len = plaintext_len; ctx->add_len = total_ad_len; ctx->tag_len = tag_len; ctx->processed = 0; ctx->state |= CCM_STATE__LENGTHS_SET; return ccm_calculate_first_block_if_ready(ctx); } int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, const unsigned char *add, size_t add_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t use_len, offset; #if !defined(MBEDTLS_BLOCK_CIPHER_C) size_t olen; #endif if (ctx->state & CCM_STATE__ERROR) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (add_len > 0) { if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) { if (add_len > ctx->add_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF); ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF); ctx->state |= CCM_STATE__AUTH_DATA_STARTED; } else if (ctx->processed + add_len > ctx->add_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } while (add_len > 0) { offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1] * holding total auth data length */ use_len = 16 - offset; if (use_len > add_len) { use_len = add_len; } mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len); ctx->processed += use_len; add_len -= use_len; add += use_len; if (use_len + offset == 16 || ctx->processed == ctx->add_len) { #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; return ret; } } } if (ctx->processed == ctx->add_len) { ctx->state |= CCM_STATE__AUTH_DATA_FINISHED; ctx->processed = 0; // prepare for mbedtls_ccm_update() } } return 0; } int mbedtls_ccm_update(mbedtls_ccm_context *ctx, const unsigned char *input, size_t input_len, unsigned char *output, size_t output_size, size_t *output_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char i; size_t use_len, offset; #if !defined(MBEDTLS_BLOCK_CIPHER_C) size_t olen; #endif unsigned char local_output[16]; if (ctx->state & CCM_STATE__ERROR) { return MBEDTLS_ERR_CCM_BAD_INPUT; } /* Check against plaintext length only if performing operation with * authentication */ if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (output_size < input_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } *output_len = input_len; ret = 0; while (input_len > 0) { offset = ctx->processed % 16; use_len = 16 - offset; if (use_len > input_len) { use_len = input_len; } ctx->processed += use_len; if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \ ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) { mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len); if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; goto exit; } } ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output); if (ret != 0) { goto exit; } } if (ctx->mode == MBEDTLS_CCM_DECRYPT || \ ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { /* Since output may be in shared memory, we cannot be sure that * it will contain what we wrote to it. Therefore, we should avoid using * it as input to any operations. * Write decrypted data to local_output to avoid using output variable as * input in the XOR operation for Y. */ ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output); if (ret != 0) { goto exit; } mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len); memcpy(output, local_output, use_len); if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; goto exit; } } } if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { for (i = 0; i < ctx->q; i++) { if (++(ctx->ctr)[15-i] != 0) { break; } } } input_len -= use_len; input += use_len; output += use_len; } exit: mbedtls_platform_zeroize(local_output, 16); return ret; } int mbedtls_ccm_finish(mbedtls_ccm_context *ctx, unsigned char *tag, size_t tag_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char i; if (ctx->state & CCM_STATE__ERROR) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } /* * Authentication: reset counter and crypt/mask internal tag */ for (i = 0; i < ctx->q; i++) { ctx->ctr[15-i] = 0; } ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y); if (ret != 0) { return ret; } if (tag != NULL) { memcpy(tag, ctx->y, tag_len); } mbedtls_ccm_clear_state(ctx); return 0; } /* * Authenticated encryption or decryption */ static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) { return ret; } if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) { return ret; } if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) { return ret; } if ((ret = mbedtls_ccm_update(ctx, input, length, output, length, &olen)) != 0) { return ret; } if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) { return ret; } return 0; } /* * Authenticated encryption */ int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len) { return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len); } int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len) { return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len); } /* * Authenticated decryption */ static int mbedtls_ccm_compare_tags(const unsigned char *tag1, const unsigned char *tag2, size_t tag_len) { /* Check tag in "constant-time" */ int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len); if (diff != 0) { return MBEDTLS_ERR_CCM_AUTH_FAILED; } return 0; } static int ccm_auth_decrypt(mbedtls_ccm_context *ctx, int mode, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char check_tag[16]; if ((ret = ccm_auth_crypt(ctx, mode, length, iv, iv_len, add, add_len, input, output, check_tag, tag_len)) != 0) { return ret; } if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) { mbedtls_platform_zeroize(output, length); return ret; } return 0; } int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len) { return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len); } int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len) { return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len); } #endif /* !MBEDTLS_CCM_ALT */ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) /* * Examples 1 to 3 from SP800-38C Appendix C */ #define NB_TESTS 3 #define CCM_SELFTEST_PT_MAX_LEN 24 #define CCM_SELFTEST_CT_MAX_LEN 32 /* * The data is the same for all tests, only the used length changes */ static const unsigned char key_test_data[] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; static const unsigned char iv_test_data[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b }; static const unsigned char ad_test_data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 }; static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, }; static const size_t iv_len_test_data[NB_TESTS] = { 7, 8, 12 }; static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 }; static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 }; static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 }; static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } }; int mbedtls_ccm_self_test(int verbose) { mbedtls_ccm_context ctx; /* * Some hardware accelerators require the input and output buffers * would be in RAM, because the flash is not accessible. * Use buffers on the stack to hold the test vectors data. */ unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; size_t i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ccm_init(&ctx); if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data, 8 * sizeof(key_test_data)) != 0) { if (verbose != 0) { mbedtls_printf(" CCM: setup failed"); } return 1; } for (i = 0; i < NB_TESTS; i++) { if (verbose != 0) { mbedtls_printf(" CCM-AES #%u: ", (unsigned int) i + 1); } memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN); memset(ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN); memcpy(plaintext, msg_test_data, msg_len_test_data[i]); ret = mbedtls_ccm_encrypt_and_tag(&ctx, msg_len_test_data[i], iv_test_data, iv_len_test_data[i], ad_test_data, add_len_test_data[i], plaintext, ciphertext, ciphertext + msg_len_test_data[i], tag_len_test_data[i]); if (ret != 0 || memcmp(ciphertext, res_test_data[i], msg_len_test_data[i] + tag_len_test_data[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN); ret = mbedtls_ccm_auth_decrypt(&ctx, msg_len_test_data[i], iv_test_data, iv_len_test_data[i], ad_test_data, add_len_test_data[i], ciphertext, plaintext, ciphertext + msg_len_test_data[i], tag_len_test_data[i]); if (ret != 0 || memcmp(plaintext, msg_test_data, msg_len_test_data[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } if (verbose != 0) { mbedtls_printf("passed\n"); } } mbedtls_ccm_free(&ctx); if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_CCM_C */ webfakes/src/mbedtls/library/rsa.c0000644000176200001440000027011414740737024016674 0ustar liggesusers/* * The RSA public-key cryptosystem * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this implementation * of the RSA algorithm: * * [1] A method for obtaining digital signatures and public-key cryptosystems * R Rivest, A Shamir, and L Adleman * http://people.csail.mit.edu/rivest/pubs.html#RSA78 * * [2] Handbook of Applied Cryptography - 1997, Chapter 8 * Menezes, van Oorschot and Vanstone * * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and * Stefan Mangard * https://arxiv.org/abs/1702.08719v2 * */ #include "common.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #include "bignum_core.h" #include "bignum_internal.h" #include "rsa_alt_helpers.h" #include "rsa_internal.h" #include "mbedtls/oid.h" #include "mbedtls/asn1write.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" #include "md_psa.h" #include #if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) #include #endif #include "mbedtls/platform.h" /* * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. * * The value zero is: * - never a valid value for an RSA parameter * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). * * Since values can't be omitted in PKCS#1, passing a zero value to * rsa_complete() would be incorrect, so reject zero values early. */ static int asn1_get_nonzero_mpi(unsigned char **p, const unsigned char *end, mbedtls_mpi *X) { int ret; ret = mbedtls_asn1_get_mpi(p, end, X); if (ret != 0) { return ret; } if (mbedtls_mpi_cmp_int(X, 0) == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return 0; } int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen) { int ret, version; size_t len; unsigned char *p, *end; mbedtls_mpi T; mbedtls_mpi_init(&T); p = (unsigned char *) key; end = p + keylen; /* * This function parses the RSAPrivateKey (PKCS#1) * * RSAPrivateKey ::= SEQUENCE { * version Version, * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER, -- (inverse of q) mod p * otherPrimeInfos OtherPrimeInfos OPTIONAL * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } if (end != p + len) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { return ret; } if (version != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* Import N */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL, NULL, NULL)) != 0) { goto cleanup; } /* Import E */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, NULL, &T)) != 0) { goto cleanup; } /* Import D */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, &T, NULL)) != 0) { goto cleanup; } /* Import P */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL, NULL, NULL)) != 0) { goto cleanup; } /* Import Q */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T, NULL, NULL)) != 0) { goto cleanup; } #if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) /* * The RSA CRT parameters DP, DQ and QP are nominally redundant, in * that they can be easily recomputed from D, P and Q. However by * parsing them from the PKCS1 structure it is possible to avoid * recalculating them which both reduces the overhead of loading * RSA private keys into memory and also avoids side channels which * can arise when computing those values, since all of D, P, and Q * are secret. See https://eprint.iacr.org/2020/055 for a * description of one such attack. */ /* Import DP */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) { goto cleanup; } /* Import DQ */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) { goto cleanup; } /* Import QP */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) { goto cleanup; } #else /* Verify existence of the CRT params */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) { goto cleanup; } #endif /* rsa_complete() doesn't complete anything with the default * implementation but is still called: * - for the benefit of alternative implementation that may want to * pre-compute stuff beyond what's provided (eg Montgomery factors) * - as is also sanity-checks the key * * Furthermore, we also check the public part for consistency with * mbedtls_pk_parse_pubkey(), as it includes size minima for example. */ if ((ret = mbedtls_rsa_complete(rsa)) != 0 || (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) { goto cleanup; } if (p != end) { ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } cleanup: mbedtls_mpi_free(&T); if (ret != 0) { mbedtls_rsa_free(rsa); } return ret; } int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen) { unsigned char *p = (unsigned char *) key; unsigned char *end = (unsigned char *) (key + keylen); int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER -- e * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } if (end != p + len) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* Import N */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { return ret; } if ((ret = mbedtls_rsa_import_raw(rsa, p, len, NULL, 0, NULL, 0, NULL, 0, NULL, 0)) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } p += len; /* Import E */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { return ret; } if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0, NULL, 0, p, len)) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } p += len; if (mbedtls_rsa_complete(rsa) != 0 || mbedtls_rsa_check_pubkey(rsa) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (p != end) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } return 0; } int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start, unsigned char **p) { size_t len = 0; int ret; mbedtls_mpi T; /* Temporary holding the exported parameters */ /* * Export the parameters one after another to avoid simultaneous copies. */ mbedtls_mpi_init(&T); /* Export QP */ if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export DQ */ if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export DP */ if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export Q */ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, &T, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export P */ if ((ret = mbedtls_rsa_export(rsa, NULL, &T, NULL, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export D */ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, &T, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export E */ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export N */ if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; end_of_export: mbedtls_mpi_free(&T); if (ret < 0) { return ret; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, start, 0)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } /* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER -- e * } */ int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start, unsigned char **p) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; mbedtls_mpi T; mbedtls_mpi_init(&T); /* Export E */ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export N */ if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; end_of_export: mbedtls_mpi_free(&T); if (ret < 0) { return ret; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) /** This function performs the unpadding part of a PKCS#1 v1.5 decryption * operation (EME-PKCS1-v1_5 decoding). * * \note The return value from this function is a sensitive value * (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen * in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING * is often a situation that an attacker can provoke and leaking which * one is the result is precisely the information the attacker wants. * * \param input The input buffer which is the payload inside PKCS#1v1.5 * encryption padding, called the "encoded message EM" * by the terminology. * \param ilen The length of the payload in the \p input buffer. * \param output The buffer for the payload, called "message M" by the * PKCS#1 terminology. This must be a writable buffer of * length \p output_max_len bytes. * \param olen The address at which to store the length of * the payload. This must not be \c NULL. * \param output_max_len The length in bytes of the output buffer \p output. * * \return \c 0 on success. * \return #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE * The output buffer is too small for the unpadded payload. * \return #MBEDTLS_ERR_RSA_INVALID_PADDING * The input doesn't contain properly formatted padding. */ static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input, size_t ilen, unsigned char *output, size_t output_max_len, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, plaintext_max_size; /* The following variables take sensitive values: their value must * not leak into the observable behavior of the function other than * the designated outputs (output, olen, return value). Otherwise * this would open the execution of the function to * side-channel-based variants of the Bleichenbacher padding oracle * attack. Potential side channels include overall timing, memory * access patterns (especially visible to an adversary who has access * to a shared memory cache), and branches (especially visible to * an adversary who has access to a shared code cache or to a shared * branch predictor). */ size_t pad_count = 0; mbedtls_ct_condition_t bad; mbedtls_ct_condition_t pad_done; size_t plaintext_size = 0; mbedtls_ct_condition_t output_too_large; plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11 : output_max_len; /* Check and get padding length in constant time and constant * memory trace. The first byte must be 0. */ bad = mbedtls_ct_bool(input[0]); /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 * where PS must be at least 8 nonzero bytes. */ bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(input[1], MBEDTLS_RSA_CRYPT)); /* Read the whole buffer. Set pad_done to nonzero if we find * the 0x00 byte and remember the padding length in pad_count. */ pad_done = MBEDTLS_CT_FALSE; for (i = 2; i < ilen; i++) { mbedtls_ct_condition_t found = mbedtls_ct_uint_eq(input[i], 0); pad_done = mbedtls_ct_bool_or(pad_done, found); pad_count += mbedtls_ct_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1); } /* If pad_done is still zero, there's no data, only unfinished padding. */ bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_not(pad_done)); /* There must be at least 8 bytes of padding. */ bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_gt(8, pad_count)); /* If the padding is valid, set plaintext_size to the number of * remaining bytes after stripping the padding. If the padding * is invalid, avoid leaking this fact through the size of the * output: use the maximum message size that fits in the output * buffer. Do it without branches to avoid leaking the padding * validity through timing. RSA keys are small enough that all the * size_t values involved fit in unsigned int. */ plaintext_size = mbedtls_ct_uint_if( bad, (unsigned) plaintext_max_size, (unsigned) (ilen - pad_count - 3)); /* Set output_too_large to 0 if the plaintext fits in the output * buffer and to 1 otherwise. */ output_too_large = mbedtls_ct_uint_gt(plaintext_size, plaintext_max_size); /* Set ret without branches to avoid timing attacks. Return: * - INVALID_PADDING if the padding is bad (bad != 0). * - OUTPUT_TOO_LARGE if the padding is good but the decrypted * plaintext does not fit in the output buffer. * - 0 if the padding is correct. */ ret = mbedtls_ct_error_if( bad, MBEDTLS_ERR_RSA_INVALID_PADDING, mbedtls_ct_error_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ); /* If the padding is bad or the plaintext is too large, zero the * data that we're about to copy to the output buffer. * We need to copy the same amount of data * from the same buffer whether the padding is good or not to * avoid leaking the padding validity through overall timing or * through memory or cache access patterns. */ mbedtls_ct_zeroize_if(mbedtls_ct_bool_or(bad, output_too_large), input + 11, ilen - 11); /* If the plaintext is too large, truncate it to the buffer size. * Copy anyway to avoid revealing the length through timing, because * revealing the length is as bad as revealing the padding validity * for a Bleichenbacher attack. */ plaintext_size = mbedtls_ct_uint_if(output_too_large, (unsigned) plaintext_max_size, (unsigned) plaintext_size); /* Move the plaintext to the leftmost position where it can start in * the working buffer, i.e. make it start plaintext_max_size from * the end of the buffer. Do this with a memory access trace that * does not depend on the plaintext size. After this move, the * starting location of the plaintext is no longer sensitive * information. */ mbedtls_ct_memmove_left(input + ilen - plaintext_max_size, plaintext_max_size, plaintext_max_size - plaintext_size); /* Finally copy the decrypted plaintext plus trailing zeros into the output * buffer. If output_max_len is 0, then output may be an invalid pointer * and the result of memcpy() would be undefined; prevent undefined * behavior making sure to depend only on output_max_len (the size of the * user-provided output buffer), which is independent from plaintext * length, validity of padding, success of the decryption, and other * secrets. */ if (output_max_len != 0) { memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size); } /* Report the amount of data we copied to the output buffer. In case * of errors (bad padding or output too large), the value of *olen * when this function returns is not specified. Making it equivalent * to the good case limits the risks of leaking the padding validity. */ *olen = plaintext_size; return ret; } #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ #if !defined(MBEDTLS_RSA_ALT) int mbedtls_rsa_import(mbedtls_rsa_context *ctx, const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((N != NULL && (ret = mbedtls_mpi_copy(&ctx->N, N)) != 0) || (P != NULL && (ret = mbedtls_mpi_copy(&ctx->P, P)) != 0) || (Q != NULL && (ret = mbedtls_mpi_copy(&ctx->Q, Q)) != 0) || (D != NULL && (ret = mbedtls_mpi_copy(&ctx->D, D)) != 0) || (E != NULL && (ret = mbedtls_mpi_copy(&ctx->E, E)) != 0)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } if (N != NULL) { ctx->len = mbedtls_mpi_size(&ctx->N); } return 0; } int mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx, unsigned char const *N, size_t N_len, unsigned char const *P, size_t P_len, unsigned char const *Q, size_t Q_len, unsigned char const *D, size_t D_len, unsigned char const *E, size_t E_len) { int ret = 0; if (N != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->N, N, N_len)); ctx->len = mbedtls_mpi_size(&ctx->N); } if (P != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->P, P, P_len)); } if (Q != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->Q, Q, Q_len)); } if (D != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->D, D, D_len)); } if (E != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->E, E, E_len)); } cleanup: if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } return 0; } /* * Checks whether the context fields are set in such a way * that the RSA primitives will be able to execute without error. * It does *not* make guarantees for consistency of the parameters. */ static int rsa_check_context(mbedtls_rsa_context const *ctx, int is_priv, int blinding_needed) { #if !defined(MBEDTLS_RSA_NO_CRT) /* blinding_needed is only used for NO_CRT to decide whether * P,Q need to be present or not. */ ((void) blinding_needed); #endif if (ctx->len != mbedtls_mpi_size(&ctx->N) || ctx->len > MBEDTLS_MPI_MAX_SIZE) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * 1. Modular exponentiation needs positive, odd moduli. */ /* Modular exponentiation wrt. N is always used for * RSA public key operations. */ if (mbedtls_mpi_cmp_int(&ctx->N, 0) <= 0 || mbedtls_mpi_get_bit(&ctx->N, 0) == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #if !defined(MBEDTLS_RSA_NO_CRT) /* Modular exponentiation for P and Q is only * used for private key operations and if CRT * is used. */ if (is_priv && (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 || mbedtls_mpi_get_bit(&ctx->P, 0) == 0 || mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0 || mbedtls_mpi_get_bit(&ctx->Q, 0) == 0)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #endif /* !MBEDTLS_RSA_NO_CRT */ /* * 2. Exponents must be positive */ /* Always need E for public key operations */ if (mbedtls_mpi_cmp_int(&ctx->E, 0) <= 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #if defined(MBEDTLS_RSA_NO_CRT) /* For private key operations, use D or DP & DQ * as (unblinded) exponents. */ if (is_priv && mbedtls_mpi_cmp_int(&ctx->D, 0) <= 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #else if (is_priv && (mbedtls_mpi_cmp_int(&ctx->DP, 0) <= 0 || mbedtls_mpi_cmp_int(&ctx->DQ, 0) <= 0)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #endif /* MBEDTLS_RSA_NO_CRT */ /* Blinding shouldn't make exponents negative either, * so check that P, Q >= 1 if that hasn't yet been * done as part of 1. */ #if defined(MBEDTLS_RSA_NO_CRT) if (is_priv && blinding_needed && (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 || mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #endif /* It wouldn't lead to an error if it wasn't satisfied, * but check for QP >= 1 nonetheless. */ #if !defined(MBEDTLS_RSA_NO_CRT) if (is_priv && mbedtls_mpi_cmp_int(&ctx->QP, 0) <= 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #endif return 0; } int mbedtls_rsa_complete(mbedtls_rsa_context *ctx) { int ret = 0; int have_N, have_P, have_Q, have_D, have_E; #if !defined(MBEDTLS_RSA_NO_CRT) int have_DP, have_DQ, have_QP; #endif int n_missing, pq_missing, d_missing, is_pub, is_priv; have_N = (mbedtls_mpi_cmp_int(&ctx->N, 0) != 0); have_P = (mbedtls_mpi_cmp_int(&ctx->P, 0) != 0); have_Q = (mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0); have_D = (mbedtls_mpi_cmp_int(&ctx->D, 0) != 0); have_E = (mbedtls_mpi_cmp_int(&ctx->E, 0) != 0); #if !defined(MBEDTLS_RSA_NO_CRT) have_DP = (mbedtls_mpi_cmp_int(&ctx->DP, 0) != 0); have_DQ = (mbedtls_mpi_cmp_int(&ctx->DQ, 0) != 0); have_QP = (mbedtls_mpi_cmp_int(&ctx->QP, 0) != 0); #endif /* * Check whether provided parameters are enough * to deduce all others. The following incomplete * parameter sets for private keys are supported: * * (1) P, Q missing. * (2) D and potentially N missing. * */ n_missing = have_P && have_Q && have_D && have_E; pq_missing = have_N && !have_P && !have_Q && have_D && have_E; d_missing = have_P && have_Q && !have_D && have_E; is_pub = have_N && !have_P && !have_Q && !have_D && have_E; /* These three alternatives are mutually exclusive */ is_priv = n_missing || pq_missing || d_missing; if (!is_priv && !is_pub) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * Step 1: Deduce N if P, Q are provided. */ if (!have_N && have_P && have_Q) { if ((ret = mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } ctx->len = mbedtls_mpi_size(&ctx->N); } /* * Step 2: Deduce and verify all remaining core parameters. */ if (pq_missing) { ret = mbedtls_rsa_deduce_primes(&ctx->N, &ctx->E, &ctx->D, &ctx->P, &ctx->Q); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } } else if (d_missing) { if ((ret = mbedtls_rsa_deduce_private_exponent(&ctx->P, &ctx->Q, &ctx->E, &ctx->D)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } } /* * Step 3: Deduce all additional parameters specific * to our current RSA implementation. */ #if !defined(MBEDTLS_RSA_NO_CRT) if (is_priv && !(have_DP && have_DQ && have_QP)) { ret = mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } } #endif /* MBEDTLS_RSA_NO_CRT */ /* * Step 3: Basic sanity checks */ return rsa_check_context(ctx, is_priv, 1); } int mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx, unsigned char *N, size_t N_len, unsigned char *P, size_t P_len, unsigned char *Q, size_t Q_len, unsigned char *D, size_t D_len, unsigned char *E, size_t E_len) { int ret = 0; int is_priv; /* Check if key is private or public */ is_priv = mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->E, 0) != 0; if (!is_priv) { /* If we're trying to export private parameters for a public key, * something must be wrong. */ if (P != NULL || Q != NULL || D != NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } } if (N != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->N, N, N_len)); } if (P != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->P, P, P_len)); } if (Q != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->Q, Q, Q_len)); } if (D != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->D, D, D_len)); } if (E != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->E, E, E_len)); } cleanup: return ret; } int mbedtls_rsa_export(const mbedtls_rsa_context *ctx, mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, mbedtls_mpi *D, mbedtls_mpi *E) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int is_priv; /* Check if key is private or public */ is_priv = mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->E, 0) != 0; if (!is_priv) { /* If we're trying to export private parameters for a public key, * something must be wrong. */ if (P != NULL || Q != NULL || D != NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } } /* Export all requested core parameters. */ if ((N != NULL && (ret = mbedtls_mpi_copy(N, &ctx->N)) != 0) || (P != NULL && (ret = mbedtls_mpi_copy(P, &ctx->P)) != 0) || (Q != NULL && (ret = mbedtls_mpi_copy(Q, &ctx->Q)) != 0) || (D != NULL && (ret = mbedtls_mpi_copy(D, &ctx->D)) != 0) || (E != NULL && (ret = mbedtls_mpi_copy(E, &ctx->E)) != 0)) { return ret; } return 0; } /* * Export CRT parameters * This must also be implemented if CRT is not used, for being able to * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt * can be used in this case. */ int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int is_priv; /* Check if key is private or public */ is_priv = mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->E, 0) != 0; if (!is_priv) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #if !defined(MBEDTLS_RSA_NO_CRT) /* Export all requested blinding parameters. */ if ((DP != NULL && (ret = mbedtls_mpi_copy(DP, &ctx->DP)) != 0) || (DQ != NULL && (ret = mbedtls_mpi_copy(DQ, &ctx->DQ)) != 0) || (QP != NULL && (ret = mbedtls_mpi_copy(QP, &ctx->QP)) != 0)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } #else if ((ret = mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D, DP, DQ, QP)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } #endif return 0; } /* * Initialize an RSA context */ void mbedtls_rsa_init(mbedtls_rsa_context *ctx) { memset(ctx, 0, sizeof(mbedtls_rsa_context)); ctx->padding = MBEDTLS_RSA_PKCS_V15; ctx->hash_id = MBEDTLS_MD_NONE; #if defined(MBEDTLS_THREADING_C) /* Set ctx->ver to nonzero to indicate that the mutex has been * initialized and will need to be freed. */ ctx->ver = 1; mbedtls_mutex_init(&ctx->mutex); #endif } /* * Set padding for an existing RSA context */ int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, mbedtls_md_type_t hash_id) { switch (padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: break; #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: break; #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } #if defined(MBEDTLS_PKCS1_V21) if ((padding == MBEDTLS_RSA_PKCS_V21) && (hash_id != MBEDTLS_MD_NONE)) { /* Just make sure this hash is supported in this build. */ if (mbedtls_md_info_from_type(hash_id) == NULL) { return MBEDTLS_ERR_RSA_INVALID_PADDING; } } #endif /* MBEDTLS_PKCS1_V21 */ ctx->padding = padding; ctx->hash_id = hash_id; return 0; } /* * Get padding mode of initialized RSA context */ int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx) { return ctx->padding; } /* * Get hash identifier of mbedtls_md_type_t type */ int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx) { return ctx->hash_id; } /* * Get length in bits of RSA modulus */ size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx) { return mbedtls_mpi_bitlen(&ctx->N); } /* * Get length in bytes of RSA modulus */ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx) { return ctx->len; } #if defined(MBEDTLS_GENPRIME) /* * Generate an RSA keypair * * This generation method follows the RSA key pair generation procedure of * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. */ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, unsigned int nbits, int exponent) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi H, G, L; int prime_quality = 0; /* * If the modulus is 1024 bit long or shorter, then the security strength of * the RSA algorithm is less than or equal to 80 bits and therefore an error * rate of 2^-80 is sufficient. */ if (nbits > 1024) { prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; } mbedtls_mpi_init(&H); mbedtls_mpi_init(&G); mbedtls_mpi_init(&L); if (exponent < 3 || nbits % 2 != 0) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } if (nbits < MBEDTLS_RSA_GEN_KEY_MIN_BITS) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } /* * find primes P and Q with Q < P so that: * 1. |P-Q| > 2^( nbits / 2 - 100 ) * 2. GCD( E, (P-1)*(Q-1) ) == 1 * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->E, exponent)); do { MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->P, nbits >> 1, prime_quality, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->Q, nbits >> 1, prime_quality, f_rng, p_rng)); /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&H, &ctx->P, &ctx->Q)); if (mbedtls_mpi_bitlen(&H) <= ((nbits >= 200) ? ((nbits >> 1) - 99) : 0)) { continue; } /* not required by any standards, but some users rely on the fact that P > Q */ if (H.s < 0) { mbedtls_mpi_swap(&ctx->P, &ctx->Q); } /* Temporarily replace P,Q by P-1, Q-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->P, &ctx->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->Q, &ctx->Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&H, &ctx->P, &ctx->Q)); /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->E, &H)); if (mbedtls_mpi_cmp_int(&G, 1) != 0) { continue; } /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->P, &ctx->Q)); MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&L, NULL, &H, &G)); MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->D, &ctx->E, &L)); if (mbedtls_mpi_bitlen(&ctx->D) <= ((nbits + 1) / 2)) { // (FIPS 186-4 §B.3.1 criterion 3(a)) continue; } break; } while (1); /* Restore P,Q */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->P, &ctx->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->Q, &ctx->Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q)); ctx->len = mbedtls_mpi_size(&ctx->N); #if !defined(MBEDTLS_RSA_NO_CRT) /* * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ MBEDTLS_MPI_CHK(mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP)); #endif /* MBEDTLS_RSA_NO_CRT */ /* Double-check */ MBEDTLS_MPI_CHK(mbedtls_rsa_check_privkey(ctx)); cleanup: mbedtls_mpi_free(&H); mbedtls_mpi_free(&G); mbedtls_mpi_free(&L); if (ret != 0) { mbedtls_rsa_free(ctx); if ((-ret & ~0x7f) == 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret); } return ret; } return 0; } #endif /* MBEDTLS_GENPRIME */ /* * Check a public RSA key */ int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx) { if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } if (mbedtls_mpi_bitlen(&ctx->N) < 128) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } if (mbedtls_mpi_get_bit(&ctx->E, 0) == 0 || mbedtls_mpi_bitlen(&ctx->E) < 2 || mbedtls_mpi_cmp_mpi(&ctx->E, &ctx->N) >= 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } return 0; } /* * Check for the consistency of all fields in an RSA private key context */ int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx) { if (mbedtls_rsa_check_pubkey(ctx) != 0 || rsa_check_context(ctx, 1 /* private */, 1 /* blinding */) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } if (mbedtls_rsa_validate_params(&ctx->N, &ctx->P, &ctx->Q, &ctx->D, &ctx->E, NULL, NULL) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } #if !defined(MBEDTLS_RSA_NO_CRT) else if (mbedtls_rsa_validate_crt(&ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } #endif return 0; } /* * Check if contexts holding a public and private key match */ int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv) { if (mbedtls_rsa_check_pubkey(pub) != 0 || mbedtls_rsa_check_privkey(prv) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } if (mbedtls_mpi_cmp_mpi(&pub->N, &prv->N) != 0 || mbedtls_mpi_cmp_mpi(&pub->E, &prv->E) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } return 0; } /* * Do an RSA public key operation */ int mbedtls_rsa_public(mbedtls_rsa_context *ctx, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; mbedtls_mpi T; if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } mbedtls_mpi_init(&T); #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len)); if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } olen = ctx->len; MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod_unsafe(&T, &T, &ctx->E, &ctx->N, &ctx->RN)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen)); cleanup: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif mbedtls_mpi_free(&T); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret); } return 0; } /* * Generate or update blinding values, see section 10 of: * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer * Berlin Heidelberg, 1996. p. 104-113. */ static int rsa_prepare_blinding(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, count = 0; mbedtls_mpi R; mbedtls_mpi_init(&R); if (ctx->Vf.p != NULL) { /* We already have blinding values, just update them by squaring */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->N)); goto cleanup; } /* Unblinding value: Vf = random number, invertible mod N */ do { if (count++ > 10) { ret = MBEDTLS_ERR_RSA_RNG_FAILED; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->Vf, ctx->len - 1, f_rng, p_rng)); /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, ctx->len - 1, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vf, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N)); /* At this point, Vi is invertible mod N if and only if both Vf and R * are invertible mod N. If one of them isn't, we don't need to know * which one, we just loop and choose new values for both of them. * (Each iteration succeeds with overwhelming probability.) */ ret = mbedtls_mpi_inv_mod(&ctx->Vi, &ctx->Vi, &ctx->N); if (ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { goto cleanup; } } while (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE); /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N)); /* Blinding value: Vi = Vf^(-e) mod N * (Vi already contains Vf^-1 at this point) */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN)); cleanup: mbedtls_mpi_free(&R); return ret; } /* * Unblind * T = T * Vf mod N */ static int rsa_unblind(mbedtls_mpi *T, mbedtls_mpi *Vf, const mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p); const size_t nlimbs = N->n; const size_t tlimbs = mbedtls_mpi_core_montmul_working_limbs(nlimbs); mbedtls_mpi RR, M_T; mbedtls_mpi_init(&RR); mbedtls_mpi_init(&M_T); MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&M_T, tlimbs)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(T, nlimbs)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Vf, nlimbs)); /* T = T * Vf mod N * Reminder: montmul(A, B, N) = A * B * R^-1 mod N * Usually both operands are multiplied by R mod N beforehand (by calling * `to_mont_rep()` on them), yielding a result that's also * R mod N (aka * "in the Montgomery domain"). Here we only multiply one operand by R mod * N, so the result is directly what we want - no need to call * `from_mont_rep()` on it. */ mbedtls_mpi_core_to_mont_rep(T->p, T->p, N->p, nlimbs, mm, RR.p, M_T.p); mbedtls_mpi_core_montmul(T->p, T->p, Vf->p, nlimbs, N->p, nlimbs, mm, M_T.p); cleanup: mbedtls_mpi_free(&RR); mbedtls_mpi_free(&M_T); return ret; } /* * Exponent blinding supposed to prevent side-channel attacks using multiple * traces of measurements to recover the RSA key. The more collisions are there, * the more bits of the key can be recovered. See [3]. * * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) * observations on average. * * For example with 28 byte blinding to achieve 2 collisions the adversary has * to make 2^112 observations on average. * * (With the currently (as of 2017 April) known best algorithms breaking 2048 * bit RSA requires approximately as much time as trying out 2^112 random keys. * Thus in this sense with 28 byte blinding the security is not reduced by * side-channel attacks like the one in [3]) * * This countermeasure does not help if the key recovery is possible with a * single trace. */ #define RSA_EXPONENT_BLINDING 28 /* * Do an RSA private key operation */ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; /* Temporary holding the result */ mbedtls_mpi T; /* Temporaries holding P-1, Q-1 and the * exponent blinding factor, respectively. */ mbedtls_mpi P1, Q1, R; #if !defined(MBEDTLS_RSA_NO_CRT) /* Temporaries holding the results mod p resp. mod q. */ mbedtls_mpi TP, TQ; /* Temporaries holding the blinded exponents for * the mod p resp. mod q computation (if used). */ mbedtls_mpi DP_blind, DQ_blind; #else /* Temporary holding the blinded exponent (if used). */ mbedtls_mpi D_blind; #endif /* MBEDTLS_RSA_NO_CRT */ /* Temporaries holding the initial input and the double * checked result; should be the same in the end. */ mbedtls_mpi input_blinded, check_result_blinded; if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (rsa_check_context(ctx, 1 /* private key checks */, 1 /* blinding on */) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif /* MPI Initialization */ mbedtls_mpi_init(&T); mbedtls_mpi_init(&P1); mbedtls_mpi_init(&Q1); mbedtls_mpi_init(&R); #if defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_init(&D_blind); #else mbedtls_mpi_init(&DP_blind); mbedtls_mpi_init(&DQ_blind); #endif #if !defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_init(&TP); mbedtls_mpi_init(&TQ); #endif mbedtls_mpi_init(&input_blinded); mbedtls_mpi_init(&check_result_blinded); /* End of MPI initialization */ MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len)); if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } /* * Blinding * T = T * Vi mod N */ MBEDTLS_MPI_CHK(rsa_prepare_blinding(ctx, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&input_blinded, &T)); /* * Exponent blinding */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&P1, &ctx->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&Q1, &ctx->Q, 1)); #if defined(MBEDTLS_RSA_NO_CRT) /* * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D)); #else /* * DP_blind = ( P - 1 ) * R + DP */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DP_blind, &P1, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind, &ctx->DP)); /* * DQ_blind = ( Q - 1 ) * R + DQ */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind, &ctx->DQ)); #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_RSA_NO_CRT) MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &D_blind, &ctx->N, &ctx->RN)); #else /* * Faster decryption using the CRT * * TP = input ^ dP mod P * TQ = input ^ dQ mod Q */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, &DP_blind, &ctx->P, &ctx->RP)); MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, &DQ_blind, &ctx->Q, &ctx->RQ)); /* * T = (TP - TQ) * (Q^-1 mod P) mod P */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&T, &TP, &TQ)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->QP)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &TP, &ctx->P)); /* * T = TQ + T * Q */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->Q)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP)); #endif /* MBEDTLS_RSA_NO_CRT */ /* Verify the result to prevent glitching attacks. */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&check_result_blinded, &T, &ctx->E, &ctx->N, &ctx->RN)); if (mbedtls_mpi_cmp_mpi(&check_result_blinded, &input_blinded) != 0) { ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; goto cleanup; } /* * Unblind * T = T * Vf mod N */ MBEDTLS_MPI_CHK(rsa_unblind(&T, &ctx->Vf, &ctx->N)); olen = ctx->len; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen)); cleanup: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif mbedtls_mpi_free(&P1); mbedtls_mpi_free(&Q1); mbedtls_mpi_free(&R); #if defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_free(&D_blind); #else mbedtls_mpi_free(&DP_blind); mbedtls_mpi_free(&DQ_blind); #endif mbedtls_mpi_free(&T); #if !defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_free(&TP); mbedtls_mpi_free(&TQ); #endif mbedtls_mpi_free(&check_result_blinded); mbedtls_mpi_free(&input_blinded); if (ret != 0 && ret >= -0x007f) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret); } return ret; } #if defined(MBEDTLS_PKCS1_V21) /** * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. * * \param dst buffer to mask * \param dlen length of destination buffer * \param src source of the mask generation * \param slen length of the source buffer * \param md_alg message digest to use */ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src, size_t slen, mbedtls_md_type_t md_alg) { unsigned char counter[4]; unsigned char *p; unsigned int hlen; size_t i, use_len; unsigned char mask[MBEDTLS_MD_MAX_SIZE]; int ret = 0; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; mbedtls_md_init(&md_ctx); md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } mbedtls_md_init(&md_ctx); if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { goto exit; } hlen = mbedtls_md_get_size(md_info); memset(mask, 0, sizeof(mask)); memset(counter, 0, 4); /* Generate and apply dbMask */ p = dst; while (dlen > 0) { use_len = hlen; if (dlen < hlen) { use_len = dlen; } if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, src, slen)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, counter, 4)) != 0) { goto exit; } if ((ret = mbedtls_md_finish(&md_ctx, mask)) != 0) { goto exit; } for (i = 0; i < use_len; ++i) { *p++ ^= mask[i]; } counter[3]++; dlen -= use_len; } exit: mbedtls_platform_zeroize(mask, sizeof(mask)); mbedtls_md_free(&md_ctx); return ret; } /** * Generate Hash(M') as in RFC 8017 page 43 points 5 and 6. * * \param hash the input hash * \param hlen length of the input hash * \param salt the input salt * \param slen length of the input salt * \param out the output buffer - must be large enough for \p md_alg * \param md_alg message digest to use */ static int hash_mprime(const unsigned char *hash, size_t hlen, const unsigned char *salt, size_t slen, unsigned char *out, mbedtls_md_type_t md_alg) { const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; mbedtls_md_context_t md_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } mbedtls_md_init(&md_ctx); if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { goto exit; } if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, zeros, sizeof(zeros))) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, hash, hlen)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, salt, slen)) != 0) { goto exit; } if ((ret = mbedtls_md_finish(&md_ctx, out)) != 0) { goto exit; } exit: mbedtls_md_free(&md_ctx); return ret; } /** * Compute a hash. * * \param md_alg algorithm to use * \param input input message to hash * \param ilen input length * \param output the output buffer - must be large enough for \p md_alg */ static int compute_hash(mbedtls_md_type_t md_alg, const unsigned char *input, size_t ilen, unsigned char *output) { const mbedtls_md_info_t *md_info; md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return mbedtls_md(md_info, input, ilen, output); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V21) /* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function */ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *label, size_t label_len, size_t ilen, const unsigned char *input, unsigned char *output) { size_t olen; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = output; unsigned int hlen; if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id); if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } olen = ctx->len; /* first comparison checks for overflow */ if (ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } memset(output, 0, olen); *p++ = 0; /* Generate a random octet string seed */ if ((ret = f_rng(p_rng, p, hlen)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret); } p += hlen; /* Construct DB */ ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, label, label_len, p); if (ret != 0) { return ret; } p += hlen; p += olen - 2 * hlen - 2 - ilen; *p++ = 1; if (ilen != 0) { memcpy(p, input, ilen); } /* maskedDB: Apply dbMask to DB */ if ((ret = mgf_mask(output + hlen + 1, olen - hlen - 1, output + 1, hlen, (mbedtls_md_type_t) ctx->hash_id)) != 0) { return ret; } /* maskedSeed: Apply seedMask to seed */ if ((ret = mgf_mask(output + 1, hlen, output + hlen + 1, olen - hlen - 1, (mbedtls_md_type_t) ctx->hash_id)) != 0) { return ret; } return mbedtls_rsa_public(ctx, output, output); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) /* * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function */ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t ilen, const unsigned char *input, unsigned char *output) { size_t nb_pad, olen; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = output; olen = ctx->len; /* first comparison checks for overflow */ if (ilen + 11 < ilen || olen < ilen + 11) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } nb_pad = olen - 3 - ilen; *p++ = 0; if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } *p++ = MBEDTLS_RSA_CRYPT; while (nb_pad-- > 0) { int rng_dl = 100; do { ret = f_rng(p_rng, p, 1); } while (*p == 0 && --rng_dl && ret == 0); /* Check if RNG failed to generate data */ if (rng_dl == 0 || ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret); } p++; } *p++ = 0; if (ilen != 0) { memcpy(p, input, ilen); } return mbedtls_rsa_public(ctx, output, output); } #endif /* MBEDTLS_PKCS1_V15 */ /* * Add the message padding, then do an RSA operation */ int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t ilen, const unsigned char *input, unsigned char *output) { switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: return mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx, f_rng, p_rng, ilen, input, output); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: return mbedtls_rsa_rsaes_oaep_encrypt(ctx, f_rng, p_rng, NULL, 0, ilen, input, output); #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } } #if defined(MBEDTLS_PKCS1_V21) /* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function */ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t ilen, i, pad_len; unsigned char *p; mbedtls_ct_condition_t bad, in_padding; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; unsigned int hlen; /* * Parameters sanity checks */ if (ctx->padding != MBEDTLS_RSA_PKCS_V21) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } ilen = ctx->len; if (ilen < 16 || ilen > sizeof(buf)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id); if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } // checking for integer underflow if (2 * hlen + 2 > ilen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * RSA operation */ ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); if (ret != 0) { goto cleanup; } /* * Unmask data and generate lHash */ /* seed: Apply seedMask to maskedSeed */ if ((ret = mgf_mask(buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, (mbedtls_md_type_t) ctx->hash_id)) != 0 || /* DB: Apply dbMask to maskedDB */ (ret = mgf_mask(buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, (mbedtls_md_type_t) ctx->hash_id)) != 0) { goto cleanup; } /* Generate lHash */ ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, label, label_len, lhash); if (ret != 0) { goto cleanup; } /* * Check contents, in "constant-time" */ p = buf; bad = mbedtls_ct_bool(*p++); /* First byte must be 0 */ p += hlen; /* Skip seed */ /* Check lHash */ bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool(mbedtls_ct_memcmp(lhash, p, hlen))); p += hlen; /* Get zero-padding len, but always read till end of buffer * (minus one, for the 01 byte) */ pad_len = 0; in_padding = MBEDTLS_CT_TRUE; for (i = 0; i < ilen - 2 * hlen - 2; i++) { in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_uint_eq(p[i], 0)); pad_len += mbedtls_ct_uint_if_else_0(in_padding, 1); } p += pad_len; bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(*p++, 0x01)); /* * The only information "leaked" is whether the padding was correct or not * (eg, no data is copied if it was not correct). This meets the * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between * the different error conditions. */ if (bad != MBEDTLS_CT_FALSE) { ret = MBEDTLS_ERR_RSA_INVALID_PADDING; goto cleanup; } if (ilen - ((size_t) (p - buf)) > output_max_len) { ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; goto cleanup; } *olen = ilen - ((size_t) (p - buf)); if (*olen != 0) { memcpy(output, p, *olen); } ret = 0; cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize(lhash, sizeof(lhash)); return ret; } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) /* * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function */ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t ilen; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; ilen = ctx->len; if (ctx->padding != MBEDTLS_RSA_PKCS_V15) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (ilen < 16 || ilen > sizeof(buf)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); if (ret != 0) { goto cleanup; } ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding(buf, ilen, output, output_max_len, olen); cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } #endif /* MBEDTLS_PKCS1_V15 */ /* * Do an RSA operation, then remove the message padding */ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len) { switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: return mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx, f_rng, p_rng, olen, input, output, output_max_len); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: return mbedtls_rsa_rsaes_oaep_decrypt(ctx, f_rng, p_rng, NULL, 0, olen, input, output, output_max_len); #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } } #if defined(MBEDTLS_PKCS1_V21) static int rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, int saltlen, unsigned char *sig) { size_t olen; unsigned char *p = sig; unsigned char *salt = NULL; size_t slen, min_slen, hlen, offset = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t msb; mbedtls_md_type_t hash_id; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } olen = ctx->len; if (md_alg != MBEDTLS_MD_NONE) { /* Gather length of hash to sign */ size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg); if (exp_hashlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (hashlen != exp_hashlen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } } hash_id = (mbedtls_md_type_t) ctx->hash_id; if (hash_id == MBEDTLS_MD_NONE) { hash_id = md_alg; } hlen = mbedtls_md_get_size_from_type(hash_id); if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY) { /* Calculate the largest possible salt length, up to the hash size. * Normally this is the hash length, which is the maximum salt length * according to FIPS 185-4 §5.5 (e) and common practice. If there is not * enough room, use the maximum salt length that fits. The constraint is * that the hash length plus the salt length plus 2 bytes must be at most * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 * (PKCS#1 v2.2) §9.1.1 step 3. */ min_slen = hlen - 2; if (olen < hlen + min_slen + 2) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } else if (olen >= hlen + hlen + 2) { slen = hlen; } else { slen = olen - hlen - 2; } } else if ((saltlen < 0) || (saltlen + hlen + 2 > olen)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } else { slen = (size_t) saltlen; } memset(sig, 0, olen); /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ msb = mbedtls_mpi_bitlen(&ctx->N) - 1; p += olen - hlen - slen - 2; *p++ = 0x01; /* Generate salt of length slen in place in the encoded message */ salt = p; if ((ret = f_rng(p_rng, salt, slen)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret); } p += slen; /* Generate H = Hash( M' ) */ ret = hash_mprime(hash, hashlen, salt, slen, p, hash_id); if (ret != 0) { return ret; } /* Compensate for boundary condition when applying mask */ if (msb % 8 == 0) { offset = 1; } /* maskedDB: Apply dbMask to DB */ ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen, hash_id); if (ret != 0) { return ret; } msb = mbedtls_mpi_bitlen(&ctx->N) - 1; sig[0] &= 0xFF >> (olen * 8 - msb); p += hlen; *p++ = 0xBC; return mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig); } static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, int saltlen, unsigned char *sig) { if (ctx->padding != MBEDTLS_RSA_PKCS_V21) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if ((ctx->hash_id == MBEDTLS_MD_NONE) && (md_alg == MBEDTLS_MD_NONE)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen, sig); } int mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig); } /* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with * the option to pass in the salt length. */ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, int saltlen, unsigned char *sig) { return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen, sig); } /* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function */ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) /* * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function */ /* Construct a PKCS v1.5 encoding of a hashed message * * This is used both for signature generation and verification. * * Parameters: * - md_alg: Identifies the hash algorithm used to generate the given hash; * MBEDTLS_MD_NONE if raw data is signed. * - hashlen: Length of hash. Must match md_alg if that's not NONE. * - hash: Buffer containing the hashed message or the raw data. * - dst_len: Length of the encoded message. * - dst: Buffer to hold the encoded message. * * Assumptions: * - hash has size hashlen. * - dst points to a buffer of size at least dst_len. * */ static int rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, size_t dst_len, unsigned char *dst) { size_t oid_size = 0; size_t nb_pad = dst_len; unsigned char *p = dst; const char *oid = NULL; /* Are we signing hashed or raw data? */ if (md_alg != MBEDTLS_MD_NONE) { unsigned char md_size = mbedtls_md_get_size_from_type(md_alg); if (md_size == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (mbedtls_oid_get_oid_by_md(md_alg, &oid, &oid_size) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (hashlen != md_size) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* Double-check that 8 + hashlen + oid_size can be used as a * 1-byte ASN.1 length encoding and that there's no overflow. */ if (8 + hashlen + oid_size >= 0x80 || 10 + hashlen < hashlen || 10 + hashlen + oid_size < 10 + hashlen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * Static bounds check: * - Need 10 bytes for five tag-length pairs. * (Insist on 1-byte length encodings to protect against variants of * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) * - Need hashlen bytes for hash * - Need oid_size bytes for hash alg OID. */ if (nb_pad < 10 + hashlen + oid_size) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } nb_pad -= 10 + hashlen + oid_size; } else { if (nb_pad < hashlen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } nb_pad -= hashlen; } /* Need space for signature header and padding delimiter (3 bytes), * and 8 bytes for the minimal padding */ if (nb_pad < 3 + 8) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } nb_pad -= 3; /* Now nb_pad is the amount of memory to be filled * with padding, and at least 8 bytes long. */ /* Write signature header and padding */ *p++ = 0; *p++ = MBEDTLS_RSA_SIGN; memset(p, 0xFF, nb_pad); p += nb_pad; *p++ = 0; /* Are we signing raw data? */ if (md_alg == MBEDTLS_MD_NONE) { memcpy(p, hash, hashlen); return 0; } /* Signing hashed data, add corresponding ASN.1 structure * * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest } * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * Digest ::= OCTET STRING * * Schematic: * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] * TAG-NULL + LEN [ NULL ] ] * TAG-OCTET + LEN [ HASH ] ] */ *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; *p++ = (unsigned char) (0x08 + oid_size + hashlen); *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; *p++ = (unsigned char) (0x04 + oid_size); *p++ = MBEDTLS_ASN1_OID; *p++ = (unsigned char) oid_size; memcpy(p, oid, oid_size); p += oid_size; *p++ = MBEDTLS_ASN1_NULL; *p++ = 0x00; *p++ = MBEDTLS_ASN1_OCTET_STRING; *p++ = (unsigned char) hashlen; memcpy(p, hash, hashlen); p += hashlen; /* Just a sanity-check, should be automatic * after the initial bounds check. */ if (p != dst + dst_len) { mbedtls_platform_zeroize(dst, dst_len); return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return 0; } /* * Do an RSA operation to sign the message digest */ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *sig_try = NULL, *verif = NULL; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (ctx->padding != MBEDTLS_RSA_PKCS_V15) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * Prepare PKCS1-v1.5 encoding (padding and hash identifier) */ if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash, ctx->len, sig)) != 0) { return ret; } /* Private key operation * * In order to prevent Lenstra's attack, make the signature in a * temporary buffer and check it before returning it. */ sig_try = mbedtls_calloc(1, ctx->len); if (sig_try == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } verif = mbedtls_calloc(1, ctx->len); if (verif == NULL) { mbedtls_free(sig_try); return MBEDTLS_ERR_MPI_ALLOC_FAILED; } MBEDTLS_MPI_CHK(mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig_try)); MBEDTLS_MPI_CHK(mbedtls_rsa_public(ctx, sig_try, verif)); if (mbedtls_ct_memcmp(verif, sig, ctx->len) != 0) { ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; goto cleanup; } memcpy(sig, sig_try, ctx->len); cleanup: mbedtls_zeroize_and_free(sig_try, ctx->len); mbedtls_zeroize_and_free(verif, ctx->len); if (ret != 0) { memset(sig, '!', ctx->len); } return ret; } #endif /* MBEDTLS_PKCS1_V15 */ /* * Do an RSA operation to sign the message digest */ int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: return mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, sig); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: return mbedtls_rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, sig); #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } } #if defined(MBEDTLS_PKCS1_V21) /* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function */ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, mbedtls_md_type_t mgf1_hash_id, int expected_salt_len, const unsigned char *sig) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t siglen; unsigned char *p; unsigned char *hash_start; unsigned char result[MBEDTLS_MD_MAX_SIZE]; unsigned int hlen; size_t observed_salt_len, msb; unsigned char buf[MBEDTLS_MPI_MAX_SIZE] = { 0 }; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } siglen = ctx->len; if (siglen < 16 || siglen > sizeof(buf)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } ret = mbedtls_rsa_public(ctx, sig, buf); if (ret != 0) { return ret; } p = buf; if (buf[siglen - 1] != 0xBC) { return MBEDTLS_ERR_RSA_INVALID_PADDING; } if (md_alg != MBEDTLS_MD_NONE) { /* Gather length of hash to sign */ size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg); if (exp_hashlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (hashlen != exp_hashlen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } } hlen = mbedtls_md_get_size_from_type(mgf1_hash_id); if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * Note: EMSA-PSS verification is over the length of N - 1 bits */ msb = mbedtls_mpi_bitlen(&ctx->N) - 1; if (buf[0] >> (8 - siglen * 8 + msb)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* Compensate for boundary condition when applying mask */ if (msb % 8 == 0) { p++; siglen -= 1; } if (siglen < hlen + 2) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } hash_start = p + siglen - hlen - 1; ret = mgf_mask(p, siglen - hlen - 1, hash_start, hlen, mgf1_hash_id); if (ret != 0) { return ret; } buf[0] &= 0xFF >> (siglen * 8 - msb); while (p < hash_start - 1 && *p == 0) { p++; } if (*p++ != 0x01) { return MBEDTLS_ERR_RSA_INVALID_PADDING; } observed_salt_len = (size_t) (hash_start - p); if (expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && observed_salt_len != (size_t) expected_salt_len) { return MBEDTLS_ERR_RSA_INVALID_PADDING; } /* * Generate H = Hash( M' ) */ ret = hash_mprime(hash, hashlen, p, observed_salt_len, result, mgf1_hash_id); if (ret != 0) { return ret; } if (memcmp(hash_start, result, hlen) != 0) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } return 0; } /* * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function */ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig) { mbedtls_md_type_t mgf1_hash_id; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } mgf1_hash_id = (ctx->hash_id != MBEDTLS_MD_NONE) ? (mbedtls_md_type_t) ctx->hash_id : md_alg; return mbedtls_rsa_rsassa_pss_verify_ext(ctx, md_alg, hashlen, hash, mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, sig); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) /* * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function */ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig) { int ret = 0; size_t sig_len; unsigned char *encoded = NULL, *encoded_expected = NULL; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } sig_len = ctx->len; /* * Prepare expected PKCS1 v1.5 encoding of hash. */ if ((encoded = mbedtls_calloc(1, sig_len)) == NULL || (encoded_expected = mbedtls_calloc(1, sig_len)) == NULL) { ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; goto cleanup; } if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash, sig_len, encoded_expected)) != 0) { goto cleanup; } /* * Apply RSA primitive to get what should be PKCS1 encoded hash. */ ret = mbedtls_rsa_public(ctx, sig, encoded); if (ret != 0) { goto cleanup; } /* * Compare */ if ((ret = mbedtls_ct_memcmp(encoded, encoded_expected, sig_len)) != 0) { ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; goto cleanup; } cleanup: if (encoded != NULL) { mbedtls_zeroize_and_free(encoded, sig_len); } if (encoded_expected != NULL) { mbedtls_zeroize_and_free(encoded_expected, sig_len); } return ret; } #endif /* MBEDTLS_PKCS1_V15 */ /* * Do an RSA operation and check the message digest */ int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig) { if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: return mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx, md_alg, hashlen, hash, sig); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: return mbedtls_rsa_rsassa_pss_verify(ctx, md_alg, hashlen, hash, sig); #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } } /* * Copy the components of an RSA key */ int mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; dst->len = src->len; MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->N, &src->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->E, &src->E)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->D, &src->D)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->P, &src->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Q, &src->Q)); #if !defined(MBEDTLS_RSA_NO_CRT) MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DP, &src->DP)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DQ, &src->DQ)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->QP, &src->QP)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RP, &src->RP)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RQ, &src->RQ)); #endif MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RN, &src->RN)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vi, &src->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vf, &src->Vf)); dst->padding = src->padding; dst->hash_id = src->hash_id; cleanup: if (ret != 0) { mbedtls_rsa_free(dst); } return ret; } /* * Free the components of an RSA key */ void mbedtls_rsa_free(mbedtls_rsa_context *ctx) { if (ctx == NULL) { return; } mbedtls_mpi_free(&ctx->Vi); mbedtls_mpi_free(&ctx->Vf); mbedtls_mpi_free(&ctx->RN); mbedtls_mpi_free(&ctx->D); mbedtls_mpi_free(&ctx->Q); mbedtls_mpi_free(&ctx->P); mbedtls_mpi_free(&ctx->E); mbedtls_mpi_free(&ctx->N); #if !defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_free(&ctx->RQ); mbedtls_mpi_free(&ctx->RP); mbedtls_mpi_free(&ctx->QP); mbedtls_mpi_free(&ctx->DQ); mbedtls_mpi_free(&ctx->DP); #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_THREADING_C) /* Free the mutex, but only if it hasn't been freed already. */ if (ctx->ver != 0) { mbedtls_mutex_free(&ctx->mutex); ctx->ver = 0; } #endif } #endif /* !MBEDTLS_RSA_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * Example RSA-1024 keypair, for test purposes */ #define KEY_LEN 128 #define RSA_N "9292758453063D803DD603D5E777D788" \ "8ED1D5BF35786190FA2F23EBC0848AEA" \ "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ "7130B9CED7ACDF54CFC7555AC14EEBAB" \ "93A89813FBF3C4F8066D2D800F7C38A8" \ "1AE31942917403FF4946B0A83D3D3E05" \ "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ "5E94BB77B07507233A0BC7BAC8F90F79" #define RSA_E "10001" #define RSA_D "24BF6185468786FDD303083D25E64EFC" \ "66CA472BC44D253102F8B4A9D3BFA750" \ "91386C0077937FE33FA3252D28855837" \ "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ "DF79C5CE07EE72C7F123142198164234" \ "CABB724CF78B8173B9F880FC86322407" \ "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ "071513A1E85B5DFA031F21ECAE91A34D" #define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ "2C01CAD19EA484A87EA4377637E75500" \ "FCB2005C5C7DD6EC4AC023CDA285D796" \ "C3D9E75E1EFC42488BB4F1D13AC30A57" #define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ "E211C2B9E5DB1ED0BF61D0D9899620F4" \ "910E4168387E3C30AA1E00C339A79508" \ "8452DD96A9A5EA5D9DCA68DA636032AF" #define PT_LEN 24 #define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" #if defined(MBEDTLS_PKCS1_V15) static int myrand(void *rng_state, unsigned char *output, size_t len) { #if !defined(__OpenBSD__) && !defined(__NetBSD__) size_t i; if (rng_state != NULL) { rng_state = NULL; } for (i = 0; i < len; ++i) { output[i] = rand(); } #else if (rng_state != NULL) { rng_state = NULL; } arc4random_buf(output, len); #endif /* !OpenBSD && !NetBSD */ return 0; } #endif /* MBEDTLS_PKCS1_V15 */ /* * Checkup routine */ int mbedtls_rsa_self_test(int verbose) { int ret = 0; #if defined(MBEDTLS_PKCS1_V15) size_t len; mbedtls_rsa_context rsa; unsigned char rsa_plaintext[PT_LEN]; unsigned char rsa_decrypted[PT_LEN]; unsigned char rsa_ciphertext[KEY_LEN]; #if defined(MBEDTLS_MD_CAN_SHA1) unsigned char sha1sum[20]; #endif mbedtls_mpi K; mbedtls_mpi_init(&K); mbedtls_rsa_init(&rsa); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_N)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, &K, NULL, NULL, NULL, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_P)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, &K, NULL, NULL, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_Q)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, &K, NULL, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_D)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, &K, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_E)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, NULL, &K)); MBEDTLS_MPI_CHK(mbedtls_rsa_complete(&rsa)); if (verbose != 0) { mbedtls_printf(" RSA key validation: "); } if (mbedtls_rsa_check_pubkey(&rsa) != 0 || mbedtls_rsa_check_privkey(&rsa) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n PKCS#1 encryption : "); } memcpy(rsa_plaintext, RSA_PT, PT_LEN); if (mbedtls_rsa_pkcs1_encrypt(&rsa, myrand, NULL, PT_LEN, rsa_plaintext, rsa_ciphertext) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n PKCS#1 decryption : "); } if (mbedtls_rsa_pkcs1_decrypt(&rsa, myrand, NULL, &len, rsa_ciphertext, rsa_decrypted, sizeof(rsa_decrypted)) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (memcmp(rsa_decrypted, rsa_plaintext, len) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } #if defined(MBEDTLS_MD_CAN_SHA1) if (verbose != 0) { mbedtls_printf(" PKCS#1 data sign : "); } if (mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), rsa_plaintext, PT_LEN, sha1sum) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } if (mbedtls_rsa_pkcs1_sign(&rsa, myrand, NULL, MBEDTLS_MD_SHA1, 20, sha1sum, rsa_ciphertext) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n PKCS#1 sig. verify: "); } if (mbedtls_rsa_pkcs1_verify(&rsa, MBEDTLS_MD_SHA1, 20, sha1sum, rsa_ciphertext) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } #endif /* MBEDTLS_MD_CAN_SHA1 */ if (verbose != 0) { mbedtls_printf("\n"); } cleanup: mbedtls_mpi_free(&K); mbedtls_rsa_free(&rsa); #else /* MBEDTLS_PKCS1_V15 */ ((void) verbose); #endif /* MBEDTLS_PKCS1_V15 */ return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_RSA_C */ webfakes/src/mbedtls/library/psa_crypto_ecp.h0000644000176200001440000003110714740737024021123 0ustar liggesusers/* * PSA ECP layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ECP_H #define PSA_CRYPTO_ECP_H #include #include /** Load the contents of a key buffer into an internal ECP representation * * \param[in] type The type of key contained in \p data. * \param[in] curve_bits The nominal bit-size of the curve. * It must be consistent with the representation * passed in \p data. * This can be 0, in which case the bit-size * is inferred from \p data_length (which is possible * for all key types and representation formats * formats that are currently supported or will * be in the foreseeable future). * \param[in] data The buffer from which to load the representation. * \param[in] data_length The size in bytes of \p data. * \param[out] p_ecp Returns a pointer to an ECP context on success. * The caller is responsible for freeing both the * contents of the context and the context itself * when done. */ psa_status_t mbedtls_psa_ecp_load_representation(psa_key_type_t type, size_t curve_bits, const uint8_t *data, size_t data_length, mbedtls_ecp_keypair **p_ecp); /** Load the public part of an internal ECP, if required. * * \param ecp The ECP context to load the public part for. * * \return PSA_SUCCESS on success, otherwise an MPI error. */ psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp); /** Import an ECP key in binary format. * * \note The signature of this function is that of a PSA driver * import_key entry point. This function behaves as an import_key * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes for the key to import. * \param[in] data The buffer containing the key data in import * format. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] key_buffer The buffer containing the key data in output * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p * key_buffer in bytes. * \param[out] bits The key size in number of bits. * * \retval #PSA_SUCCESS The ECP key was imported successfully. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key data is not correctly formatted. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_ecp_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits); /** Export an ECP key to export representation * * \param[in] type The type of key (public/private) to export * \param[in] ecp The internal ECP representation from which to export * \param[out] data The buffer to export to * \param[in] data_size The length of the buffer to export to * \param[out] data_length The amount of bytes written to \p data */ psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type, mbedtls_ecp_keypair *ecp, uint8_t *data, size_t data_size, size_t *data_length); /** Export an ECP public key or the public part of an ECP key pair in binary * format. * * \note The signature of this function is that of a PSA driver * export_public_key entry point. This function behaves as an * export_public_key entry point as defined in the PSA driver interface * specification. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data * * \retval #PSA_SUCCESS The ECP public key was exported successfully. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_ecp_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** * \brief Generate an ECP key. * * \note The signature of the function is that of a PSA driver generate_key * entry point. * * \param[in] attributes The attributes for the ECP key to generate. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in * \p key_buffer. * * \retval #PSA_SUCCESS * The key was successfully generated. * \retval #PSA_ERROR_NOT_SUPPORTED * Key length or type not supported. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. */ psa_status_t mbedtls_psa_ecp_generate_key( const psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); /** Sign an already-calculated hash with ECDSA. * * \note The signature of this function is that of a PSA driver * sign_hash entry point. This function behaves as a sign_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the ECC key to use for the * operation. * \param[in] key_buffer The buffer containing the ECC key context. * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg Randomized or deterministic ECDSA algorithm. * \param[in] hash The hash or message to sign. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_ECC_KEY_PAIR, \c key_bits, * \p alg) where \c key_bits is the bit-size of the ECC key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t mbedtls_psa_ecdsa_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Verify an ECDSA hash or short message signature. * * \note The signature of this function is that of a PSA driver * verify_hash entry point. This function behaves as a verify_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the ECC key to use for the * operation. * \param[in] key_buffer The buffer containing the ECC key context. * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg Randomized or deterministic ECDSA algorithm. * \param[in] hash The hash or message whose signature is to be * verified. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_ecdsa_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** Perform a key agreement and return the raw ECDH shared secret. * * \note The signature of this function is that of a PSA driver * key_agreement entry point. This function behaves as a key_agreement * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the private key * context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in * bytes. * \param[in] alg A key agreement algorithm that is * compatible with the type of the key. * \param[in] peer_key The buffer containing the key context * of the peer's public key. * \param[in] peer_key_length Size of the \p peer_key buffer in * bytes. * \param[out] shared_secret The buffer to which the shared secret * is to be written. * \param[in] shared_secret_size Size of the \p shared_secret buffer in * bytes. * \param[out] shared_secret_length On success, the number of bytes that make * up the returned shared secret. * \retval #PSA_SUCCESS * Success. Shared secret successfully calculated. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p alg is not a key agreement algorithm, or * \p private_key is not compatible with \p alg, * or \p peer_key is not valid for \p alg or not compatible with * \p private_key. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p shared_secret_size is too small * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not a supported key agreement algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_key_agreement_ecdh( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length); #endif /* PSA_CRYPTO_ECP_H */ webfakes/src/mbedtls/library/ssl_tls13_invasive.h0000644000176200001440000000114514740737024021643 0ustar liggesusers/* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_TLS13_INVASIVE_H #define MBEDTLS_SSL_TLS13_INVASIVE_H #include "common.h" #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "psa/crypto.h" #if defined(MBEDTLS_TEST_HOOKS) int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); #endif /* MBEDTLS_TEST_HOOKS */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #endif /* MBEDTLS_SSL_TLS13_INVASIVE_H */ webfakes/src/mbedtls/library/ssl_misc.h0000644000176200001440000035245614740737024017742 0ustar liggesusers/** * \file ssl_misc.h * * \brief Internal functions shared by the SSL modules */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_MISC_H #define MBEDTLS_SSL_MISC_H #include "mbedtls/build_info.h" #include "mbedtls/error.h" #include "mbedtls/ssl.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "psa/crypto.h" #include "psa_util_internal.h" #endif #if defined(MBEDTLS_MD_CAN_MD5) #include "mbedtls/md5.h" #endif #if defined(MBEDTLS_MD_CAN_SHA1) #include "mbedtls/sha1.h" #endif #if defined(MBEDTLS_MD_CAN_SHA256) #include "mbedtls/sha256.h" #endif #if defined(MBEDTLS_MD_CAN_SHA512) #include "mbedtls/sha512.h" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ !defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/ecjpake.h" #endif #include "mbedtls/pk.h" #include "ssl_ciphersuites_internal.h" #include "x509_internal.h" #include "pk_internal.h" #include "common.h" /* Shorthand for restartable ECC */ #if defined(MBEDTLS_ECP_RESTARTABLE) && \ defined(MBEDTLS_SSL_CLI_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED #endif #define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 #define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ #define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ #define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ /* Faked handshake message identity for HelloRetryRequest. */ #define MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST (-MBEDTLS_SSL_HS_SERVER_HELLO) /* * Internal identity of handshake extensions */ #define MBEDTLS_SSL_EXT_ID_UNRECOGNIZED 0 #define MBEDTLS_SSL_EXT_ID_SERVERNAME 1 #define MBEDTLS_SSL_EXT_ID_SERVERNAME_HOSTNAME 1 #define MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH 2 #define MBEDTLS_SSL_EXT_ID_STATUS_REQUEST 3 #define MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS 4 #define MBEDTLS_SSL_EXT_ID_SUPPORTED_ELLIPTIC_CURVES 4 #define MBEDTLS_SSL_EXT_ID_SIG_ALG 5 #define MBEDTLS_SSL_EXT_ID_USE_SRTP 6 #define MBEDTLS_SSL_EXT_ID_HEARTBEAT 7 #define MBEDTLS_SSL_EXT_ID_ALPN 8 #define MBEDTLS_SSL_EXT_ID_SCT 9 #define MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE 10 #define MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE 11 #define MBEDTLS_SSL_EXT_ID_PADDING 12 #define MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY 13 #define MBEDTLS_SSL_EXT_ID_EARLY_DATA 14 #define MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS 15 #define MBEDTLS_SSL_EXT_ID_COOKIE 16 #define MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES 17 #define MBEDTLS_SSL_EXT_ID_CERT_AUTH 18 #define MBEDTLS_SSL_EXT_ID_OID_FILTERS 19 #define MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH 20 #define MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT 21 #define MBEDTLS_SSL_EXT_ID_KEY_SHARE 22 #define MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC 23 #define MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS 24 #define MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC 25 #define MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET 26 #define MBEDTLS_SSL_EXT_ID_SESSION_TICKET 27 #define MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT 28 /* Utility for translating IANA extension type. */ uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type); uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type); /* Macros used to define mask constants */ #define MBEDTLS_SSL_EXT_MASK(id) (1ULL << (MBEDTLS_SSL_EXT_ID_##id)) /* Reset value of extension mask */ #define MBEDTLS_SSL_EXT_MASK_NONE 0 /* In messages containing extension requests, we should ignore unrecognized * extensions. In messages containing extension responses, unrecognized * extensions should result in handshake abortion. Messages containing * extension requests include ClientHello, CertificateRequest and * NewSessionTicket. Messages containing extension responses include * ServerHello, HelloRetryRequest, EncryptedExtensions and Certificate. * * RFC 8446 section 4.1.3 * * The ServerHello MUST only include extensions which are required to establish * the cryptographic context and negotiate the protocol version. * * RFC 8446 section 4.2 * * If an implementation receives an extension which it recognizes and which is * not specified for the message in which it appears, it MUST abort the handshake * with an "illegal_parameter" alert. */ /* Extensions that are not recognized by TLS 1.3 */ #define MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED \ (MBEDTLS_SSL_EXT_MASK(SUPPORTED_POINT_FORMATS) | \ MBEDTLS_SSL_EXT_MASK(ENCRYPT_THEN_MAC) | \ MBEDTLS_SSL_EXT_MASK(EXTENDED_MASTER_SECRET) | \ MBEDTLS_SSL_EXT_MASK(SESSION_TICKET) | \ MBEDTLS_SSL_EXT_MASK(TRUNCATED_HMAC) | \ MBEDTLS_SSL_EXT_MASK(UNRECOGNIZED)) /* RFC 8446 section 4.2. Allowed extensions for ClientHello */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH \ (MBEDTLS_SSL_EXT_MASK(SERVERNAME) | \ MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH) | \ MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | \ MBEDTLS_SSL_EXT_MASK(SIG_ALG) | \ MBEDTLS_SSL_EXT_MASK(USE_SRTP) | \ MBEDTLS_SSL_EXT_MASK(HEARTBEAT) | \ MBEDTLS_SSL_EXT_MASK(ALPN) | \ MBEDTLS_SSL_EXT_MASK(SCT) | \ MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE) | \ MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE) | \ MBEDTLS_SSL_EXT_MASK(PADDING) | \ MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | \ MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES) | \ MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ MBEDTLS_SSL_EXT_MASK(COOKIE) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS) | \ MBEDTLS_SSL_EXT_MASK(CERT_AUTH) | \ MBEDTLS_SSL_EXT_MASK(POST_HANDSHAKE_AUTH) | \ MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT) | \ MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT) | \ MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) /* RFC 8446 section 4.2. Allowed extensions for EncryptedExtensions */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE \ (MBEDTLS_SSL_EXT_MASK(SERVERNAME) | \ MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | \ MBEDTLS_SSL_EXT_MASK(USE_SRTP) | \ MBEDTLS_SSL_EXT_MASK(HEARTBEAT) | \ MBEDTLS_SSL_EXT_MASK(ALPN) | \ MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE) | \ MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE) | \ MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) /* RFC 8446 section 4.2. Allowed extensions for CertificateRequest */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR \ (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ MBEDTLS_SSL_EXT_MASK(SIG_ALG) | \ MBEDTLS_SSL_EXT_MASK(SCT) | \ MBEDTLS_SSL_EXT_MASK(CERT_AUTH) | \ MBEDTLS_SSL_EXT_MASK(OID_FILTERS) | \ MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT) | \ MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) /* RFC 8446 section 4.2. Allowed extensions for Certificate */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT \ (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ MBEDTLS_SSL_EXT_MASK(SCT)) /* RFC 8446 section 4.2. Allowed extensions for ServerHello */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH \ (MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)) /* RFC 8446 section 4.2. Allowed extensions for HelloRetryRequest */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR \ (MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ MBEDTLS_SSL_EXT_MASK(COOKIE) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)) /* RFC 8446 section 4.2. Allowed extensions for NewSessionTicket */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST \ (MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) /* * Helper macros for function call with return check. */ /* * Exit when return non-zero value */ #define MBEDTLS_SSL_PROC_CHK(f) \ do { \ ret = (f); \ if (ret != 0) \ { \ goto cleanup; \ } \ } while (0) /* * Exit when return negative value */ #define MBEDTLS_SSL_PROC_CHK_NEG(f) \ do { \ ret = (f); \ if (ret < 0) \ { \ goto cleanup; \ } \ } while (0) /* * DTLS retransmission states, see RFC 6347 4.2.4 * * The SENDING state is merged in PREPARING for initial sends, * but is distinct for resends. * * Note: initial state is wrong for server, but is not used anyway. */ #define MBEDTLS_SSL_RETRANS_PREPARING 0 #define MBEDTLS_SSL_RETRANS_SENDING 1 #define MBEDTLS_SSL_RETRANS_WAITING 2 #define MBEDTLS_SSL_RETRANS_FINISHED 3 /* * Allow extra bytes for record, authentication and encryption overhead: * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256). */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* This macro determines whether CBC is supported. */ #if defined(MBEDTLS_SSL_HAVE_CBC) && \ (defined(MBEDTLS_SSL_HAVE_AES) || \ defined(MBEDTLS_SSL_HAVE_CAMELLIA) || \ defined(MBEDTLS_SSL_HAVE_ARIA)) #define MBEDTLS_SSL_SOME_SUITES_USE_CBC #endif /* This macro determines whether a ciphersuite using a * stream cipher can be used. */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #define MBEDTLS_SSL_SOME_SUITES_USE_STREAM #endif /* This macro determines whether the CBC construct used in TLS 1.2 is supported. */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) #define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC #endif #if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) || \ defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) #define MBEDTLS_SSL_SOME_SUITES_USE_MAC #endif /* This macro determines whether a ciphersuite uses Encrypt-then-MAC with CBC */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) #define MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) /* Ciphersuites using HMAC */ #if defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ #elif defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ #else #define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ #endif #else /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ /* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ #define MBEDTLS_SSL_MAC_ADD 16 #endif #if defined(MBEDTLS_SSL_HAVE_CBC) #define MBEDTLS_SSL_PADDING_ADD 256 #else #define MBEDTLS_SSL_PADDING_ADD 0 #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_MAX_CID_EXPANSION MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY #else #define MBEDTLS_SSL_MAX_CID_EXPANSION 0 #endif #define MBEDTLS_SSL_PAYLOAD_OVERHEAD (MBEDTLS_MAX_IV_LENGTH + \ MBEDTLS_SSL_MAC_ADD + \ MBEDTLS_SSL_PADDING_ADD + \ MBEDTLS_SSL_MAX_CID_EXPANSION \ ) #define MBEDTLS_SSL_IN_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ (MBEDTLS_SSL_IN_CONTENT_LEN)) #define MBEDTLS_SSL_OUT_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ (MBEDTLS_SSL_OUT_CONTENT_LEN)) /* The maximum number of buffered handshake messages. */ #define MBEDTLS_SSL_MAX_BUFFERED_HS 4 /* Maximum length we can advertise as our max content length for RFC 6066 max_fragment_length extension negotiation purposes (the lesser of both sizes, if they are unequal.) */ #define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ ? (MBEDTLS_SSL_OUT_CONTENT_LEN) \ : (MBEDTLS_SSL_IN_CONTENT_LEN) \ ) /* Maximum size in bytes of list in signature algorithms ext., RFC 5246/8446 */ #define MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN 65534 /* Minimum size in bytes of list in signature algorithms ext., RFC 5246/8446 */ #define MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN 2 /* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ #define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 #define MBEDTLS_RECEIVED_SIG_ALGS_SIZE 20 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #define MBEDTLS_TLS_SIG_NONE MBEDTLS_TLS1_3_SIG_NONE #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #define MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(sig, hash) ((hash << 8) | sig) #define MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg & 0xFF) #define MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg >> 8) #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ /* * Check that we obey the standard's message size bounds */ #if MBEDTLS_SSL_IN_CONTENT_LEN > 16384 #error "Bad configuration - incoming record content too large." #endif #if MBEDTLS_SSL_OUT_CONTENT_LEN > 16384 #error "Bad configuration - outgoing record content too large." #endif #if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_IN_CONTENT_LEN + 2048 #error "Bad configuration - incoming protected record payload too large." #endif #if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN + 2048 #error "Bad configuration - outgoing protected record payload too large." #endif /* Calculate buffer sizes */ /* Note: Even though the TLS record header is only 5 bytes long, we're internally using 8 bytes to store the implicit sequence number. */ #define MBEDTLS_SSL_HEADER_LEN 13 #if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_IN_BUFFER_LEN \ ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN)) #else #define MBEDTLS_SSL_IN_BUFFER_LEN \ ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN) \ + (MBEDTLS_SSL_CID_IN_LEN_MAX)) #endif #if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_OUT_BUFFER_LEN \ ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN)) #else #define MBEDTLS_SSL_OUT_BUFFER_LEN \ ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN) \ + (MBEDTLS_SSL_CID_OUT_LEN_MAX)) #endif #define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32 #define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** * \brief Return the maximum fragment length (payload, in bytes) for * the output buffer. For the client, this is the configured * value. For the server, it is the minimum of two - the * configured value and the negotiated one. * * \sa mbedtls_ssl_conf_max_frag_len() * \sa mbedtls_ssl_get_max_out_record_payload() * * \param ssl SSL context * * \return Current maximum fragment length for the output buffer. */ size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl); /** * \brief Return the maximum fragment length (payload, in bytes) for * the input buffer. This is the negotiated maximum fragment * length, or, if there is none, MBEDTLS_SSL_IN_CONTENT_LEN. * If it is not defined either, the value is 2^14. This function * works as its predecessor, \c mbedtls_ssl_get_max_frag_len(). * * \sa mbedtls_ssl_conf_max_frag_len() * \sa mbedtls_ssl_get_max_in_record_payload() * * \param ssl SSL context * * \return Current maximum fragment length for the output buffer. */ size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) /** * \brief Get the size limit in bytes for the protected outgoing records * as defined in RFC 8449 * * \param ssl SSL context * * \return The size limit in bytes for the protected outgoing * records as defined in RFC 8449. */ size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) static inline size_t mbedtls_ssl_get_output_buflen(const mbedtls_ssl_context *ctx) { #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) return mbedtls_ssl_get_output_max_frag_len(ctx) + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + MBEDTLS_SSL_CID_OUT_LEN_MAX; #else return mbedtls_ssl_get_output_max_frag_len(ctx) + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; #endif } static inline size_t mbedtls_ssl_get_input_buflen(const mbedtls_ssl_context *ctx) { #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) return mbedtls_ssl_get_input_max_frag_len(ctx) + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + MBEDTLS_SSL_CID_IN_LEN_MAX; #else return mbedtls_ssl_get_input_max_frag_len(ctx) + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; #endif } #endif /* * TLS extension flags (for extensions with outgoing ServerHello content * that need it (e.g. for RENEGOTIATION_INFO the server already knows because * of state of the renegotiation flag, so no indicator is required) */ #define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) #define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) /** * \brief This function checks if the remaining size in a buffer is * greater or equal than a needed space. * * \param cur Pointer to the current position in the buffer. * \param end Pointer to one past the end of the buffer. * \param need Needed space in bytes. * * \return Zero if the needed space is available in the buffer, non-zero * otherwise. */ #if !defined(MBEDTLS_TEST_HOOKS) static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur, const uint8_t *end, size_t need) { return (cur > end) || (need > (size_t) (end - cur)); } #else typedef struct { const uint8_t *cur; const uint8_t *end; size_t need; } mbedtls_ssl_chk_buf_ptr_args; void mbedtls_ssl_set_chk_buf_ptr_fail_args( const uint8_t *cur, const uint8_t *end, size_t need); void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args); static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur, const uint8_t *end, size_t need) { if ((cur > end) || (need > (size_t) (end - cur))) { mbedtls_ssl_set_chk_buf_ptr_fail_args(cur, end, need); return 1; } return 0; } #endif /* MBEDTLS_TEST_HOOKS */ /** * \brief This macro checks if the remaining size in a buffer is * greater or equal than a needed space. If it is not the case, * it returns an SSL_BUFFER_TOO_SMALL error. * * \param cur Pointer to the current position in the buffer. * \param end Pointer to one past the end of the buffer. * \param need Needed space in bytes. * */ #define MBEDTLS_SSL_CHK_BUF_PTR(cur, end, need) \ do { \ if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \ { \ return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; \ } \ } while (0) /** * \brief This macro checks if the remaining length in an input buffer is * greater or equal than a needed length. If it is not the case, it * returns #MBEDTLS_ERR_SSL_DECODE_ERROR error and pends a * #MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR alert message. * * This is a function-like macro. It is guaranteed to evaluate each * argument exactly once. * * \param cur Pointer to the current position in the buffer. * \param end Pointer to one past the end of the buffer. * \param need Needed length in bytes. * */ #define MBEDTLS_SSL_CHK_BUF_READ_PTR(cur, end, need) \ do { \ if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \ { \ MBEDTLS_SSL_DEBUG_MSG(1, \ ("missing input data in %s", __func__)); \ MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, \ MBEDTLS_ERR_SSL_DECODE_ERROR); \ return MBEDTLS_ERR_SSL_DECODE_ERROR; \ } \ } while (0) #ifdef __cplusplus extern "C" { #endif typedef int mbedtls_ssl_tls_prf_cb(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); /* cipher.h exports the maximum IV, key and block length from * all ciphers enabled in the config, regardless of whether those * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled * in the default configuration and uses 64 Byte keys, but it is * not used for record protection in SSL/TLS. * * In order to prevent unnecessary inflation of key structures, * we introduce SSL-specific variants of the max-{key,block,IV} * macros here which are meant to only take those ciphers into * account which can be negotiated in SSL/TLS. * * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH * in cipher.h are rough overapproximations of the real maxima, here * we content ourselves with replicating those overapproximations * for the maximum block and IV length, and excluding XTS from the * computation of the maximum key length. */ #define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16 #define MBEDTLS_SSL_MAX_IV_LENGTH 16 #define MBEDTLS_SSL_MAX_KEY_LENGTH 32 /** * \brief The data structure holding the cryptographic material (key and IV) * used for record protection in TLS 1.3. */ struct mbedtls_ssl_key_set { /*! The key for client->server records. */ unsigned char client_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH]; /*! The key for server->client records. */ unsigned char server_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH]; /*! The IV for client->server records. */ unsigned char client_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH]; /*! The IV for server->client records. */ unsigned char server_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH]; size_t key_len; /*!< The length of client_write_key and * server_write_key, in Bytes. */ size_t iv_len; /*!< The length of client_write_iv and * server_write_iv, in Bytes. */ }; typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set; typedef struct { unsigned char binder_key[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char client_early_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char early_exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; } mbedtls_ssl_tls13_early_secrets; typedef struct { unsigned char client_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char server_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; } mbedtls_ssl_tls13_handshake_secrets; /* * This structure contains the parameters only needed during handshake. */ struct mbedtls_ssl_handshake_params { /* Frequently-used boolean or byte fields (placed early to take * advantage of smaller code size for indirect access on Arm Thumb) */ uint8_t resume; /*!< session resume indicator*/ uint8_t cli_exts; /*!< client extension presence*/ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) uint8_t sni_authmode; /*!< authmode from SNI callback */ #endif #if defined(MBEDTLS_SSL_SRV_C) /* Flag indicating if a CertificateRequest message has been sent * to the client or not. */ uint8_t certificate_request_sent; #if defined(MBEDTLS_SSL_EARLY_DATA) /* Flag indicating if the server has accepted early data or not. */ uint8_t early_data_accepted; #endif #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) uint8_t new_session_ticket; /*!< use NewSessionTicket? */ #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_CLI_C) /** Minimum TLS version to be negotiated. * * It is set up in the ClientHello writing preparation stage and used * throughout the ClientHello writing. Not relevant anymore as soon as * the protocol version has been negotiated thus as soon as the * ServerHello is received. * For a fresh handshake not linked to any previous handshake, it is * equal to the configured minimum minor version to be negotiated. When * renegotiating or resuming a session, it is equal to the previously * negotiated minor version. * * There is no maximum TLS version field in this handshake context. * From the start of the handshake, we need to define a current protocol * version for the record layer which we define as the maximum TLS * version to be negotiated. The `tls_version` field of the SSL context is * used to store this maximum value until it contains the actual * negotiated value. */ mbedtls_ssl_protocol_version min_tls_version; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) uint8_t extended_ms; /*!< use Extended Master Secret? */ #endif #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) uint8_t async_in_progress; /*!< an asynchronous operation is in progress */ #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned char retransmit_state; /*!< Retransmission state */ #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) unsigned char group_list_heap_allocated; unsigned char sig_algs_heap_allocated; #endif #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) uint8_t ecrs_enabled; /*!< Handshake supports EC restart? */ enum { /* this complements ssl->state with info on intra-state operations */ ssl_ecrs_none = 0, /*!< nothing going on (yet) */ ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ } ecrs_state; /*!< current (or last) operation */ mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */ size_t ecrs_n; /*!< place for saving a length */ #endif mbedtls_ssl_ciphersuite_t const *ciphersuite_info; MBEDTLS_CHECK_RETURN_CRITICAL int (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); MBEDTLS_CHECK_RETURN_CRITICAL int (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *); MBEDTLS_CHECK_RETURN_CRITICAL int (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); mbedtls_ssl_tls_prf_cb *tls_prf; /* * Handshake specific crypto variables */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) uint8_t key_exchange_mode; /*!< Selected key exchange mode */ /** * Flag indicating if, in the course of the current handshake, an * HelloRetryRequest message has been sent by the server or received by * the client (<> 0) or not (0). */ uint8_t hello_retry_request_flag; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /** * Flag indicating if, in the course of the current handshake, a dummy * change_cipher_spec (CCS) record has already been sent. Used to send only * one CCS per handshake while not complicating the handshake state * transitions for that purpose. */ uint8_t ccs_sent; #endif #if defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */ #endif /** selected_group of key_share extension in HelloRetryRequest message. */ uint16_t hrr_selected_group; #if defined(MBEDTLS_SSL_SESSION_TICKETS) uint16_t new_session_tickets_count; /*!< number of session tickets */ #endif #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) uint16_t received_sig_algs[MBEDTLS_RECEIVED_SIG_ALGS_SIZE]; #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) const uint16_t *group_list; const uint16_t *sig_algs; #endif #if defined(MBEDTLS_DHM_C) mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ #endif #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED) psa_key_type_t xxdh_psa_type; size_t xxdh_psa_bits; mbedtls_svc_key_id_t xxdh_psa_privkey; uint8_t xxdh_psa_privkey_is_external; unsigned char xxdh_psa_peerkey[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; size_t xxdh_psa_peerkey_len; #endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_pake_operation_t psa_pake_ctx; /*!< EC J-PAKE key exchange */ mbedtls_svc_key_id_t psa_pake_password; uint8_t psa_pake_ctx_is_ok; #else mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ size_t ecjpake_cache_len; /*!< Length of cached data */ #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) uint16_t *curves_tls_id; /*!< List of TLS IDs of supported elliptic curves */ #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t psk_opaque; /*!< Opaque PSK from the callback */ uint8_t psk_opaque_is_internal; #else unsigned char *psk; /*!< PSK from the callback */ size_t psk_len; /*!< Length of PSK from callback */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ uint16_t selected_identity; #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */ #endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ struct { size_t total_bytes_buffered; /*!< Cumulative size of heap allocated * buffers used for message buffering. */ uint8_t seen_ccs; /*!< Indicates if a CCS message has * been seen in the current flight. */ struct mbedtls_ssl_hs_buffer { unsigned is_valid : 1; unsigned is_fragmented : 1; unsigned is_complete : 1; unsigned char *data; size_t data_len; } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; struct { unsigned char *data; size_t len; unsigned epoch; } future_record; } buffering; #if defined(MBEDTLS_SSL_CLI_C) && \ (defined(MBEDTLS_SSL_PROTO_DTLS) || \ defined(MBEDTLS_SSL_PROTO_TLS1_3)) unsigned char *cookie; /*!< HelloVerifyRequest cookie for DTLS * HelloRetryRequest cookie for TLS 1.3 */ #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) /* RFC 6347 page 15 ... opaque cookie<0..2^8-1>; ... */ uint8_t cookie_len; #else /* RFC 8446 page 39 ... opaque cookie<0..2^16-1>; ... If TLS1_3 is enabled, the max length is 2^16 - 1 */ uint16_t cookie_len; /*!< DTLS: HelloVerifyRequest cookie length * TLS1_3: HelloRetryRequest cookie length */ #endif #endif /* MBEDTLS_SSL_CLI_C && ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_DTLS) unsigned char cookie_verify_result; /*!< Srv: flag for sending a cookie */ #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ uint32_t retransmit_timeout; /*!< Current value of timeout */ mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ unsigned char *cur_msg_p; /*!< Position in current message */ unsigned int in_flight_start_seq; /*!< Minimum message sequence in the flight being received */ mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for resending messages */ unsigned char alt_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Alternative record epoch/counter for resending messages */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* The state of CID configuration in this handshake. */ uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension * has been negotiated. Possible values are * #MBEDTLS_SSL_CID_ENABLED and * #MBEDTLS_SSL_CID_DISABLED. */ unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; /*! The peer's CID */ uint8_t peer_cid_len; /*!< The length of * \c peer_cid. */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Checksum contexts */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_operation_t fin_sha256_psa; #else mbedtls_md_context_t fin_sha256; #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_operation_t fin_sha384_psa; #else mbedtls_md_context_t fin_sha384; #endif #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) uint16_t offered_group_id; /* The NamedGroup value for the group * that is being used for ephemeral * key exchange. * * On the client: Defaults to the first * entry in the client's group list, * but can be overwritten by the HRR. */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_CLI_C) uint8_t client_auth; /*!< used to check if CertificateRequest has been received from server side. If CertificateRequest has been received, Certificate and CertificateVerify should be sent to server */ #endif /* MBEDTLS_SSL_CLI_C */ /* * State-local variables used during the processing * of a specific handshake state. */ union { /* Outgoing Finished message */ struct { uint8_t preparation_done; /* Buffer holding digest of the handshake up to * but excluding the outgoing finished message. */ unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t digest_len; } finished_out; /* Incoming Finished message */ struct { uint8_t preparation_done; /* Buffer holding digest of the handshake up to but * excluding the peer's incoming finished message. */ unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t digest_len; } finished_in; } state_local; /* End of state-local variables. */ unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN + MBEDTLS_SERVER_HELLO_RANDOM_LEN]; /*!< random bytes */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; /*!< premaster secret */ size_t pmslen; /*!< premaster length */ #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) uint32_t sent_extensions; /*!< extensions sent by endpoint */ uint32_t received_extensions; /*!< extensions received by endpoint */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) unsigned char certificate_request_context_len; unsigned char *certificate_request_context; #endif /** TLS 1.3 transform for encrypted handshake messages. */ mbedtls_ssl_transform *transform_handshake; union { unsigned char early[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char app[MBEDTLS_TLS1_3_MD_MAX_SIZE]; } tls13_master_secrets; mbedtls_ssl_tls13_handshake_secrets tls13_hs_secrets; #if defined(MBEDTLS_SSL_EARLY_DATA) /** TLS 1.3 transform for early data and handshake messages. */ mbedtls_ssl_transform *transform_earlydata; #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) /** Asynchronous operation context. This field is meant for use by the * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, * mbedtls_ssl_config::f_async_decrypt_start, * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). * The library does not use it internally. */ void *user_async_ctx; #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) const unsigned char *sni_name; /*!< raw SNI */ size_t sni_name_len; /*!< raw SNI len */ #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) const mbedtls_x509_crt *dn_hints; /*!< acceptable client cert issuers */ #endif #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ }; typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; /* * Representation of decryption/encryption transformations on records * * There are the following general types of record transformations: * - Stream transformations (TLS versions == 1.2 only) * Transformation adding a MAC and applying a stream-cipher * to the authenticated message. * - CBC block cipher transformations ([D]TLS versions == 1.2 only) * For TLS 1.2, no IV is generated at key extraction time, but every * encrypted record is explicitly prefixed by the IV with which it was * encrypted. * - AEAD transformations ([D]TLS versions == 1.2 only) * These come in two fundamentally different versions, the first one * used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second * one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3. * In the first transformation, the IV to be used for a record is obtained * as the concatenation of an explicit, static 4-byte IV and the 8-byte * record sequence number, and explicitly prepending this sequence number * to the encrypted record. In contrast, in the second transformation * the IV is obtained by XOR'ing a static IV obtained at key extraction * time with the 8-byte record sequence number, without prepending the * latter to the encrypted record. * * Additionally, DTLS 1.2 + CID as well as TLS 1.3 use an inner plaintext * which allows to add flexible length padding and to hide a record's true * content type. * * In addition to type and version, the following parameters are relevant: * - The symmetric cipher algorithm to be used. * - The (static) encryption/decryption keys for the cipher. * - For stream/CBC, the type of message digest to be used. * - For stream/CBC, (static) encryption/decryption keys for the digest. * - For AEAD transformations, the size (potentially 0) of an explicit, * random initialization vector placed in encrypted records. * - For some transformations (currently AEAD) an implicit IV. It is static * and (if present) is combined with the explicit IV in a transformation- * -dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3). * - For stream/CBC, a flag determining the order of encryption and MAC. * - The details of the transformation depend on the SSL/TLS version. * - The length of the authentication tag. * * The struct below refines this abstract view as follows: * - The cipher underlying the transformation is managed in * cipher contexts cipher_ctx_{enc/dec}, which must have the * same cipher type. The mode of these cipher contexts determines * the type of the transformation in the sense above: e.g., if * the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM * then the transformation has type CBC resp. AEAD. * - The cipher keys are never stored explicitly but * are maintained within cipher_ctx_{enc/dec}. * - For stream/CBC transformations, the message digest contexts * used for the MAC's are stored in md_ctx_{enc/dec}. These contexts * are unused for AEAD transformations. * - For stream/CBC transformations, the MAC keys are not stored explicitly * but maintained within md_ctx_{enc/dec}. * - The mac_enc and mac_dec fields are unused for EAD transformations. * - For transformations using an implicit IV maintained within * the transformation context, its contents are stored within * iv_{enc/dec}. * - The value of ivlen indicates the length of the IV. * This is redundant in case of stream/CBC transformations * which always use 0 resp. the cipher's block length as the * IV length, but is needed for AEAD ciphers and may be * different from the underlying cipher's block length * in this case. * - The field fixed_ivlen is nonzero for AEAD transformations only * and indicates the length of the static part of the IV which is * constant throughout the communication, and which is stored in * the first fixed_ivlen bytes of the iv_{enc/dec} arrays. * - tls_version denotes the 2-byte TLS version * - For stream/CBC transformations, maclen denotes the length of the * authentication tag, while taglen is unused and 0. * - For AEAD transformations, taglen denotes the length of the * authentication tag, while maclen is unused and 0. * - For CBC transformations, encrypt_then_mac determines the * order of encryption and authentication. This field is unused * in other transformations. * */ struct mbedtls_ssl_transform { /* * Session specific crypto layer */ size_t minlen; /*!< min. ciphertext length */ size_t ivlen; /*!< IV length */ size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ size_t maclen; /*!< MAC(CBC) len */ size_t taglen; /*!< TAG(AEAD) len */ unsigned char iv_enc[16]; /*!< IV (encryption) */ unsigned char iv_dec[16]; /*!< IV (decryption) */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t psa_mac_enc; /*!< MAC (encryption) */ mbedtls_svc_key_id_t psa_mac_dec; /*!< MAC (decryption) */ psa_algorithm_t psa_mac_alg; /*!< psa MAC algorithm */ #else mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) int encrypt_then_mac; /*!< flag for EtM activation */ #endif #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ mbedtls_ssl_protocol_version tls_version; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t psa_key_enc; /*!< psa encryption key */ mbedtls_svc_key_id_t psa_key_dec; /*!< psa decryption key */ psa_algorithm_t psa_alg; /*!< psa algorithm */ #else mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) uint8_t in_cid_len; uint8_t out_cid_len; unsigned char in_cid[MBEDTLS_SSL_CID_IN_LEN_MAX]; unsigned char out_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) /* We need the Hello random bytes in order to re-derive keys from the * Master Secret and other session info, * see ssl_tls12_populate_transform() */ unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN + MBEDTLS_CLIENT_HELLO_RANDOM_LEN]; /*!< ServerHello.random+ClientHello.random */ #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ }; /* * Return 1 if the transform uses an AEAD cipher, 0 otherwise. * Equivalently, return 0 if a separate MAC is used, 1 otherwise. */ static inline int mbedtls_ssl_transform_uses_aead( const mbedtls_ssl_transform *transform) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) return transform->maclen == 0 && transform->taglen != 0; #else (void) transform; return 1; #endif } /* * Internal representation of record frames * * Instances come in two flavors: * (1) Encrypted * These always have data_offset = 0 * (2) Unencrypted * These have data_offset set to the amount of * pre-expansion during record protection. Concretely, * this is the length of the fixed part of the explicit IV * used for encryption, or 0 if no explicit IV is used * (e.g. for stream ciphers). * * The reason for the data_offset in the unencrypted case * is to allow for in-place conversion of an unencrypted to * an encrypted record. If the offset wasn't included, the * encrypted content would need to be shifted afterwards to * make space for the fixed IV. * */ #if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX #define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX #else #define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX #endif typedef struct { uint8_t ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /* In TLS: The implicit record sequence number. * In DTLS: The 2-byte epoch followed by * the 6-byte sequence number. * This is stored as a raw big endian byte array * as opposed to a uint64_t because we rarely * need to perform arithmetic on this, but do * need it as a Byte array for the purpose of * MAC computations. */ uint8_t type; /* The record content type. */ uint8_t ver[2]; /* SSL/TLS version as present on the wire. * Convert to internal presentation of versions * using mbedtls_ssl_read_version() and * mbedtls_ssl_write_version(). * Keep wire-format for MAC computations. */ unsigned char *buf; /* Memory buffer enclosing the record content */ size_t buf_len; /* Buffer length */ size_t data_offset; /* Offset of record content */ size_t data_len; /* Length of record content */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) uint8_t cid_len; /* Length of the CID (0 if not present) */ unsigned char cid[MBEDTLS_SSL_CID_LEN_MAX]; /* The CID */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ } mbedtls_record; #if defined(MBEDTLS_X509_CRT_PARSE_C) /* * List of certificate + private key pairs */ struct mbedtls_ssl_key_cert { mbedtls_x509_crt *cert; /*!< cert */ mbedtls_pk_context *key; /*!< private key */ mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ }; #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_PROTO_DTLS) /* * List of handshake messages kept around for resending */ struct mbedtls_ssl_flight_item { unsigned char *p; /*!< message, including handshake headers */ size_t len; /*!< length of p */ unsigned char type; /*!< type of the message: handshake or CCS */ mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ }; #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /** * \brief Given an SSL context and its associated configuration, write the TLS * 1.2 specific extensions of the ClientHello message. * * \param[in] ssl SSL context * \param[in] buf Base address of the buffer where to write the extensions * \param[in] end End address of the buffer where to write the extensions * \param uses_ec Whether one proposed ciphersuite uses an elliptic curve * (<> 0) or not ( 0 ). * \param[out] out_len Length of the data written into the buffer \p buf */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, int uses_ec, size_t *out_len); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /** * \brief Find the preferred hash for a given signature algorithm. * * \param[in] ssl SSL context * \param[in] sig_alg A signature algorithm identifier as defined in the * TLS 1.2 SignatureAlgorithm enumeration. * * \return The preferred hash algorithm for \p sig_alg. It is a hash algorithm * identifier as defined in the TLS 1.2 HashAlgorithm enumeration. */ unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( mbedtls_ssl_context *ssl, unsigned int sig_alg); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /** * \brief Free referenced items in an SSL transform context and clear * memory * * \param transform SSL transform context */ void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform); /** * \brief Free referenced items in an SSL handshake context and clear * memory * * \param ssl SSL context */ void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl); /* set inbound transform of ssl context */ void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform); /* set outbound transform of ssl context */ void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl); void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl); static inline void mbedtls_ssl_handshake_set_state(mbedtls_ssl_context *ssl, mbedtls_ssl_states state) { ssl->state = (int) state; } MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl); /** * \brief Update record layer * * This function roughly separates the implementation * of the logic of (D)TLS from the implementation * of the secure transport. * * \param ssl The SSL context to use. * \param update_hs_digest This indicates if the handshake digest * should be automatically updated in case * a handshake message is found. * * \return 0 or non-zero error code. * * \note A clarification on what is called 'record layer' here * is in order, as many sensible definitions are possible: * * The record layer takes as input an untrusted underlying * transport (stream or datagram) and transforms it into * a serially multiplexed, secure transport, which * conceptually provides the following: * * (1) Three datagram based, content-agnostic transports * for handshake, alert and CCS messages. * (2) One stream- or datagram-based transport * for application data. * (3) Functionality for changing the underlying transform * securing the contents. * * The interface to this functionality is given as follows: * * a Updating * [Currently implemented by mbedtls_ssl_read_record] * * Check if and on which of the four 'ports' data is pending: * Nothing, a controlling datagram of type (1), or application * data (2). In any case data is present, internal buffers * provide access to the data for the user to process it. * Consumption of type (1) datagrams is done automatically * on the next update, invalidating that the internal buffers * for previous datagrams, while consumption of application * data (2) is user-controlled. * * b Reading of application data * [Currently manual adaption of ssl->in_offt pointer] * * As mentioned in the last paragraph, consumption of data * is different from the automatic consumption of control * datagrams (1) because application data is treated as a stream. * * c Tracking availability of application data * [Currently manually through decreasing ssl->in_msglen] * * For efficiency and to retain datagram semantics for * application data in case of DTLS, the record layer * provides functionality for checking how much application * data is still available in the internal buffer. * * d Changing the transformation securing the communication. * * Given an opaque implementation of the record layer in the * above sense, it should be possible to implement the logic * of (D)TLS on top of it without the need to know anything * about the record layer's internals. This is done e.g. * in all the handshake handling functions, and in the * application data reading function mbedtls_ssl_read. * * \note The above tries to give a conceptual picture of the * record layer, but the current implementation deviates * from it in some places. For example, our implementation of * the update functionality through mbedtls_ssl_read_record * discards datagrams depending on the current state, which * wouldn't fall under the record layer's responsibility * following the above definition. * */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl, unsigned update_hs_digest); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want); /* * Write handshake message header */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type, unsigned char **buf, size_t *buf_len); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl, int update_checksum, int force_flush); static inline int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) { return mbedtls_ssl_write_handshake_msg_ext(ssl, 1 /* update checksum */, 1 /* force flush */); } /* * Write handshake message tail */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl, size_t buf_len, size_t msg_len); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl); void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info); /* * Update checksum of handshake messages. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl, unsigned hs_type, unsigned char const *msg, size_t msg_len); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl, unsigned hs_type, size_t total_hs_len); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) #if !defined(MBEDTLS_USE_PSA_CRYPTO) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex); #endif /* !MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_SSL_CLI_C) || defined(MBEDTLS_SSL_SRV_C) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf); #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * Get the first defined opaque PSK by order of precedence: * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in the PSK * callback * 2. static PSK configured by \c mbedtls_ssl_conf_psk_opaque() * Return an opaque PSK */ static inline mbedtls_svc_key_id_t mbedtls_ssl_get_opaque_psk( const mbedtls_ssl_context *ssl) { if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { return ssl->handshake->psk_opaque; } if (!mbedtls_svc_key_id_is_null(ssl->conf->psk_opaque)) { return ssl->conf->psk_opaque; } return MBEDTLS_SVC_KEY_ID_INIT; } #else /** * Get the first defined PSK by order of precedence: * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback * 2. static PSK configured by \c mbedtls_ssl_conf_psk() * Return a code and update the pair (PSK, PSK length) passed to this function */ static inline int mbedtls_ssl_get_psk(const mbedtls_ssl_context *ssl, const unsigned char **psk, size_t *psk_len) { if (ssl->handshake->psk != NULL && ssl->handshake->psk_len > 0) { *psk = ssl->handshake->psk; *psk_len = ssl->handshake->psk_len; } else if (ssl->conf->psk != NULL && ssl->conf->psk_len > 0) { *psk = ssl->conf->psk; *psk_len = ssl->conf->psk_len; } else { *psk = NULL; *psk_len = 0; return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_PK_C) unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk); unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type); mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig); #endif mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash); unsigned char mbedtls_ssl_hash_from_md_alg(int md); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md); #endif MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id); #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /** * \brief Return PSA EC info for the specified TLS ID. * * \param tls_id The TLS ID to look for * \param type If the TLD ID is supported, then proper \c psa_key_type_t * value is returned here. Can be NULL. * \param bits If the TLD ID is supported, then proper bit size is returned * here. Can be NULL. * \return PSA_SUCCESS if the TLS ID is supported, * PSA_ERROR_NOT_SUPPORTED otherwise * * \note If either \c family or \c bits parameters are NULL, then * the corresponding value is not returned. * The function can be called with both parameters as NULL * simply to check if a specific TLS ID is supported. */ int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id, psa_key_type_t *type, size_t *bits); /** * \brief Return \c mbedtls_ecp_group_id for the specified TLS ID. * * \param tls_id The TLS ID to look for * \return Proper \c mbedtls_ecp_group_id if the TLS ID is supported, * or MBEDTLS_ECP_DP_NONE otherwise */ mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id); /** * \brief Return TLS ID for the specified \c mbedtls_ecp_group_id. * * \param grp_id The \c mbedtls_ecp_group_id ID to look for * \return Proper TLS ID if the \c mbedtls_ecp_group_id is supported, * or 0 otherwise */ uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id); #if defined(MBEDTLS_DEBUG_C) /** * \brief Return EC's name for the specified TLS ID. * * \param tls_id The TLS ID to look for * \return A pointer to a const string with the proper name. If TLS * ID is not supported, a NULL pointer is returned instead. */ const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id); #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value (const uint16_t srtp_profile_value) { switch (srtp_profile_value) { case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: return srtp_profile_value; default: break; } return MBEDTLS_TLS_SRTP_UNSET; } #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) static inline mbedtls_pk_context *mbedtls_ssl_own_key(mbedtls_ssl_context *ssl) { mbedtls_ssl_key_cert *key_cert; if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { key_cert = ssl->handshake->key_cert; } else { key_cert = ssl->conf->key_cert; } return key_cert == NULL ? NULL : key_cert->key; } static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl) { mbedtls_ssl_key_cert *key_cert; if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { key_cert = ssl->handshake->key_cert; } else { key_cert = ssl->conf->key_cert; } return key_cert == NULL ? NULL : key_cert->cert; } /* * Verify a certificate. * * [in/out] ssl: misc. things read * ssl->session_negotiate->verify_result updated * [in] authmode: one of MBEDTLS_SSL_VERIFY_{NONE,OPTIONAL,REQUIRED} * [in] chain: the certificate chain to verify (ie the peer's chain) * [in] ciphersuite_info: For TLS 1.2, this session's ciphersuite; * for TLS 1.3, may be left NULL. * [in] rs_ctx: restart context if restartable ECC is in use; * leave NULL for no restartable behaviour. * * Return: * - 0 if the handshake should continue. Depending on the * authmode it means: * - REQUIRED: the certificate was found to be valid, trusted & acceptable. * ssl->session_negotiate->verify_result is 0. * - OPTIONAL: the certificate may or may not be acceptable, but * ssl->session_negotiate->verify_result was updated with the result. * - NONE: the certificate wasn't even checked. * - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED or MBEDTLS_ERR_SSL_BAD_CERTIFICATE if * the certificate was found to be invalid/untrusted/unacceptable and the * handshake should be aborted (can only happen with REQUIRED). * - another error code if another error happened (out-of-memory, etc.) */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl, int authmode, mbedtls_x509_crt *chain, const mbedtls_ssl_ciphersuite_t *ciphersuite_info, void *rs_ctx); /* * Check usage of a certificate wrt usage extensions: * keyUsage and extendedKeyUsage. * (Note: nSCertType is deprecated and not standard, we don't check it.) * * Note: if tls_version is 1.3, ciphersuite is ignored and can be NULL. * * Note: recv_endpoint is the receiver's endpoint. * * Return 0 if everything is OK, -1 if not. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, const mbedtls_ssl_ciphersuite_t *ciphersuite, int recv_endpoint, mbedtls_ssl_protocol_version tls_version, uint32_t *flags); #endif /* MBEDTLS_X509_CRT_PARSE_C */ void mbedtls_ssl_write_version(unsigned char version[2], int transport, mbedtls_ssl_protocol_version tls_version); uint16_t mbedtls_ssl_read_version(const unsigned char version[2], int transport); static inline size_t mbedtls_ssl_in_hdr_len(const mbedtls_ssl_context *ssl) { #if !defined(MBEDTLS_SSL_PROTO_DTLS) ((void) ssl); #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 13; } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { return 5; } } static inline size_t mbedtls_ssl_out_hdr_len(const mbedtls_ssl_context *ssl) { return (size_t) (ssl->out_iv - ssl->out_hdr); } static inline size_t mbedtls_ssl_hs_hdr_len(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 12; } #else ((void) ssl); #endif return 4; } #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl); void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_resend(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl); #endif /* Visible for testing purposes only */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl); void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl); #endif MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, const mbedtls_ssl_session *src); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hashlen, unsigned char *data, size_t data_len, mbedtls_md_type_t md_alg); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #ifdef __cplusplus } #endif void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec); /* Length of the "epoch" field in the record header */ static inline size_t mbedtls_ssl_ep_len(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 2; } #else ((void) ssl); #endif return 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_PROTO_DTLS */ void mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl); void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl); void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform); void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial); void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, int partial); /* * Send pending alert */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl); /* * Set pending fatal alert flag. */ void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl, unsigned char alert_type, int alert_reason); /* Alias of mbedtls_ssl_pend_fatal_alert */ #define MBEDTLS_SSL_PEND_FATAL_ALERT(type, user_return_value) \ mbedtls_ssl_pend_fatal_alert(ssl, type, user_return_value) #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) void mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl); #endif void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_RENEGOTIATION) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_PROTO_DTLS) size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl); void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl); void mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight); #endif /* MBEDTLS_SSL_PROTO_DTLS */ /** * ssl utils functions for checking configuration. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) static inline int mbedtls_ssl_conf_is_tls13_only(const mbedtls_ssl_config *conf) { return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) static inline int mbedtls_ssl_conf_is_tls12_only(const mbedtls_ssl_config *conf) { return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_2; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ static inline int mbedtls_ssl_conf_is_tls13_enabled(const mbedtls_ssl_config *conf) { #if defined(MBEDTLS_SSL_PROTO_TLS1_3) return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 && conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_3; #else ((void) conf); return 0; #endif } static inline int mbedtls_ssl_conf_is_tls12_enabled(const mbedtls_ssl_config *conf) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2 && conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_2; #else ((void) conf); return 0; #endif } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) static inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13(const mbedtls_ssl_config *conf) { return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /** \brief Initialize the PSA crypto subsystem if necessary. * * Call this function before doing any cryptography in a TLS 1.3 handshake. * * This is necessary in Mbed TLS 3.x for backward compatibility. * Up to Mbed TLS 3.5, in the default configuration, you could perform * a TLS connection with default parameters without having called * psa_crypto_init(), since the TLS layer only supported TLS 1.2 and * did not use PSA crypto. (TLS 1.2 only uses PSA crypto if * MBEDTLS_USE_PSA_CRYPTO is enabled, which is not the case in the default * configuration.) Starting with Mbed TLS 3.6.0, TLS 1.3 is enabled * by default, and the TLS 1.3 layer uses PSA crypto. This means that * applications that are not otherwise using PSA crypto and that worked * with Mbed TLS 3.5 started failing in TLS 3.6.0 if they connected to * a peer that supports TLS 1.3. See * https://github.com/Mbed-TLS/mbedtls/issues/9072 */ int mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl); extern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ MBEDTLS_SERVER_HELLO_RANDOM_LEN]; MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl); void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl); /** * \brief Given an SSL context and its associated configuration, write the TLS * 1.3 specific extensions of the ClientHello message. * * \param[in] ssl SSL context * \param[in] buf Base address of the buffer where to write the extensions * \param[in] end End address of the buffer where to write the extensions * \param[out] out_len Length of the data written into the buffer \p buf */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len); /** * \brief TLS 1.3 client side state machine entry * * \param ssl SSL context */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl); /** * \brief TLS 1.3 server side state machine entry * * \param ssl SSL context */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl); /* * Helper functions around key exchange modes. */ static inline int mbedtls_ssl_conf_tls13_is_kex_mode_enabled(mbedtls_ssl_context *ssl, int kex_mode_mask) { return (ssl->conf->tls13_kex_modes & kex_mode_mask) != 0; } static inline int mbedtls_ssl_conf_tls13_is_psk_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); } static inline int mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL); } static inline int mbedtls_ssl_conf_tls13_is_ephemeral_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL); } static inline int mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); } static inline int mbedtls_ssl_conf_tls13_is_some_psk_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); } #if defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /** * Given a list of key exchange modes, check if at least one of them is * supported by peer. * * \param[in] ssl SSL context * \param kex_modes_mask Mask of the key exchange modes to check * * \return Non-zero if at least one of the key exchange modes is supported by * the peer, otherwise \c 0. */ static inline int mbedtls_ssl_tls13_is_kex_mode_supported(mbedtls_ssl_context *ssl, int kex_modes_mask) { return (ssl->handshake->tls13_kex_modes & kex_modes_mask) != 0; } static inline int mbedtls_ssl_tls13_is_psk_supported(mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); } static inline int mbedtls_ssl_tls13_is_psk_ephemeral_supported( mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL); } static inline int mbedtls_ssl_tls13_is_ephemeral_supported(mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL); } static inline int mbedtls_ssl_tls13_is_some_ephemeral_supported(mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); } static inline int mbedtls_ssl_tls13_is_some_psk_supported(mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ /* * Helper functions for extensions checking. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_check_received_extension( mbedtls_ssl_context *ssl, int hs_msg_type, unsigned int received_extension_type, uint32_t hs_msg_allowed_extensions_mask); static inline void mbedtls_ssl_tls13_set_hs_sent_ext_mask( mbedtls_ssl_context *ssl, unsigned int extension_type) { ssl->handshake->sent_extensions |= mbedtls_ssl_get_extension_mask(extension_type); } /* * Helper functions to check the selected key exchange mode. */ static inline int mbedtls_ssl_tls13_key_exchange_mode_check( mbedtls_ssl_context *ssl, int kex_mask) { return (ssl->handshake->key_exchange_mode & kex_mask) != 0; } static inline int mbedtls_ssl_tls13_key_exchange_mode_with_psk( mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_key_exchange_mode_check(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); } static inline int mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral( mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_key_exchange_mode_check(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); } /* * Fetch TLS 1.3 handshake message header */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, unsigned char **buf, size_t *buf_len); /** * \brief Detect if a list of extensions contains a supported_versions * extension or not. * * \param[in] ssl SSL context * \param[in] buf Address of the first byte of the extensions vector. * \param[in] end End of the buffer containing the list of extensions. * \param[out] supported_versions_data If the extension is present, address of * its first byte of data, NULL otherwise. * \param[out] supported_versions_data_end If the extension is present, address * of the first byte immediately * following the extension data, NULL * otherwise. * \return 0 if the list of extensions does not contain a supported_versions * extension. * \return 1 if the list of extensions contains a supported_versions * extension. * \return A negative value if an error occurred while parsing the * extensions. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end, const unsigned char **supported_versions_data, const unsigned char **supported_versions_data_end); /* * Handler of TLS 1.3 server certificate message */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * Handler of TLS 1.3 write Certificate message */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl); /* * Handler of TLS 1.3 write Certificate Verify message */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * Generic handler of Certificate Verify */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl); /* * Write of dummy-CCS's for middlebox compatibility */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl); #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( mbedtls_ssl_context *ssl, uint16_t named_group, unsigned char *buf, unsigned char *end, size_t *out_len); #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ #if defined(MBEDTLS_SSL_EARLY_DATA) int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, int in_new_session_ticket, unsigned char *buf, const unsigned char *end, size_t *out_len); int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl, size_t early_data_len); typedef enum { /* * The client has not sent the first ClientHello yet, the negotiation of early * data has not started yet. */ MBEDTLS_SSL_EARLY_DATA_STATE_IDLE, /* * In its ClientHello, the client has not included an early data indication * extension. */ MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT, /* * The client has sent an early data indication extension in its first * ClientHello, it has not received the response (ServerHello or * HelloRetryRequest) from the server yet. The transform to protect early data * is not set either as for middlebox compatibility a dummy CCS may have to be * sent in clear. Early data cannot be sent to the server yet. */ MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT, /* * The client has sent an early data indication extension in its first * ClientHello, it has not received the response (ServerHello or * HelloRetryRequest) from the server yet. The transform to protect early data * has been set and early data can be written now. */ MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, /* * The client has indicated the use of early data and the server has accepted * it. */ MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED, /* * The client has indicated the use of early data but the server has rejected * it. */ MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED, /* * The client has sent an early data indication extension in its first * ClientHello, the server has accepted them and the client has received the * server Finished message. It cannot send early data to the server anymore. */ MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED, } mbedtls_ssl_early_data_state; #endif /* MBEDTLS_SSL_EARLY_DATA */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* * Write Signature Algorithm extension */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len); /* * Parse TLS Signature Algorithm extension */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ /* Get handshake transcript */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, const mbedtls_md_type_t md, unsigned char *dst, size_t dst_len, size_t *olen); /* * Return supported groups. * * In future, invocations can be changed to ssl->conf->group_list * when mbedtls_ssl_conf_curves() is deleted. * * ssl->handshake->group_list is either a translation of curve_list to IANA TLS group * identifiers when mbedtls_ssl_conf_curves() has been used, or a pointer to * ssl->conf->group_list when mbedtls_ssl_conf_groups() has been more recently invoked. * */ static inline const void *mbedtls_ssl_get_groups(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_DEPRECATED_REMOVED) || !defined(MBEDTLS_ECP_C) return ssl->conf->group_list; #else if ((ssl->handshake != NULL) && (ssl->handshake->group_list != NULL)) { return ssl->handshake->group_list; } else { return ssl->conf->group_list; } #endif } /* * Helper functions for NamedGroup. */ static inline int mbedtls_ssl_tls12_named_group_is_ecdhe(uint16_t named_group) { /* * RFC 8422 section 5.1.1 */ return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448 || /* Below deprecated curves should be removed with notice to users */ named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1; } static inline int mbedtls_ssl_tls13_named_group_is_ecdhe(uint16_t named_group) { return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448; } static inline int mbedtls_ssl_tls13_named_group_is_ffdh(uint16_t named_group) { return named_group >= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 && named_group <= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192; } static inline int mbedtls_ssl_named_group_is_offered( const mbedtls_ssl_context *ssl, uint16_t named_group) { const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); if (group_list == NULL) { return 0; } for (; *group_list != 0; group_list++) { if (*group_list == named_group) { return 1; } } return 0; } static inline int mbedtls_ssl_named_group_is_supported(uint16_t named_group) { #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) { if (mbedtls_ssl_get_ecp_group_id_from_tls_id(named_group) != MBEDTLS_ECP_DP_NONE) { return 1; } } #endif #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) { return 1; } #endif #if !defined(PSA_WANT_ALG_ECDH) && !defined(PSA_WANT_ALG_FFDH) (void) named_group; #endif return 0; } /* * Return supported signature algorithms. * * In future, invocations can be changed to ssl->conf->sig_algs when * mbedtls_ssl_conf_sig_hashes() is deleted. * * ssl->handshake->sig_algs is either a translation of sig_hashes to IANA TLS * signature algorithm identifiers when mbedtls_ssl_conf_sig_hashes() has been * used, or a pointer to ssl->conf->sig_algs when mbedtls_ssl_conf_sig_algs() has * been more recently invoked. * */ static inline const void *mbedtls_ssl_get_sig_algs( const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) if (ssl->handshake != NULL && ssl->handshake->sig_algs_heap_allocated == 1 && ssl->handshake->sig_algs != NULL) { return ssl->handshake->sig_algs; } #endif return ssl->conf->sig_algs; #else /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ ((void) ssl); return NULL; #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) static inline int mbedtls_ssl_sig_alg_is_received(const mbedtls_ssl_context *ssl, uint16_t own_sig_alg) { const uint16_t *sig_alg = ssl->handshake->received_sig_algs; if (sig_alg == NULL) { return 0; } for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { if (*sig_alg == own_sig_alg) { return 1; } } return 0; } static inline int mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported( const uint16_t sig_alg) { switch (sig_alg) { #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) #if defined(PSA_WANT_ALG_SHA_256) && defined(PSA_WANT_ECC_SECP_R1_256) case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: break; #endif /* PSA_WANT_ALG_SHA_256 && MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(PSA_WANT_ALG_SHA_384) && defined(PSA_WANT_ECC_SECP_R1_384) case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: break; #endif /* PSA_WANT_ALG_SHA_384 && MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(PSA_WANT_ALG_SHA_512) && defined(PSA_WANT_ECC_SECP_R1_521) case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: break; #endif /* PSA_WANT_ALG_SHA_512 && MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ #if defined(MBEDTLS_PKCS1_V21) #if defined(PSA_WANT_ALG_SHA_256) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: break; #endif /* PSA_WANT_ALG_SHA_256 */ #if defined(PSA_WANT_ALG_SHA_384) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: break; #endif /* PSA_WANT_ALG_SHA_384 */ #if defined(PSA_WANT_ALG_SHA_512) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: break; #endif /* PSA_WANT_ALG_SHA_512 */ #endif /* MBEDTLS_PKCS1_V21 */ default: return 0; } return 1; } static inline int mbedtls_ssl_tls13_sig_alg_is_supported( const uint16_t sig_alg) { switch (sig_alg) { #if defined(MBEDTLS_PKCS1_V15) #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: break; #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: break; #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: break; #endif /* MBEDTLS_MD_CAN_SHA512 */ #endif /* MBEDTLS_PKCS1_V15 */ default: return mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported( sig_alg); } return 1; } MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg, mbedtls_pk_context *key); #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) static inline int mbedtls_ssl_sig_alg_is_offered(const mbedtls_ssl_context *ssl, uint16_t proposed_sig_alg) { const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); if (sig_alg == NULL) { return 0; } for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { if (*sig_alg == proposed_sig_alg) { return 1; } } return 0; } static inline int mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( uint16_t sig_alg, mbedtls_pk_type_t *pk_type, mbedtls_md_type_t *md_alg) { *pk_type = mbedtls_ssl_pk_alg_from_sig(sig_alg & 0xff); *md_alg = mbedtls_ssl_md_alg_from_hash((sig_alg >> 8) & 0xff); if (*pk_type != MBEDTLS_PK_NONE && *md_alg != MBEDTLS_MD_NONE) { return 0; } switch (sig_alg) { #if defined(MBEDTLS_PKCS1_V21) #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: *md_alg = MBEDTLS_MD_SHA256; *pk_type = MBEDTLS_PK_RSASSA_PSS; break; #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: *md_alg = MBEDTLS_MD_SHA384; *pk_type = MBEDTLS_PK_RSASSA_PSS; break; #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: *md_alg = MBEDTLS_MD_SHA512; *pk_type = MBEDTLS_PK_RSASSA_PSS; break; #endif /* MBEDTLS_MD_CAN_SHA512 */ #endif /* MBEDTLS_PKCS1_V21 */ default: return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } return 0; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) static inline int mbedtls_ssl_tls12_sig_alg_is_supported( const uint16_t sig_alg) { /* High byte is hash */ unsigned char hash = MBEDTLS_BYTE_1(sig_alg); unsigned char sig = MBEDTLS_BYTE_0(sig_alg); switch (hash) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_SSL_HASH_MD5: break; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_SSL_HASH_SHA1: break; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_SSL_HASH_SHA224: break; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_SSL_HASH_SHA256: break; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_SSL_HASH_SHA384: break; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_SSL_HASH_SHA512: break; #endif default: return 0; } switch (sig) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_SSL_SIG_RSA: break; #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) case MBEDTLS_SSL_SIG_ECDSA: break; #endif default: return 0; } return 1; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ static inline int mbedtls_ssl_sig_alg_is_supported( const mbedtls_ssl_context *ssl, const uint16_t sig_alg) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { return mbedtls_ssl_tls12_sig_alg_is_supported(sig_alg); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { return mbedtls_ssl_tls13_sig_alg_is_supported(sig_alg); } #endif ((void) ssl); ((void) sig_alg); return 0; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) /* Corresponding PSA algorithm for MBEDTLS_CIPHER_NULL. * Same value is used for PSA_ALG_CATEGORY_CIPHER, hence it is * guaranteed to not be a valid PSA algorithm identifier. */ #define MBEDTLS_SSL_NULL_CIPHER 0x04000000 /** * \brief Translate mbedtls cipher type/taglen pair to psa: * algorithm, key type and key size. * * \param mbedtls_cipher_type [in] given mbedtls cipher type * \param taglen [in] given tag length * 0 - default tag length * \param alg [out] corresponding PSA alg * There is no corresponding PSA * alg for MBEDTLS_CIPHER_NULL, so * in this case MBEDTLS_SSL_NULL_CIPHER * is returned via this parameter * \param key_type [out] corresponding PSA key type * \param key_size [out] corresponding PSA key size * * \return PSA_SUCCESS on success or PSA_ERROR_NOT_SUPPORTED if * conversion is not supported. */ psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type, size_t taglen, psa_algorithm_t *alg, psa_key_type_t *key_type, size_t *key_size); #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Convert given PSA status to mbedtls error code. * * \param status [in] given PSA status * * \return corresponding mbedtls error code */ static inline MBEDTLS_DEPRECATED int psa_ssl_status_to_mbedtls(psa_status_t status) { switch (status) { case PSA_SUCCESS: return 0; case PSA_ERROR_INSUFFICIENT_MEMORY: return MBEDTLS_ERR_SSL_ALLOC_FAILED; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; case PSA_ERROR_INVALID_SIGNATURE: return MBEDTLS_ERR_SSL_INVALID_MAC; case PSA_ERROR_INVALID_ARGUMENT: return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; case PSA_ERROR_BAD_STATE: return MBEDTLS_ERR_SSL_INTERNAL_ERROR; case PSA_ERROR_BUFFER_TOO_SMALL: return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; default: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } } #endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) typedef enum { MBEDTLS_ECJPAKE_ROUND_ONE, MBEDTLS_ECJPAKE_ROUND_TWO } mbedtls_ecjpake_rounds_t; /** * \brief Parse the provided input buffer for getting the first round * of key exchange. This code is common between server and client * * \param pake_ctx [in] the PAKE's operation/context structure * \param buf [in] input buffer to parse * \param len [in] length of the input buffer * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or * MBEDTLS_ECJPAKE_ROUND_TWO * * \return 0 on success or a negative error code in case of failure */ int mbedtls_psa_ecjpake_read_round( psa_pake_operation_t *pake_ctx, const unsigned char *buf, size_t len, mbedtls_ecjpake_rounds_t round); /** * \brief Write the first round of key exchange into the provided output * buffer. This code is common between server and client * * \param pake_ctx [in] the PAKE's operation/context structure * \param buf [out] the output buffer in which data will be written to * \param len [in] length of the output buffer * \param olen [out] the length of the data really written on the buffer * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or * MBEDTLS_ECJPAKE_ROUND_TWO * * \return 0 on success or a negative error code in case of failure */ int mbedtls_psa_ecjpake_write_round( psa_pake_operation_t *pake_ctx, unsigned char *buf, size_t len, size_t *olen, mbedtls_ecjpake_rounds_t round); #endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO /** * \brief TLS record protection modes */ typedef enum { MBEDTLS_SSL_MODE_STREAM = 0, MBEDTLS_SSL_MODE_CBC, MBEDTLS_SSL_MODE_CBC_ETM, MBEDTLS_SSL_MODE_AEAD } mbedtls_ssl_mode_t; mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform( const mbedtls_ssl_transform *transform); #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( int encrypt_then_mac, const mbedtls_ssl_ciphersuite_t *suite); #else mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( const mbedtls_ssl_ciphersuite_t *suite); #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t buf_len); #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ static inline int mbedtls_ssl_tls13_cipher_suite_is_offered( mbedtls_ssl_context *ssl, int cipher_suite) { const int *ciphersuite_list = ssl->conf->ciphersuite_list; /* Check whether we have offered this ciphersuite */ for (size_t i = 0; ciphersuite_list[i] != 0; i++) { if (ciphersuite_list[i] == cipher_suite) { return 1; } } return 0; } /** * \brief Validate cipher suite against config in SSL context. * * \param ssl SSL context * \param suite_info Cipher suite to validate * \param min_tls_version Minimal TLS version to accept a cipher suite * \param max_tls_version Maximal TLS version to accept a cipher suite * * \return 0 if valid, negative value otherwise. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_validate_ciphersuite( const mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *suite_info, mbedtls_ssl_protocol_version min_tls_version, mbedtls_ssl_protocol_version max_tls_version); #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) #define MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH (2) #define MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN (64) /* As defined in RFC 8449 */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len); #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len); #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_TEST_HOOKS) int mbedtls_ssl_check_dtls_clihlo_cookie( mbedtls_ssl_context *ssl, const unsigned char *cli_id, size_t cli_id_len, const unsigned char *in, size_t in_len, unsigned char *obuf, size_t buf_len, size_t *olen); #endif #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /** * \brief Given an SSL context and its associated configuration, write the TLS * 1.3 specific Pre-Shared key extension. * * \param[in] ssl SSL context * \param[in] buf Base address of the buffer where to write the extension * \param[in] end End address of the buffer where to write the extension * \param[out] out_len Length in bytes of the Pre-Shared key extension: data * written into the buffer \p buf by this function plus * the length of the binders to be written. * \param[out] binders_len Length of the binders to be written at the end of * the extension. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, size_t *binders_len); /** * \brief Given an SSL context and its associated configuration, write the TLS * 1.3 specific Pre-Shared key extension binders at the end of the * ClientHello. * * \param[in] ssl SSL context * \param[in] buf Base address of the buffer where to write the binders * \param[in] end End address of the buffer where to write the binders */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end); #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ defined(MBEDTLS_SSL_CLI_C) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session, const char *hostname); #endif #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \ defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session, const char *alpn); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME (604800) static inline unsigned int mbedtls_ssl_tls13_session_get_ticket_flags( mbedtls_ssl_session *session, unsigned int flags) { return session->ticket_flags & (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); } /** * Check if at least one of the given flags is set in * the session ticket. See the definition of * `MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK` to get all * permitted flags. */ static inline int mbedtls_ssl_tls13_session_ticket_has_flags( mbedtls_ssl_session *session, unsigned int flags) { return mbedtls_ssl_tls13_session_get_ticket_flags(session, flags) != 0; } static inline int mbedtls_ssl_tls13_session_ticket_allow_psk( mbedtls_ssl_session *session) { return mbedtls_ssl_tls13_session_ticket_has_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION); } static inline int mbedtls_ssl_tls13_session_ticket_allow_psk_ephemeral( mbedtls_ssl_session *session) { return mbedtls_ssl_tls13_session_ticket_has_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION); } static inline unsigned int mbedtls_ssl_tls13_session_ticket_allow_early_data( mbedtls_ssl_session *session) { return mbedtls_ssl_tls13_session_ticket_has_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); } static inline void mbedtls_ssl_tls13_session_set_ticket_flags( mbedtls_ssl_session *session, unsigned int flags) { session->ticket_flags |= (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); } static inline void mbedtls_ssl_tls13_session_clear_ticket_flags( mbedtls_ssl_session *session, unsigned int flags) { session->ticket_flags &= ~(flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) #define MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT 0 #define MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT 1 #define MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK \ (1 << MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT) #define MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK \ (1 << MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT) static inline int mbedtls_ssl_conf_get_session_tickets( const mbedtls_ssl_config *conf) { return conf->session_tickets & MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK ? MBEDTLS_SSL_SESSION_TICKETS_ENABLED : MBEDTLS_SSL_SESSION_TICKETS_DISABLED; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) static inline int mbedtls_ssl_conf_is_signal_new_session_tickets_enabled( const mbedtls_ssl_config *conf) { return conf->session_tickets & MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK ? MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED : MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl); #endif #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) /** Compute the HMAC of variable-length data with constant flow. * * This function computes the HMAC of the concatenation of \p add_data and \p * data, and does with a code flow and memory access pattern that does not * depend on \p data_len_secret, but only on \p min_data_len and \p * max_data_len. In particular, this function always reads exactly \p * max_data_len bytes from \p data. * * \param ctx The HMAC context. It must have keys configured * with mbedtls_md_hmac_starts() and use one of the * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. * It is reset using mbedtls_md_hmac_reset() after * the computation is complete to prepare for the * next computation. * \param add_data The first part of the message whose HMAC is being * calculated. This must point to a readable buffer * of \p add_data_len bytes. * \param add_data_len The length of \p add_data in bytes. * \param data The buffer containing the second part of the * message. This must point to a readable buffer * of \p max_data_len bytes. * \param data_len_secret The length of the data to process in \p data. * This must be no less than \p min_data_len and no * greater than \p max_data_len. * \param min_data_len The minimal length of the second part of the * message, read from \p data. * \param max_data_len The maximal length of the second part of the * message, read from \p data. * \param output The HMAC will be written here. This must point to * a writable buffer of sufficient size to hold the * HMAC value. * * \retval 0 on success. * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED * The hardware accelerator failed. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ct_hmac(mbedtls_svc_key_id_t key, psa_algorithm_t mac_alg, const unsigned char *add_data, size_t add_data_len, const unsigned char *data, size_t data_len_secret, size_t min_data_len, size_t max_data_len, unsigned char *output); #else int mbedtls_ct_hmac(mbedtls_md_context_t *ctx, const unsigned char *add_data, size_t add_data_len, const unsigned char *data, size_t data_len_secret, size_t min_data_len, size_t max_data_len, unsigned char *output); #endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ #endif /* MBEDTLS_TEST_HOOKS && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) */ #endif /* ssl_misc.h */ webfakes/src/mbedtls/library/ecp_curves_new.c0000644000176200001440000122466514740737024021131 0ustar liggesusers/* * Elliptic curves over GF(p): curve-specific data and functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_ECP_WITH_MPI_UINT) #if defined(MBEDTLS_ECP_LIGHT) #include "mbedtls/ecp.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "constant_time_internal.h" #include "bn_mul.h" #include "bignum_core.h" #include "ecp_invasive.h" #include #if !defined(MBEDTLS_ECP_ALT) #define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) } #define ECP_MPI_INIT_ARRAY(x) \ ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) #define ECP_POINT_INIT_XY_Z0(x, y) { \ ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) } #define ECP_POINT_INIT_XY_Z1(x, y) { \ ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) } #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* For these curves, we build the group parameters dynamically. */ #define ECP_LOAD_GROUP static mbedtls_mpi_uint mpi_one[] = { 1 }; #endif /* * Note: the constants are in little-endian order * to be directly usable in MPIs */ /* * Domain parameters for secp192r1 */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static const mbedtls_mpi_uint secp192r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp192r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64), }; static const mbedtls_mpi_uint secp192r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), }; static const mbedtls_mpi_uint secp192r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), }; static const mbedtls_mpi_uint secp192r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp192r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), }; static const mbedtls_mpi_uint secp192r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), }; static const mbedtls_mpi_uint secp192r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED), }; static const mbedtls_mpi_uint secp192r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E), }; static const mbedtls_mpi_uint secp192r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E), }; static const mbedtls_mpi_uint secp192r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14), }; static const mbedtls_mpi_uint secp192r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2), }; static const mbedtls_mpi_uint secp192r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB), }; static const mbedtls_mpi_uint secp192r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7), }; static const mbedtls_mpi_uint secp192r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2), }; static const mbedtls_mpi_uint secp192r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62), }; static const mbedtls_mpi_uint secp192r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC), }; static const mbedtls_mpi_uint secp192r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F), }; static const mbedtls_mpi_uint secp192r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55), }; static const mbedtls_mpi_uint secp192r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF), }; static const mbedtls_mpi_uint secp192r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31), }; static const mbedtls_mpi_uint secp192r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC), }; static const mbedtls_mpi_uint secp192r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83), }; static const mbedtls_mpi_uint secp192r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98), }; static const mbedtls_mpi_uint secp192r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5), }; static const mbedtls_mpi_uint secp192r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD), }; static const mbedtls_mpi_uint secp192r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F), }; static const mbedtls_mpi_uint secp192r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD), }; static const mbedtls_mpi_uint secp192r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A), }; static const mbedtls_mpi_uint secp192r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66), }; static const mbedtls_mpi_uint secp192r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7), }; static const mbedtls_mpi_uint secp192r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45), }; static const mbedtls_mpi_uint secp192r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71), }; static const mbedtls_mpi_uint secp192r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC), }; static const mbedtls_mpi_uint secp192r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2), }; static const mbedtls_mpi_uint secp192r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48), }; static const mbedtls_mpi_uint secp192r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C), }; static const mbedtls_ecp_point secp192r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y), }; #else #define secp192r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ /* * Domain parameters for secp224r1 */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static const mbedtls_mpi_uint secp224r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C), MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4), }; static const mbedtls_mpi_uint secp224r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7), }; static const mbedtls_mpi_uint secp224r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD), }; static const mbedtls_mpi_uint secp224r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp224r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp224r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y), }; #else #define secp224r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ /* * Domain parameters for secp256r1 */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) static const mbedtls_mpi_uint secp256r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp256r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A), }; static const mbedtls_mpi_uint secp256r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), }; static const mbedtls_mpi_uint secp256r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), }; static const mbedtls_mpi_uint secp256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp256r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), }; static const mbedtls_mpi_uint secp256r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), }; static const mbedtls_mpi_uint secp256r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C), }; static const mbedtls_mpi_uint secp256r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4), }; static const mbedtls_mpi_uint secp256r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6), }; static const mbedtls_mpi_uint secp256r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20), }; static const mbedtls_mpi_uint secp256r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62), }; static const mbedtls_mpi_uint secp256r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7), }; static const mbedtls_mpi_uint secp256r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00), }; static const mbedtls_mpi_uint secp256r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03), }; static const mbedtls_mpi_uint secp256r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C), }; static const mbedtls_mpi_uint secp256r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3), }; static const mbedtls_mpi_uint secp256r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED), }; static const mbedtls_mpi_uint secp256r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3), }; static const mbedtls_mpi_uint secp256r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95), }; static const mbedtls_mpi_uint secp256r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68), }; static const mbedtls_mpi_uint secp256r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54), }; static const mbedtls_mpi_uint secp256r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6), }; static const mbedtls_mpi_uint secp256r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE), }; static const mbedtls_mpi_uint secp256r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4), }; static const mbedtls_mpi_uint secp256r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86), }; static const mbedtls_mpi_uint secp256r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16), }; static const mbedtls_mpi_uint secp256r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18), }; static const mbedtls_mpi_uint secp256r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C), }; static const mbedtls_mpi_uint secp256r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6), }; static const mbedtls_mpi_uint secp256r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF), }; static const mbedtls_mpi_uint secp256r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E), }; static const mbedtls_mpi_uint secp256r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44), }; static const mbedtls_mpi_uint secp256r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4), }; static const mbedtls_mpi_uint secp256r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7), }; static const mbedtls_mpi_uint secp256r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82), }; static const mbedtls_mpi_uint secp256r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43), }; static const mbedtls_ecp_point secp256r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y), }; #else #define secp256r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ /* * Domain parameters for secp384r1 */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) static const mbedtls_mpi_uint secp384r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp384r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3), }; static const mbedtls_mpi_uint secp384r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), }; static const mbedtls_mpi_uint secp384r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), }; static const mbedtls_mpi_uint secp384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp384r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), }; static const mbedtls_mpi_uint secp384r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD), }; static const mbedtls_mpi_uint secp384r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23), }; static const mbedtls_mpi_uint secp384r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE), }; static const mbedtls_mpi_uint secp384r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3), }; static const mbedtls_mpi_uint secp384r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD), }; static const mbedtls_mpi_uint secp384r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F), }; static const mbedtls_mpi_uint secp384r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48), }; static const mbedtls_mpi_uint secp384r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A), }; static const mbedtls_mpi_uint secp384r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08), }; static const mbedtls_mpi_uint secp384r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F), }; static const mbedtls_mpi_uint secp384r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74), }; static const mbedtls_mpi_uint secp384r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03), }; static const mbedtls_mpi_uint secp384r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB), }; static const mbedtls_mpi_uint secp384r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF), }; static const mbedtls_mpi_uint secp384r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97), }; static const mbedtls_mpi_uint secp384r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71), }; static const mbedtls_mpi_uint secp384r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5), }; static const mbedtls_mpi_uint secp384r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91), }; static const mbedtls_mpi_uint secp384r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5), }; static const mbedtls_mpi_uint secp384r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15), }; static const mbedtls_mpi_uint secp384r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98), }; static const mbedtls_mpi_uint secp384r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F), }; static const mbedtls_mpi_uint secp384r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10), }; static const mbedtls_mpi_uint secp384r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1), }; static const mbedtls_mpi_uint secp384r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0), }; static const mbedtls_mpi_uint secp384r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC), }; static const mbedtls_mpi_uint secp384r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6), }; static const mbedtls_mpi_uint secp384r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A), }; static const mbedtls_mpi_uint secp384r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53), }; static const mbedtls_mpi_uint secp384r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC), }; static const mbedtls_mpi_uint secp384r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85), }; static const mbedtls_mpi_uint secp384r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23), }; static const mbedtls_mpi_uint secp384r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3), }; static const mbedtls_mpi_uint secp384r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6), }; static const mbedtls_mpi_uint secp384r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67), }; static const mbedtls_mpi_uint secp384r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC), }; static const mbedtls_mpi_uint secp384r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE), }; static const mbedtls_mpi_uint secp384r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05), }; static const mbedtls_mpi_uint secp384r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA), }; static const mbedtls_mpi_uint secp384r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF), }; static const mbedtls_mpi_uint secp384r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63), }; static const mbedtls_mpi_uint secp384r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1), }; static const mbedtls_mpi_uint secp384r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D), }; static const mbedtls_mpi_uint secp384r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D), }; static const mbedtls_mpi_uint secp384r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF), }; static const mbedtls_mpi_uint secp384r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71), }; static const mbedtls_mpi_uint secp384r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B), }; static const mbedtls_mpi_uint secp384r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F), }; static const mbedtls_mpi_uint secp384r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E), }; static const mbedtls_mpi_uint secp384r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2), }; static const mbedtls_mpi_uint secp384r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7), }; static const mbedtls_mpi_uint secp384r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21), }; static const mbedtls_mpi_uint secp384r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6), }; static const mbedtls_mpi_uint secp384r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E), }; static const mbedtls_mpi_uint secp384r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6), }; static const mbedtls_mpi_uint secp384r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42), }; static const mbedtls_mpi_uint secp384r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12), }; static const mbedtls_mpi_uint secp384r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77), }; static const mbedtls_mpi_uint secp384r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B), }; static const mbedtls_mpi_uint secp384r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41), }; static const mbedtls_ecp_point secp384r1_T[32] = { ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y), }; #else #define secp384r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ /* * Domain parameters for secp521r1 */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) static const mbedtls_mpi_uint secp521r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), }; static const mbedtls_mpi_uint secp521r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95), MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00), }; static const mbedtls_mpi_uint secp521r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00), }; static const mbedtls_mpi_uint secp521r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01), }; static const mbedtls_mpi_uint secp521r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp521r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp521r1_T[32] = { ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y), }; #else #define secp521r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static const mbedtls_mpi_uint secp192k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp192k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp192k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00), }; static const mbedtls_mpi_uint secp192k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), }; static const mbedtls_mpi_uint secp192k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), }; static const mbedtls_mpi_uint secp192k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp192k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), }; static const mbedtls_mpi_uint secp192k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), }; static const mbedtls_mpi_uint secp192k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E), }; static const mbedtls_mpi_uint secp192k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7), }; static const mbedtls_mpi_uint secp192k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28), }; static const mbedtls_mpi_uint secp192k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4), }; static const mbedtls_mpi_uint secp192k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C), }; static const mbedtls_mpi_uint secp192k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A), }; static const mbedtls_mpi_uint secp192k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF), }; static const mbedtls_mpi_uint secp192k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F), }; static const mbedtls_mpi_uint secp192k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9), }; static const mbedtls_mpi_uint secp192k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D), }; static const mbedtls_mpi_uint secp192k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5), }; static const mbedtls_mpi_uint secp192k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B), }; static const mbedtls_mpi_uint secp192k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC), }; static const mbedtls_mpi_uint secp192k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E), }; static const mbedtls_mpi_uint secp192k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82), }; static const mbedtls_mpi_uint secp192k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22), }; static const mbedtls_mpi_uint secp192k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05), }; static const mbedtls_mpi_uint secp192k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96), }; static const mbedtls_mpi_uint secp192k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D), }; static const mbedtls_mpi_uint secp192k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D), }; static const mbedtls_mpi_uint secp192k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67), }; static const mbedtls_mpi_uint secp192k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C), }; static const mbedtls_mpi_uint secp192k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF), }; static const mbedtls_mpi_uint secp192k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD), }; static const mbedtls_mpi_uint secp192k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8), }; static const mbedtls_mpi_uint secp192k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9), }; static const mbedtls_mpi_uint secp192k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76), }; static const mbedtls_mpi_uint secp192k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35), }; static const mbedtls_mpi_uint secp192k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63), }; static const mbedtls_mpi_uint secp192k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8), }; static const mbedtls_ecp_point secp192k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y), }; #else #define secp192k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) static const mbedtls_mpi_uint secp224k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp224k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00), }; static const mbedtls_mpi_uint secp224k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1), }; static const mbedtls_mpi_uint secp224k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E), }; static const mbedtls_mpi_uint secp224k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp224k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp224k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y), }; #else #define secp224k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) static const mbedtls_mpi_uint secp256k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp256k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp256k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00), }; static const mbedtls_mpi_uint secp256k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), }; static const mbedtls_mpi_uint secp256k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), }; static const mbedtls_mpi_uint secp256k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp256k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), }; static const mbedtls_mpi_uint secp256k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), }; static const mbedtls_mpi_uint secp256k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0), }; static const mbedtls_mpi_uint secp256k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC), }; static const mbedtls_mpi_uint secp256k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF), }; static const mbedtls_mpi_uint secp256k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4), }; static const mbedtls_mpi_uint secp256k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54), }; static const mbedtls_mpi_uint secp256k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE), }; static const mbedtls_mpi_uint secp256k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E), }; static const mbedtls_mpi_uint secp256k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0), }; static const mbedtls_mpi_uint secp256k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B), }; static const mbedtls_mpi_uint secp256k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1), }; static const mbedtls_mpi_uint secp256k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15), }; static const mbedtls_mpi_uint secp256k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05), }; static const mbedtls_mpi_uint secp256k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72), }; static const mbedtls_mpi_uint secp256k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22), }; static const mbedtls_mpi_uint secp256k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16), }; static const mbedtls_mpi_uint secp256k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E), }; static const mbedtls_mpi_uint secp256k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E), }; static const mbedtls_mpi_uint secp256k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D), }; static const mbedtls_mpi_uint secp256k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0), }; static const mbedtls_mpi_uint secp256k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01), }; static const mbedtls_mpi_uint secp256k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12), }; static const mbedtls_mpi_uint secp256k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25), }; static const mbedtls_mpi_uint secp256k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B), }; static const mbedtls_mpi_uint secp256k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B), }; static const mbedtls_mpi_uint secp256k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64), }; static const mbedtls_mpi_uint secp256k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F), }; static const mbedtls_mpi_uint secp256k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07), }; static const mbedtls_mpi_uint secp256k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9), }; static const mbedtls_mpi_uint secp256k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89), }; static const mbedtls_mpi_uint secp256k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB), }; static const mbedtls_ecp_point secp256k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y), }; #else #define secp256k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ /* * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) static const mbedtls_mpi_uint brainpoolP256r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), }; static const mbedtls_mpi_uint brainpoolP256r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D), }; static const mbedtls_mpi_uint brainpoolP256r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26), }; static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), }; static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), }; static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80), }; static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23), }; static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36), }; static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18), }; static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47), }; static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30), }; static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87), }; static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28), }; static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10), }; static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C), }; static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19), }; static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D), }; static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E), }; static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30), }; static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C), }; static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39), }; static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57), }; static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53), }; static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E), }; static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A), }; static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51), }; static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02), }; static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17), }; static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70), }; static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72), }; static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10), }; static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85), }; static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98), }; static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F), }; static const mbedtls_ecp_point brainpoolP256r1_T[16] = { ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y), }; #else #define brainpoolP256r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ /* * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) static const mbedtls_mpi_uint brainpoolP384r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), }; static const mbedtls_mpi_uint brainpoolP384r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B), }; static const mbedtls_mpi_uint brainpoolP384r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), }; static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), }; static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), }; static const mbedtls_mpi_uint brainpoolP384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E), }; static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63), }; static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73), }; static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22), }; static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17), }; static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C), }; static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68), }; static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82), }; static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E), }; static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03), }; static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39), }; static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35), }; static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31), }; static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28), }; static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61), }; static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03), }; static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27), }; static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31), }; static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00), }; static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55), }; static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78), }; static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81), }; static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63), }; static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54), }; static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77), }; static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81), }; static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01), }; static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79), }; static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89), }; static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68), }; static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88), }; static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44), }; static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59), }; static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42), }; static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01), }; static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12), }; static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18), }; static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12), }; static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19), }; static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10), }; static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70), }; static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73), }; static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22), }; static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F), }; static const mbedtls_ecp_point brainpoolP384r1_T[32] = { ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y), }; #else #define brainpoolP384r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ /* * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) static const mbedtls_mpi_uint brainpoolP512r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), }; static const mbedtls_mpi_uint brainpoolP512r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78), }; static const mbedtls_mpi_uint brainpoolP512r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D), }; static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), }; static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), }; static const mbedtls_mpi_uint brainpoolP512r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), }; static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22), }; static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41), }; static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88), }; static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36), }; static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26), }; static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2), }; static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49), }; static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20), }; static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99), }; static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33), }; static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01), }; static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14), }; static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42), }; static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37), }; static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12), }; static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16), }; static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34), }; static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02), }; static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5), }; static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11), }; static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54), }; static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F), }; static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31), }; static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A), }; static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63), }; static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54), }; static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24), }; static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20), }; static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93), }; static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82), }; static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11), }; static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35), }; static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61), }; static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A), }; static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90), }; static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18), }; static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F), }; static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34), }; static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42), }; static const mbedtls_ecp_point brainpoolP512r1_T[32] = { ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y), }; #else #define brainpoolP512r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(ECP_LOAD_GROUP) || defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* * Create an MPI from embedded constants * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint) and * len < 1048576) */ static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len) { X->s = 1; X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint)); X->p = (mbedtls_mpi_uint *) p; } #endif #if defined(ECP_LOAD_GROUP) /* * Set an MPI to static value 1 */ static inline void ecp_mpi_set1(mbedtls_mpi *X) { X->s = 1; X->n = 1; X->p = mpi_one; } /* * Make group available from embedded constants */ static int ecp_group_load(mbedtls_ecp_group *grp, const mbedtls_mpi_uint *p, size_t plen, const mbedtls_mpi_uint *a, size_t alen, const mbedtls_mpi_uint *b, size_t blen, const mbedtls_mpi_uint *gx, size_t gxlen, const mbedtls_mpi_uint *gy, size_t gylen, const mbedtls_mpi_uint *n, size_t nlen, const mbedtls_ecp_point *T) { ecp_mpi_load(&grp->P, p, plen); if (a != NULL) { ecp_mpi_load(&grp->A, a, alen); } ecp_mpi_load(&grp->B, b, blen); ecp_mpi_load(&grp->N, n, nlen); ecp_mpi_load(&grp->G.X, gx, gxlen); ecp_mpi_load(&grp->G.Y, gy, gylen); ecp_mpi_set1(&grp->G.Z); grp->pbits = mbedtls_mpi_bitlen(&grp->P); grp->nbits = mbedtls_mpi_bitlen(&grp->N); grp->h = 1; grp->T = (mbedtls_ecp_point *) T; /* * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free. */ grp->T_size = 0; return 0; } #endif /* ECP_LOAD_GROUP */ #if defined(MBEDTLS_ECP_NIST_OPTIM) /* Forward declarations */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static int ecp_mod_p192(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static int ecp_mod_p224(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) static int ecp_mod_p256(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) static int ecp_mod_p384(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) static int ecp_mod_p521(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *N_p, size_t N_n); #endif #define NIST_MODP(P) grp->modp = ecp_mod_ ## P; #else #define NIST_MODP(P) #endif /* MBEDTLS_ECP_NIST_OPTIM */ /* Additional forward declarations */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) static int ecp_mod_p255(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) static int ecp_mod_p448(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *, size_t); #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static int ecp_mod_p192k1(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) static int ecp_mod_p224k1(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) static int ecp_mod_p256k1(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(ECP_LOAD_GROUP) #define LOAD_GROUP_A(G) ecp_group_load(grp, \ G ## _p, sizeof(G ## _p), \ G ## _a, sizeof(G ## _a), \ G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ G ## _n, sizeof(G ## _n), \ G ## _T \ ) #define LOAD_GROUP(G) ecp_group_load(grp, \ G ## _p, sizeof(G ## _p), \ NULL, 0, \ G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ G ## _n, sizeof(G ## _n), \ G ## _T \ ) #endif /* ECP_LOAD_GROUP */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /* Constants used by ecp_use_curve25519() */ static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42; /* P = 2^255 - 19 */ static const mbedtls_mpi_uint curve25519_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7F) }; /* N = 2^252 + 27742317777372353535851937790883648493 */ static const mbedtls_mpi_uint curve25519_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0XED, 0XD3, 0XF5, 0X5C, 0X1A, 0X63, 0X12, 0X58), MBEDTLS_BYTES_TO_T_UINT_8(0XD6, 0X9C, 0XF7, 0XA2, 0XDE, 0XF9, 0XDE, 0X14), MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10) }; /* * Specialized function for creating the Curve25519 group */ static int ecp_use_curve25519(mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Actually ( A + 2 ) / 4 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24)); ecp_mpi_load(&grp->P, curve25519_p, sizeof(curve25519_p)); grp->pbits = mbedtls_mpi_bitlen(&grp->P); ecp_mpi_load(&grp->N, curve25519_n, sizeof(curve25519_n)); /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); mbedtls_mpi_free(&grp->G.Y); /* Actually, the required msb for private keys */ grp->nbits = 254; cleanup: if (ret != 0) { mbedtls_ecp_group_free(grp); } return ret; } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* Constants used by ecp_use_curve448() */ static const mbedtls_mpi_sint curve448_a24 = 0x98AA; /* P = 2^448 - 2^224 - 1 */ static const mbedtls_mpi_uint curve448_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFE, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) }; /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ static const mbedtls_mpi_uint curve448_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0XF3, 0X44, 0X58, 0XAB, 0X92, 0XC2, 0X78, 0X23), MBEDTLS_BYTES_TO_T_UINT_8(0X55, 0X8F, 0XC5, 0X8D, 0X72, 0XC2, 0X6C, 0X21), MBEDTLS_BYTES_TO_T_UINT_8(0X90, 0X36, 0XD6, 0XAE, 0X49, 0XDB, 0X4E, 0XC4), MBEDTLS_BYTES_TO_T_UINT_8(0XE9, 0X23, 0XCA, 0X7C, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3F), MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) }; /* * Specialized function for creating the Curve448 group */ static int ecp_use_curve448(mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Actually ( A + 2 ) / 4 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24)); ecp_mpi_load(&grp->P, curve448_p, sizeof(curve448_p)); grp->pbits = mbedtls_mpi_bitlen(&grp->P); /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); mbedtls_mpi_free(&grp->G.Y); ecp_mpi_load(&grp->N, curve448_n, sizeof(curve448_n)); /* Actually, the required msb for private keys */ grp->nbits = 447; cleanup: if (ret != 0) { mbedtls_ecp_group_free(grp); } return ret; } #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ /* * Set a group using well-known domain parameters */ int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id) { mbedtls_ecp_group_free(grp); mbedtls_ecp_group_init(grp); grp->id = id; switch (id) { #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) case MBEDTLS_ECP_DP_SECP192R1: NIST_MODP(p192); return LOAD_GROUP(secp192r1); #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) case MBEDTLS_ECP_DP_SECP224R1: NIST_MODP(p224); return LOAD_GROUP(secp224r1); #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) case MBEDTLS_ECP_DP_SECP256R1: NIST_MODP(p256); return LOAD_GROUP(secp256r1); #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) case MBEDTLS_ECP_DP_SECP384R1: NIST_MODP(p384); return LOAD_GROUP(secp384r1); #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) case MBEDTLS_ECP_DP_SECP521R1: NIST_MODP(p521); return LOAD_GROUP(secp521r1); #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) case MBEDTLS_ECP_DP_SECP192K1: grp->modp = ecp_mod_p192k1; return LOAD_GROUP_A(secp192k1); #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) case MBEDTLS_ECP_DP_SECP224K1: grp->modp = ecp_mod_p224k1; return LOAD_GROUP_A(secp224k1); #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) case MBEDTLS_ECP_DP_SECP256K1: grp->modp = ecp_mod_p256k1; return LOAD_GROUP_A(secp256k1); #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) case MBEDTLS_ECP_DP_BP256R1: return LOAD_GROUP_A(brainpoolP256r1); #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) case MBEDTLS_ECP_DP_BP384R1: return LOAD_GROUP_A(brainpoolP384r1); #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) case MBEDTLS_ECP_DP_BP512R1: return LOAD_GROUP_A(brainpoolP512r1); #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) case MBEDTLS_ECP_DP_CURVE25519: grp->modp = ecp_mod_p255; return ecp_use_curve25519(grp); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) case MBEDTLS_ECP_DP_CURVE448: grp->modp = ecp_mod_p448; return ecp_use_curve448(grp); #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ default: grp->id = MBEDTLS_ECP_DP_NONE; return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } } #if defined(MBEDTLS_ECP_NIST_OPTIM) /* * Fast reduction modulo the primes used by the NIST curves. * * These functions are critical for speed, but not needed for correct * operations. So, we make the choice to heavily rely on the internals of our * bignum library, which creates a tight coupling between these functions and * our MPI implementation. However, the coupling between the ECP module and * MPI remains loose, since these functions can be deactivated at will. */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) /* * Compared to the way things are presented in FIPS 186-3 D.2, * we proceed in columns, from right (least significant chunk) to left, * adding chunks to N in place, and keeping a carry for the next chunk. * This avoids moving things around in memory, and uselessly adding zeros, * compared to the more straightforward, line-oriented approach. * * For this prime we need to handle data in chunks of 64 bits. * Since this is always a multiple of our basic mbedtls_mpi_uint, we can * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. */ /* Add 64-bit chunks (dst += src) and update carry */ static inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry) { unsigned char i; mbedtls_mpi_uint c = 0; for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) { *dst += c; c = (*dst < c); *dst += *src; c += (*dst < *src); } *carry += c; } /* Add carry to a 64-bit chunk and update carry */ static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry) { unsigned char i; for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) { *dst += *carry; *carry = (*dst < *carry); } } #define WIDTH 8 / sizeof(mbedtls_mpi_uint) #define A(i) Np + (i) * WIDTH #define ADD(i) add64(p, A(i), &c) #define NEXT p += WIDTH; carry64(p, &c) #define LAST p += WIDTH; do *p = 0; while (++p < end) #define RESET last_carry[0] = c; c = 0; p = Np #define ADD_LAST add64(p, last_carry, &c) /* * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) */ static int ecp_mod_p192(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(192) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) { mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 }; mbedtls_mpi_uint *p, *end; if (Nn != BITS_TO_LIMBS(192) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } p = Np; end = p + Nn; ADD(3); ADD(5); NEXT; // A0 += A3 + A5 ADD(3); ADD(4); ADD(5); NEXT; // A1 += A3 + A4 + A5 ADD(4); ADD(5); // A2 += A4 + A5 RESET; /* Use the reduction for the carry as well: * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 * It can generate a carry. */ ADD_LAST; NEXT; // A0 += last_carry ADD_LAST; NEXT; // A1 += last_carry // A2 += carry RESET; /* Use the reduction for the carry as well: * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 */ ADD_LAST; NEXT; // A0 += last_carry ADD_LAST; NEXT; // A1 += last_carry // A2 += carry LAST; return 0; } #undef WIDTH #undef A #undef ADD #undef NEXT #undef LAST #undef RESET #undef ADD_LAST #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /* * The reader is advised to first understand ecp_mod_p192() since the same * general structure is used here, but with additional complications: * (1) chunks of 32 bits, and (2) subtractions. */ /* * For these primes, we need to handle data in chunks of 32 bits. * This makes it more complicated if we use 64 bits limbs in MPI, * which prevents us from using a uniform access method as for p192. * * So, we define a mini abstraction layer to access 32 bit chunks, * load them in 'cur' for work, and store them back from 'cur' when done. * * While at it, also define the size of N in terms of 32-bit chunks. */ #define LOAD32 cur = A(i); #if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ #define MAX32 X_limbs #define A(j) X[j] #define STORE32 X[i] = (mbedtls_mpi_uint) cur; #define STORE0 X[i] = 0; #else /* 64 bit */ #define MAX32 X_limbs * 2 #define A(j) \ (j) % 2 ? \ (uint32_t) (X[(j) / 2] >> 32) : \ (uint32_t) (X[(j) / 2]) #define STORE32 \ if (i % 2) { \ X[i/2] &= 0x00000000FFFFFFFF; \ X[i/2] |= (uint64_t) (cur) << 32; \ } else { \ X[i/2] &= 0xFFFFFFFF00000000; \ X[i/2] |= (uint32_t) cur; \ } #define STORE0 \ if (i % 2) { \ X[i/2] &= 0x00000000FFFFFFFF; \ } else { \ X[i/2] &= 0xFFFFFFFF00000000; \ } #endif static inline int8_t extract_carry(int64_t cur) { return (int8_t) (cur >> 32); } #define ADD(j) cur += A(j) #define SUB(j) cur -= A(j) #define ADD_CARRY(cc) cur += (cc) #define SUB_CARRY(cc) cur -= (cc) #define ADD_LAST ADD_CARRY(last_c) #define SUB_LAST SUB_CARRY(last_c) /* * Helpers for the main 'loop' */ #define INIT(b) \ int8_t c = 0, last_c; \ int64_t cur; \ size_t i = 0; \ LOAD32; #define NEXT \ c = extract_carry(cur); \ STORE32; i++; LOAD32; \ ADD_CARRY(c); #define RESET \ c = extract_carry(cur); \ last_c = c; \ STORE32; i = 0; LOAD32; \ c = 0; \ #define LAST \ c = extract_carry(cur); \ STORE32; i++; \ if (c != 0) \ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; \ while (i < MAX32) { STORE0; i++; } #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) /* * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) */ static int ecp_mod_p224(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(224) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs) { if (X_limbs != BITS_TO_LIMBS(224) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } INIT(224); SUB(7); SUB(11); NEXT; // A0 += -A7 - A11 SUB(8); SUB(12); NEXT; // A1 += -A8 - A12 SUB(9); SUB(13); NEXT; // A2 += -A9 - A13 SUB(10); ADD(7); ADD(11); NEXT; // A3 += -A10 + A7 + A11 SUB(11); ADD(8); ADD(12); NEXT; // A4 += -A11 + A8 + A12 SUB(12); ADD(9); ADD(13); NEXT; // A5 += -A12 + A9 + A13 SUB(13); ADD(10); // A6 += -A13 + A10 RESET; /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */ SUB_LAST; NEXT; // A0 -= last_c ; NEXT; // A1 ; NEXT; // A2 ADD_LAST; NEXT; // A3 += last_c ; NEXT; // A4 ; NEXT; // A5 // A6 /* The carry reduction cannot generate a carry * (see commit 73e8553 for details)*/ LAST; return 0; } #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) /* * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) */ static int ecp_mod_p256(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(256) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p256_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs) { if (X_limbs != BITS_TO_LIMBS(256) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } INIT(256); ADD(8); ADD(9); SUB(11); SUB(12); SUB(13); SUB(14); NEXT; // A0 ADD(9); ADD(10); SUB(12); SUB(13); SUB(14); SUB(15); NEXT; // A1 ADD(10); ADD(11); SUB(13); SUB(14); SUB(15); NEXT; // A2 ADD(11); ADD(11); ADD(12); ADD(12); ADD(13); SUB(15); SUB(8); SUB(9); NEXT; // A3 ADD(12); ADD(12); ADD(13); ADD(13); ADD(14); SUB(9); SUB(10); NEXT; // A4 ADD(13); ADD(13); ADD(14); ADD(14); ADD(15); SUB(10); SUB(11); NEXT; // A5 ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13); SUB(8); SUB(9); NEXT; // A6 ADD(15); ADD(15); ADD(15); ADD(8); SUB(10); SUB(11); SUB(12); SUB(13); // A7 RESET; /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 * to modulo reduce the final carry. */ ADD_LAST; NEXT; // A0 ; NEXT; // A1 ; NEXT; // A2 SUB_LAST; NEXT; // A3 ; NEXT; // A4 ; NEXT; // A5 SUB_LAST; NEXT; // A6 ADD_LAST; // A7 RESET; /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 * to modulo reduce the carry generated by the previous reduction. */ ADD_LAST; NEXT; // A0 ; NEXT; // A1 ; NEXT; // A2 SUB_LAST; NEXT; // A3 ; NEXT; // A4 ; NEXT; // A5 SUB_LAST; NEXT; // A6 ADD_LAST; // A7 LAST; return 0; } #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /* * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) */ static int ecp_mod_p384(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(384) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p384_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs) { if (X_limbs != BITS_TO_LIMBS(384) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } INIT(384); ADD(12); ADD(21); ADD(20); SUB(23); NEXT; // A0 ADD(13); ADD(22); ADD(23); SUB(12); SUB(20); NEXT; // A1 ADD(14); ADD(23); SUB(13); SUB(21); NEXT; // A2 ADD(15); ADD(12); ADD(20); ADD(21); SUB(14); SUB(22); SUB(23); NEXT; // A3 ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22); SUB(15); SUB(23); SUB(23); NEXT; // A4 ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23); SUB(16); NEXT; // A5 ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22); SUB(17); NEXT; // A6 ADD(19); ADD(16); ADD(15); ADD(23); SUB(18); NEXT; // A7 ADD(20); ADD(17); ADD(16); SUB(19); NEXT; // A8 ADD(21); ADD(18); ADD(17); SUB(20); NEXT; // A9 ADD(22); ADD(19); ADD(18); SUB(21); NEXT; // A10 ADD(23); ADD(20); ADD(19); SUB(22); // A11 RESET; /* Use 2^384 = P + 2^128 + 2^96 - 2^32 + 1 to modulo reduce the final carry */ ADD_LAST; NEXT; // A0 SUB_LAST; NEXT; // A1 ; NEXT; // A2 ADD_LAST; NEXT; // A3 ADD_LAST; NEXT; // A4 ; NEXT; // A5 ; NEXT; // A6 ; NEXT; // A7 ; NEXT; // A8 ; NEXT; // A9 ; NEXT; // A10 // A11 RESET; ADD_LAST; NEXT; // A0 SUB_LAST; NEXT; // A1 ; NEXT; // A2 ADD_LAST; NEXT; // A3 ADD_LAST; NEXT; // A4 ; NEXT; // A5 ; NEXT; // A6 ; NEXT; // A7 ; NEXT; // A8 ; NEXT; // A9 ; NEXT; // A10 // A11 LAST; return 0; } #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #undef LOAD32 #undef MAX32 #undef A #undef STORE32 #undef STORE0 #undef ADD #undef SUB #undef ADD_CARRY #undef SUB_CARRY #undef ADD_LAST #undef SUB_LAST #undef INIT #undef NEXT #undef RESET #undef LAST #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || MBEDTLS_ECP_DP_SECP256R1_ENABLED || MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) /* Size of p521 in terms of mbedtls_mpi_uint */ #define P521_WIDTH (521 / 8 / sizeof(mbedtls_mpi_uint) + 1) /* Bits to keep in the most significant mbedtls_mpi_uint */ #define P521_MASK 0x01FF /* * Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5) */ static int ecp_mod_p521(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(521) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p521_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs) { mbedtls_mpi_uint carry = 0; if (X_limbs != BITS_TO_LIMBS(521) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Step 1: Reduction to P521_WIDTH limbs */ /* Helper references for bottom part of X */ mbedtls_mpi_uint *X0 = X; size_t X0_limbs = P521_WIDTH; /* Helper references for top part of X */ mbedtls_mpi_uint *X1 = X + X0_limbs; size_t X1_limbs = X_limbs - X0_limbs; /* Split X as X0 + 2^P521_WIDTH X1 and compute X0 + 2^(biL - 9) X1. * (We are using that 2^P521_WIDTH = 2^(512 + biL) and that * 2^(512 + biL) X1 = 2^(biL - 9) X1 mod P521.) * The high order limb of the result will be held in carry and the rest * in X0 (that is the result will be represented as * 2^P521_WIDTH carry + X0). * * Also, note that the resulting carry is either 0 or 1: * X0 < 2^P521_WIDTH = 2^(512 + biL) and X1 < 2^(P521_WIDTH-biL) = 2^512 * therefore * X0 + 2^(biL - 9) X1 < 2^(512 + biL) + 2^(512 + biL - 9) * which in turn is less than 2 * 2^(512 + biL). */ mbedtls_mpi_uint shift = ((mbedtls_mpi_uint) 1u) << (biL - 9); carry = mbedtls_mpi_core_mla(X0, X0_limbs, X1, X1_limbs, shift); /* Set X to X0 (by clearing the top part). */ memset(X1, 0, X1_limbs * sizeof(mbedtls_mpi_uint)); /* Step 2: Reduction modulo P521 * * At this point X is reduced to P521_WIDTH limbs. What remains is to add * the carry (that is 2^P521_WIDTH carry) and to reduce mod P521. */ /* 2^P521_WIDTH carry = 2^(512 + biL) carry = 2^(biL - 9) carry mod P521. * Also, recall that carry is either 0 or 1. */ mbedtls_mpi_uint addend = carry << (biL - 9); /* Keep the top 9 bits and reduce the rest, using 2^521 = 1 mod P521. */ addend += (X[P521_WIDTH - 1] >> 9); X[P521_WIDTH - 1] &= P521_MASK; /* Reuse the top part of X (already zeroed) as a helper array for * carrying out the addition. */ mbedtls_mpi_uint *addend_arr = X + P521_WIDTH; addend_arr[0] = addend; (void) mbedtls_mpi_core_add(X, X, addend_arr, P521_WIDTH); /* Both addends were less than P521 therefore X < 2 * P521. (This also means * that the result fit in P521_WIDTH limbs and there won't be any carry.) */ /* Clear the reused part of X. */ addend_arr[0] = 0; return 0; } #undef P521_WIDTH #undef P521_MASK #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #endif /* MBEDTLS_ECP_NIST_OPTIM */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /* Size of p255 in terms of mbedtls_mpi_uint */ #define P255_WIDTH (255 / 8 / sizeof(mbedtls_mpi_uint) + 1) /* * Fast quasi-reduction modulo p255 = 2^255 - 19 * Write N as A0 + 2^256 A1, return A0 + 38 * A1 */ static int ecp_mod_p255(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(255) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p255_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_Limbs) { if (X_Limbs != BITS_TO_LIMBS(255) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } mbedtls_mpi_uint *carry = mbedtls_calloc(P255_WIDTH, ciL); if (carry == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } /* Step 1: Reduction to P255_WIDTH limbs */ if (X_Limbs > P255_WIDTH) { /* Helper references for top part of X */ mbedtls_mpi_uint * const A1 = X + P255_WIDTH; const size_t A1_limbs = X_Limbs - P255_WIDTH; /* X = A0 + 38 * A1, capture carry out */ *carry = mbedtls_mpi_core_mla(X, P255_WIDTH, A1, A1_limbs, 38); /* Clear top part */ memset(A1, 0, sizeof(mbedtls_mpi_uint) * A1_limbs); } /* Step 2: Reduce to <2p * Split as A0 + 2^255*c, with c a scalar, and compute A0 + 19*c */ *carry <<= 1; *carry += (X[P255_WIDTH - 1] >> (biL - 1)); *carry *= 19; /* Clear top bit */ X[P255_WIDTH - 1] <<= 1; X[P255_WIDTH - 1] >>= 1; /* Since the top bit for X has been cleared 0 + 0 + Carry * will not overflow. * * Furthermore for 2p = 2^256-38. When a carry propagation on the highest * limb occurs, X > 2^255 and all the remaining bits on the limb are zero. * - If X < 2^255 ==> X < 2p * - If X > 2^255 ==> X < 2^256 - 2^255 < 2p */ (void) mbedtls_mpi_core_add(X, X, carry, P255_WIDTH); mbedtls_free(carry); return 0; } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* Size of p448 in terms of mbedtls_mpi_uint */ #define P448_WIDTH (448 / 8 / sizeof(mbedtls_mpi_uint)) /* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ #define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y)) #define P224_SIZE (224 / 8) #define P224_WIDTH_MIN (P224_SIZE / sizeof(mbedtls_mpi_uint)) #define P224_WIDTH_MAX DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint)) #define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224) static int ecp_mod_p448(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(448) * 2; /* This is required as some tests and use cases do not pass in a Bignum of * the correct size, and expect the growth to be done automatically, which * will no longer happen. */ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p448_raw(N->p, N->n); cleanup: return ret; } /* * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 + * (B0 + B1) * 2^224. This is different to the reference implementation of * Curve448, which uses its own special 56-bit limbs rather than a generic * bignum library. We could squeeze some extra speed out on 32-bit machines by * splitting N up into 32-bit limbs and doing the arithmetic using the limbs * directly as we do for the NIST primes above, but for 64-bit targets it should * use half the number of operations if we do the reduction with 224-bit limbs, * since mpi_core_add will then use 64-bit adds. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs) { size_t round; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (X_limbs != BITS_TO_LIMBS(448) * 2) { return 0; } size_t M_limbs = X_limbs - (P448_WIDTH); if (M_limbs > P448_WIDTH) { /* Shouldn't be called with X larger than 2^896! */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Both M and Q require an extra limb to catch carries. */ M_limbs++; const size_t Q_limbs = M_limbs; mbedtls_mpi_uint *M = NULL; mbedtls_mpi_uint *Q = NULL; M = mbedtls_calloc(M_limbs, ciL); if (M == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } Q = mbedtls_calloc(Q_limbs, ciL); if (Q == NULL) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } /* M = A1 */ memset(M, 0, (M_limbs * ciL)); /* Do not copy into the overflow limb, as this would read past the end of * X. */ memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL)); /* X = A0 */ memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL)); /* X = X + M = A0 + A1 */ /* Carry here fits in oversize X. Oversize M means it will get * added in, not returned as carry. */ (void) mbedtls_mpi_core_add(X, X, M, M_limbs); /* Q = B1 = M >> 224 */ memcpy(Q, (char *) M + P224_SIZE, P224_SIZE); memset((char *) Q + P224_SIZE, 0, P224_SIZE); /* X = X + Q = (A0 + A1) + B1 * Oversize Q catches potential carry here when X is already max 448 bits. */ (void) mbedtls_mpi_core_add(X, X, Q, Q_limbs); /* M = B0 */ #ifdef MBEDTLS_HAVE_INT64 M[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS); #endif memset(M + P224_WIDTH_MAX, 0, ((M_limbs - P224_WIDTH_MAX) * ciL)); /* M = M + Q = B0 + B1 */ (void) mbedtls_mpi_core_add(M, M, Q, Q_limbs); /* M = (B0 + B1) * 2^224 */ /* Shifted carry bit from the addition fits in oversize M. */ memmove((char *) M + P224_SIZE, M, P224_SIZE + ciL); memset(M, 0, P224_SIZE); /* X = X + M = (A0 + A1 + B1) + (B0 + B1) * 2^224 */ (void) mbedtls_mpi_core_add(X, X, M, M_limbs); /* In the second and third rounds A1 and B0 have at most 1 non-zero limb and * B1=0. * Using this we need to calculate: * A0 + A1 + B1 + (B0 + B1) * 2^224 = A0 + A1 + B0 * 2^224. */ for (round = 0; round < 2; ++round) { /* M = A1 */ memset(M, 0, (M_limbs * ciL)); memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL)); /* X = A0 */ memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL)); /* M = A1 + B0 * 2^224 * We know that only one limb of A1 will be non-zero and that it will be * limb 0. We also know that B0 is the bottom 224 bits of A1 (which is * then shifted up 224 bits), so, given M is currently A1 this turns * into: * M = M + (M << 224) * As the single non-zero limb in B0 will be A1 limb 0 shifted up by 224 * bits, we can just move that into the right place, shifted up * accordingly.*/ M[P224_WIDTH_MIN] = M[0] << (224 & (biL - 1)); /* X = A0 + (A1 + B0 * 2^224) */ (void) mbedtls_mpi_core_add(X, X, M, M_limbs); } ret = 0; cleanup: mbedtls_free(M); mbedtls_free(Q); return ret; } #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* * Fast quasi-reduction modulo P = 2^s - R, * with R about 33 bits, used by the Koblitz curves. * * Write X as A0 + 2^224 A1, return A0 + R * A1. */ #define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X, size_t X_limbs, mbedtls_mpi_uint *R, size_t bits) { int ret = 0; /* Determine if A1 is aligned to limb bitsize. If not then the used limbs * of P, A0 and A1 must be set accordingly and there is a middle limb * which is shared by A0 and A1 and need to handle accordingly. */ size_t shift = bits % biL; size_t adjust = (shift + biL - 1) / biL; size_t P_limbs = bits / biL + adjust; mbedtls_mpi_uint *A1 = mbedtls_calloc(P_limbs, ciL); if (A1 == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } /* Create a buffer to store the value of `R * A1` */ size_t R_limbs = P_KOBLITZ_R; size_t M_limbs = P_limbs + R_limbs; mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL); if (M == NULL) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } mbedtls_mpi_uint mask = 0; if (adjust != 0) { mask = ((mbedtls_mpi_uint) 1 << shift) - 1; } /* Two passes are needed to reduce the value of `A0 + R * A1` and then * we need an additional one to reduce the possible overflow during * the addition. */ for (size_t pass = 0; pass < 3; pass++) { /* Copy A1 */ memcpy(A1, X + P_limbs - adjust, P_limbs * ciL); /* Shift A1 to be aligned */ if (shift != 0) { mbedtls_mpi_core_shift_r(A1, P_limbs, shift); } /* Zeroize the A1 part of the shared limb */ if (mask != 0) { X[P_limbs - 1] &= mask; } /* X = A0 * Zeroize the A1 part of X to keep only the A0 part. */ for (size_t i = P_limbs; i < X_limbs; i++) { X[i] = 0; } /* X = A0 + R * A1 */ mbedtls_mpi_core_mul(M, A1, P_limbs, R, R_limbs); (void) mbedtls_mpi_core_add(X, X, M, P_limbs + R_limbs); /* Carry can not be generated since R is a 33-bit value and stored in * 64 bits. The result value of the multiplication is at most * P length + 33 bits in length and the result value of the addition * is at most P length + 34 bits in length. So the result of the * addition always fits in P length + 64 bits. */ } cleanup: mbedtls_free(M); mbedtls_free(A1); return ret; } #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || MBEDTLS_ECP_DP_SECP224K1_ENABLED) || MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) /* * Fast quasi-reduction modulo p192k1 = 2^192 - R, * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 */ static int ecp_mod_p192k1(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(192) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p192k1_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) { static mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; if (X_limbs != BITS_TO_LIMBS(192) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return ecp_mod_koblitz(X, X_limbs, Rp, 192); } #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) /* * Fast quasi-reduction modulo p224k1 = 2^224 - R, * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 */ static int ecp_mod_p224k1(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(224) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p224k1_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) { static mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; if (X_limbs != BITS_TO_LIMBS(224) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return ecp_mod_koblitz(X, X_limbs, Rp, 224); } #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* * Fast quasi-reduction modulo p256k1 = 2^256 - R, * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 */ static int ecp_mod_p256k1(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(256) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p256k1_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) { static mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; if (X_limbs != BITS_TO_LIMBS(256) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return ecp_mod_koblitz(X, X_limbs, Rp, 256); } #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_TEST_HOOKS) MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_ecp_group_id id, const mbedtls_ecp_modulus_type ctype) { mbedtls_mpi_modp_fn modp = NULL; mbedtls_mpi_uint *p = NULL; size_t p_limbs; if (!(ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE || \ ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_SCALAR)) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } switch (id) { #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) case MBEDTLS_ECP_DP_SECP192R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p192_raw; #endif p = (mbedtls_mpi_uint *) secp192r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p)); } else { p = (mbedtls_mpi_uint *) secp192r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) case MBEDTLS_ECP_DP_SECP224R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p224_raw; #endif p = (mbedtls_mpi_uint *) secp224r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p)); } else { p = (mbedtls_mpi_uint *) secp224r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) case MBEDTLS_ECP_DP_SECP256R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p256_raw; #endif p = (mbedtls_mpi_uint *) secp256r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p)); } else { p = (mbedtls_mpi_uint *) secp256r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) case MBEDTLS_ECP_DP_SECP384R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p384_raw; #endif p = (mbedtls_mpi_uint *) secp384r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p)); } else { p = (mbedtls_mpi_uint *) secp384r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) case MBEDTLS_ECP_DP_SECP521R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p521_raw; #endif p = (mbedtls_mpi_uint *) secp521r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p)); } else { p = (mbedtls_mpi_uint *) secp521r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) case MBEDTLS_ECP_DP_BP256R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { p = (mbedtls_mpi_uint *) brainpoolP256r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p)); } else { p = (mbedtls_mpi_uint *) brainpoolP256r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) case MBEDTLS_ECP_DP_BP384R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { p = (mbedtls_mpi_uint *) brainpoolP384r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p)); } else { p = (mbedtls_mpi_uint *) brainpoolP384r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) case MBEDTLS_ECP_DP_BP512R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { p = (mbedtls_mpi_uint *) brainpoolP512r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p)); } else { p = (mbedtls_mpi_uint *) brainpoolP512r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) case MBEDTLS_ECP_DP_CURVE25519: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p255_raw; p = (mbedtls_mpi_uint *) curve25519_p; p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p)); } else { p = (mbedtls_mpi_uint *) curve25519_n; p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) case MBEDTLS_ECP_DP_SECP192K1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p192k1_raw; p = (mbedtls_mpi_uint *) secp192k1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p)); } else { p = (mbedtls_mpi_uint *) secp192k1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) case MBEDTLS_ECP_DP_SECP224K1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p224k1_raw; p = (mbedtls_mpi_uint *) secp224k1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p)); } else { p = (mbedtls_mpi_uint *) secp224k1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) case MBEDTLS_ECP_DP_SECP256K1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p256k1_raw; p = (mbedtls_mpi_uint *) secp256k1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p)); } else { p = (mbedtls_mpi_uint *) secp256k1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) case MBEDTLS_ECP_DP_CURVE448: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p448_raw; p = (mbedtls_mpi_uint *) curve448_p; p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p)); } else { p = (mbedtls_mpi_uint *) curve448_n; p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n)); } break; #endif default: case MBEDTLS_ECP_DP_NONE: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } if (modp != NULL) { if (mbedtls_mpi_mod_optred_modulus_setup(N, p, p_limbs, modp)) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } } else { if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs)) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } } return 0; } #endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_TEST_HOOKS) MBEDTLS_STATIC_TESTABLE mbedtls_ecp_variant mbedtls_ecp_get_variant(void) { return MBEDTLS_ECP_VARIANT_WITH_MPI_UINT; } #endif /* MBEDTLS_TEST_HOOKS */ #endif /* !MBEDTLS_ECP_ALT */ #endif /* MBEDTLS_ECP_LIGHT */ #endif /* MBEDTLS_ECP_WITH_MPI_UINT */ webfakes/src/mbedtls/library/ssl_ticket.c0000644000176200001440000004103414740737024020250 0ustar liggesusers/* * TLS server tickets callbacks implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_TICKET_C) #include "mbedtls/platform.h" #include "ssl_misc.h" #include "mbedtls/ssl_ticket.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif /* * Initialize context */ void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx) { memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif } #define MAX_KEY_BYTES MBEDTLS_SSL_TICKET_MAX_KEY_BYTES #define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES #define TICKET_IV_BYTES 12 #define TICKET_CRYPT_LEN_BYTES 2 #define TICKET_AUTH_TAG_BYTES 16 #define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES + \ TICKET_IV_BYTES + \ TICKET_CRYPT_LEN_BYTES + \ TICKET_AUTH_TAG_BYTES) #define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES + \ TICKET_IV_BYTES + \ TICKET_CRYPT_LEN_BYTES) /* * Generate/update a key */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx, unsigned char index) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[MAX_KEY_BYTES] = { 0 }; mbedtls_ssl_ticket_key *key = ctx->keys + index; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; #endif #if defined(MBEDTLS_HAVE_TIME) key->generation_time = mbedtls_time(NULL); #endif /* The lifetime of a key is the configured lifetime of the tickets when * the key is created. */ key->lifetime = ctx->ticket_lifetime; if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) { return ret; } if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) { return ret; } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, key->alg); psa_set_key_type(&attributes, key->key_type); psa_set_key_bits(&attributes, key->key_bits); ret = PSA_TO_MBEDTLS_ERR( psa_import_key(&attributes, buf, PSA_BITS_TO_BYTES(key->key_bits), &key->key)); #else /* With GCM and CCM, same context can encrypt & decrypt */ ret = mbedtls_cipher_setkey(&key->ctx, buf, mbedtls_cipher_get_key_bitlen(&key->ctx), MBEDTLS_ENCRYPT); #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } /* * Rotate/generate keys if necessary */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx) { #if !defined(MBEDTLS_HAVE_TIME) ((void) ctx); #else mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active; if (key->lifetime != 0) { mbedtls_time_t current_time = mbedtls_time(NULL); mbedtls_time_t key_time = key->generation_time; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif if (current_time >= key_time && (uint64_t) (current_time - key_time) < key->lifetime) { return 0; } ctx->active = 1 - ctx->active; #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return ssl_ticket_gen_key(ctx, ctx->active); } else #endif /* MBEDTLS_HAVE_TIME */ return 0; } /* * Rotate active session ticket encryption key */ int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx, const unsigned char *name, size_t nlength, const unsigned char *k, size_t klength, uint32_t lifetime) { const unsigned char idx = 1 - ctx->active; mbedtls_ssl_ticket_key * const key = ctx->keys + idx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const size_t bitlen = key->key_bits; #else const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx); #endif if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); return ret; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, key->alg); psa_set_key_type(&attributes, key->key_type); psa_set_key_bits(&attributes, key->key_bits); if ((status = psa_import_key(&attributes, k, PSA_BITS_TO_BYTES(key->key_bits), &key->key)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); return ret; } #else ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT); if (ret != 0) { return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ ctx->active = idx; ctx->ticket_lifetime = lifetime; memcpy(key->name, name, TICKET_KEY_NAME_BYTES); #if defined(MBEDTLS_HAVE_TIME) key->generation_time = mbedtls_time(NULL); #endif key->lifetime = lifetime; return 0; } /* * Setup context for actual use */ int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_cipher_type_t cipher, uint32_t lifetime) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t key_bits; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t alg; psa_key_type_t key_type; #else const mbedtls_cipher_info_t *cipher_info; #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES, &alg, &key_type, &key_bits) != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (PSA_ALG_IS_AEAD(alg) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #else cipher_info = mbedtls_cipher_info_from_type(cipher); if (mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_GCM && mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CCM && mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CHACHAPOLY) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } key_bits = mbedtls_cipher_info_get_key_bitlen(cipher_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (key_bits > 8 * MAX_KEY_BYTES) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ctx->f_rng = f_rng; ctx->p_rng = p_rng; ctx->ticket_lifetime = lifetime; #if defined(MBEDTLS_USE_PSA_CRYPTO) ctx->keys[0].alg = alg; ctx->keys[0].key_type = key_type; ctx->keys[0].key_bits = key_bits; ctx->keys[1].alg = alg; ctx->keys[1].key_type = key_type; ctx->keys[1].key_bits = key_bits; #else if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) { return ret; } if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) { return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 || (ret = ssl_ticket_gen_key(ctx, 1)) != 0) { return ret; } return 0; } /* * Create session ticket, with the following structure: * * struct { * opaque key_name[4]; * opaque iv[12]; * opaque encrypted_state<0..2^16-1>; * opaque tag[16]; * } ticket; * * The key_name, iv, and length of encrypted_state are the additional * authenticated data. */ int mbedtls_ssl_ticket_write(void *p_ticket, const mbedtls_ssl_session *session, unsigned char *start, const unsigned char *end, size_t *tlen, uint32_t *ticket_lifetime) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_ticket_context *ctx = p_ticket; mbedtls_ssl_ticket_key *key; unsigned char *key_name = start; unsigned char *iv = start + TICKET_KEY_NAME_BYTES; unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; size_t clear_len, ciph_len; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif *tlen = 0; if (ctx == NULL || ctx->f_rng == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, * in addition to session itself, that will be checked when writing it. */ MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN); #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif if ((ret = ssl_ticket_update_keys(ctx)) != 0) { goto cleanup; } key = &ctx->keys[ctx->active]; *ticket_lifetime = key->lifetime; memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES); if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) { goto cleanup; } /* Dump session state */ if ((ret = mbedtls_ssl_session_save(session, state, (size_t) (end - state), &clear_len)) != 0 || (unsigned long) clear_len > 65535) { goto cleanup; } MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0); /* Encrypt and authenticate */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES, key_name, TICKET_ADD_DATA_LEN, state, clear_len, state, end - state, &ciph_len)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto cleanup; } #else if ((ret = mbedtls_cipher_auth_encrypt_ext(&key->ctx, iv, TICKET_IV_BYTES, /* Additional data: key name, IV and length */ key_name, TICKET_ADD_DATA_LEN, state, clear_len, state, (size_t) (end - state), &ciph_len, TICKET_AUTH_TAG_BYTES)) != 0) { goto cleanup; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) { ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES; cleanup: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * Select key based on name */ static mbedtls_ssl_ticket_key *ssl_ticket_select_key( mbedtls_ssl_ticket_context *ctx, const unsigned char name[4]) { unsigned char i; for (i = 0; i < sizeof(ctx->keys) / sizeof(*ctx->keys); i++) { if (memcmp(name, ctx->keys[i].name, 4) == 0) { return &ctx->keys[i]; } } return NULL; } /* * Load session ticket (see mbedtls_ssl_ticket_write for structure) */ int mbedtls_ssl_ticket_parse(void *p_ticket, mbedtls_ssl_session *session, unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_ticket_context *ctx = p_ticket; mbedtls_ssl_ticket_key *key; unsigned char *key_name = buf; unsigned char *iv = buf + TICKET_KEY_NAME_BYTES; unsigned char *enc_len_p = iv + TICKET_IV_BYTES; unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; size_t enc_len, clear_len; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif if (ctx == NULL || ctx->f_rng == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (len < TICKET_MIN_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif if ((ret = ssl_ticket_update_keys(ctx)) != 0) { goto cleanup; } enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0); if (len != TICKET_MIN_LEN + enc_len) { ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; goto cleanup; } /* Select key */ if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) { /* We can't know for sure but this is a likely option unless we're * under attack - this is only informative anyway */ ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; goto cleanup; } /* Decrypt and authenticate */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES, key_name, TICKET_ADD_DATA_LEN, ticket, enc_len + TICKET_AUTH_TAG_BYTES, ticket, enc_len, &clear_len)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto cleanup; } #else if ((ret = mbedtls_cipher_auth_decrypt_ext(&key->ctx, iv, TICKET_IV_BYTES, /* Additional data: key name, IV and length */ key_name, TICKET_ADD_DATA_LEN, ticket, enc_len + TICKET_AUTH_TAG_BYTES, ticket, enc_len, &clear_len, TICKET_AUTH_TAG_BYTES)) != 0) { if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) { ret = MBEDTLS_ERR_SSL_INVALID_MAC; } goto cleanup; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (clear_len != enc_len) { ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } /* Actually load session */ if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) { goto cleanup; } #if defined(MBEDTLS_HAVE_TIME) mbedtls_ms_time_t ticket_creation_time, ticket_age; mbedtls_ms_time_t ticket_lifetime = (mbedtls_ms_time_t) key->lifetime * 1000; ret = mbedtls_ssl_session_get_ticket_creation_time(session, &ticket_creation_time); if (ret != 0) { goto cleanup; } ticket_age = mbedtls_ms_time() - ticket_creation_time; if (ticket_age < 0 || ticket_age > ticket_lifetime) { ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; goto cleanup; } #endif cleanup: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * Free context */ void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_destroy_key(ctx->keys[0].key); psa_destroy_key(ctx->keys[1].key); #else mbedtls_cipher_free(&ctx->keys[0].ctx); mbedtls_cipher_free(&ctx->keys[1].ctx); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&ctx->mutex); #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context)); } #endif /* MBEDTLS_SSL_TICKET_C */ webfakes/src/mbedtls/library/psa_crypto_slot_management.c0000644000176200001440000011611214740737024023524 0ustar liggesusers/* * PSA crypto layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include "psa/crypto.h" #include "psa_crypto_core.h" #include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_slot_management.h" #include "psa_crypto_storage.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #include "psa_crypto_se.h" #endif #include #include #include "mbedtls/platform.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /* Make sure we have distinct ranges of key identifiers for distinct * purposes. */ MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MIN < PSA_KEY_ID_USER_MAX, "Empty user key ID range"); MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN < PSA_KEY_ID_VENDOR_MAX, "Empty vendor key ID range"); MBEDTLS_STATIC_ASSERT(MBEDTLS_PSA_KEY_ID_BUILTIN_MIN < MBEDTLS_PSA_KEY_ID_BUILTIN_MAX, "Empty builtin key ID range"); MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MIN < PSA_KEY_ID_VOLATILE_MAX, "Empty volatile key ID range"); MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MAX < PSA_KEY_ID_VENDOR_MIN || PSA_KEY_ID_VENDOR_MAX < PSA_KEY_ID_USER_MIN, "Overlap between user key IDs and vendor key IDs"); MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN && MBEDTLS_PSA_KEY_ID_BUILTIN_MAX <= PSA_KEY_ID_VENDOR_MAX, "Builtin key identifiers are not in the vendor range"); MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= PSA_KEY_ID_VOLATILE_MIN && PSA_KEY_ID_VOLATILE_MAX <= PSA_KEY_ID_VENDOR_MAX, "Volatile key identifiers are not in the vendor range"); MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MAX < MBEDTLS_PSA_KEY_ID_BUILTIN_MIN || MBEDTLS_PSA_KEY_ID_BUILTIN_MAX < PSA_KEY_ID_VOLATILE_MIN, "Overlap between builtin key IDs and volatile key IDs"); #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) /* Dynamic key store. * * The key store consists of multiple slices. * * The volatile keys are stored in variable-sized tables called slices. * Slices are allocated on demand and deallocated when possible. * The size of slices increases exponentially, so the average overhead * (number of slots that are allocated but not used) is roughly * proportional to the number of keys (with a factor that grows * when the key store is fragmented). * * One slice is dedicated to the cache of persistent and built-in keys. * For simplicity, they are separated from volatile keys. This cache * slice has a fixed size and has the slice index KEY_SLOT_CACHE_SLICE_INDEX, * located after the slices for volatile keys. */ /* Size of the last slice containing the cache of persistent and built-in keys. */ #define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT /* Volatile keys are stored in slices 0 through * (KEY_SLOT_VOLATILE_SLICE_COUNT - 1) inclusive. * Each slice is twice the size of the previous slice. * Volatile key identifiers encode the slice number as follows: * bits 30..31: 0b10 (mandated by the PSA Crypto specification). * bits 25..29: slice index (0...KEY_SLOT_VOLATILE_SLICE_COUNT-1) * bits 0..24: slot index in slice */ #define KEY_ID_SLOT_INDEX_WIDTH 25u #define KEY_ID_SLICE_INDEX_WIDTH 5u #define KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH 16u #define KEY_SLOT_VOLATILE_SLICE_COUNT 22u #define KEY_SLICE_COUNT (KEY_SLOT_VOLATILE_SLICE_COUNT + 1u) #define KEY_SLOT_CACHE_SLICE_INDEX KEY_SLOT_VOLATILE_SLICE_COUNT /* Check that the length of the largest slice (calculated as * KEY_SLICE_LENGTH_MAX below) does not overflow size_t. We use * an indirect method in case the calculation of KEY_SLICE_LENGTH_MAX * itself overflows uintmax_t: if (BASE_LENGTH << c) * overflows size_t then BASE_LENGTH > SIZE_MAX >> c. */ #if (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH > \ SIZE_MAX >> (KEY_SLOT_VOLATILE_SLICE_COUNT - 1)) #error "Maximum slice length overflows size_t" #endif #if KEY_ID_SLICE_INDEX_WIDTH + KEY_ID_SLOT_INDEX_WIDTH > 30 #error "Not enough room in volatile key IDs for slice index and slot index" #endif #if KEY_SLOT_VOLATILE_SLICE_COUNT > (1 << KEY_ID_SLICE_INDEX_WIDTH) #error "Too many slices to fit the slice index in a volatile key ID" #endif #define KEY_SLICE_LENGTH_MAX \ (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << (KEY_SLOT_VOLATILE_SLICE_COUNT - 1)) #if KEY_SLICE_LENGTH_MAX > 1 << KEY_ID_SLOT_INDEX_WIDTH #error "Not enough room in volatile key IDs for a slot index in the largest slice" #endif #if KEY_ID_SLICE_INDEX_WIDTH > 8 #error "Slice index does not fit in uint8_t for psa_key_slot_t::slice_index" #endif /* Calculate the volatile key id to use for a given slot. * This function assumes valid parameter values. */ static psa_key_id_t volatile_key_id_of_index(size_t slice_idx, size_t slot_idx) { /* We assert above that the slice and slot indexes fit in separate * bit-fields inside psa_key_id_t, which is a 32-bit type per the * PSA Cryptography specification. */ return (psa_key_id_t) (0x40000000u | (slice_idx << KEY_ID_SLOT_INDEX_WIDTH) | slot_idx); } /* Calculate the slice containing the given volatile key. * This function assumes valid parameter values. */ static size_t slice_index_of_volatile_key_id(psa_key_id_t key_id) { size_t mask = (1LU << KEY_ID_SLICE_INDEX_WIDTH) - 1; return (key_id >> KEY_ID_SLOT_INDEX_WIDTH) & mask; } /* Calculate the index of the slot containing the given volatile key. * This function assumes valid parameter values. */ static size_t slot_index_of_volatile_key_id(psa_key_id_t key_id) { return key_id & ((1LU << KEY_ID_SLOT_INDEX_WIDTH) - 1); } /* In global_data.first_free_slot_index, use this special value to * indicate that the slice is full. */ #define FREE_SLOT_INDEX_NONE ((size_t) -1) #if defined(MBEDTLS_TEST_HOOKS) size_t psa_key_slot_volatile_slice_count(void) { return KEY_SLOT_VOLATILE_SLICE_COUNT; } #endif #else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ /* Static key store. * * All the keys (volatile or persistent) are in a single slice. * We only use slices as a concept to allow some differences between * static and dynamic key store management to be buried in auxiliary * functions. */ #define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT #define KEY_SLICE_COUNT 1u #define KEY_SLOT_CACHE_SLICE_INDEX 0 #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ typedef struct { #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) psa_key_slot_t *key_slices[KEY_SLICE_COUNT]; size_t first_free_slot_index[KEY_SLOT_VOLATILE_SLICE_COUNT]; #else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT]; #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ uint8_t key_slots_initialized; } psa_global_data_t; static psa_global_data_t global_data; static uint8_t psa_get_key_slots_initialized(void) { uint8_t initialized; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ initialized = global_data.key_slots_initialized; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ return initialized; } /** The length of the given slice in the key slot table. * * \param slice_idx The slice number. It must satisfy * 0 <= slice_idx < KEY_SLICE_COUNT. * * \return The number of elements in the given slice. */ static inline size_t key_slice_length(size_t slice_idx); /** Get a pointer to the slot where the given volatile key is located. * * \param key_id The key identifier. It must be a valid volatile key * identifier. * \return A pointer to the only slot that the given key * can be in. Note that the slot may be empty or * contain a different key. */ static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id); /** Get a pointer to an entry in the persistent key cache. * * \param slot_idx The index in the table. It must satisfy * 0 <= slot_idx < PERSISTENT_KEY_CACHE_COUNT. * \return A pointer to the slot containing the given * persistent key cache entry. */ static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx); /** Get a pointer to a slot given by slice and index. * * \param slice_idx The slice number. It must satisfy * 0 <= slice_idx < KEY_SLICE_COUNT. * \param slot_idx An index in the given slice. It must satisfy * 0 <= slot_idx < key_slice_length(slice_idx). * * \return A pointer to the given slot. */ static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx); #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) #if defined(MBEDTLS_TEST_HOOKS) size_t (*mbedtls_test_hook_psa_volatile_key_slice_length)(size_t slice_idx) = NULL; #endif static inline size_t key_slice_length(size_t slice_idx) { if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) { return PERSISTENT_KEY_CACHE_COUNT; } else { #if defined(MBEDTLS_TEST_HOOKS) if (mbedtls_test_hook_psa_volatile_key_slice_length != NULL) { return mbedtls_test_hook_psa_volatile_key_slice_length(slice_idx); } #endif return KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << slice_idx; } } static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id) { size_t slice_idx = slice_index_of_volatile_key_id(key_id); if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) { return NULL; } size_t slot_idx = slot_index_of_volatile_key_id(key_id); if (slot_idx >= key_slice_length(slice_idx)) { return NULL; } psa_key_slot_t *slice = global_data.key_slices[slice_idx]; if (slice == NULL) { return NULL; } return &slice[slot_idx]; } static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx) { return &global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX][slot_idx]; } static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx) { return &global_data.key_slices[slice_idx][slot_idx]; } #else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ static inline size_t key_slice_length(size_t slice_idx) { (void) slice_idx; return ARRAY_LENGTH(global_data.key_slots); } static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id) { MBEDTLS_STATIC_ASSERT(ARRAY_LENGTH(global_data.key_slots) <= PSA_KEY_ID_VOLATILE_MAX - PSA_KEY_ID_VOLATILE_MIN + 1, "The key slot array is larger than the volatile key ID range"); return &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN]; } static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx) { return &global_data.key_slots[slot_idx]; } static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx) { (void) slice_idx; return &global_data.key_slots[slot_idx]; } #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok) { psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); if ((PSA_KEY_ID_USER_MIN <= key_id) && (key_id <= PSA_KEY_ID_USER_MAX)) { return 1; } if (vendor_ok && (PSA_KEY_ID_VENDOR_MIN <= key_id) && (key_id <= PSA_KEY_ID_VENDOR_MAX)) { return 1; } return 0; } /** Get the description in memory of a key given its identifier and lock it. * * The descriptions of volatile keys and loaded persistent keys are * stored in key slots. This function returns a pointer to the key slot * containing the description of a key given its identifier. * * The function searches the key slots containing the description of the key * with \p key identifier. The function does only read accesses to the key * slots. The function does not load any persistent key thus does not access * any storage. * * For volatile key identifiers, only one key slot is queried as a volatile * key with identifier key_id can only be stored in slot of index * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ). * * On success, the function locks the key slot. It is the responsibility of * the caller to unlock the key slot when it does not access it anymore. * * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param key Key identifier to query. * \param[out] p_slot On success, `*p_slot` contains a pointer to the * key slot containing the description of the key * identified by \p key. * * \retval #PSA_SUCCESS * The pointer to the key slot containing the description of the key * identified by \p key was returned. * \retval #PSA_ERROR_INVALID_HANDLE * \p key is not a valid key identifier. * \retval #PSA_ERROR_DOES_NOT_EXIST * There is no key with key identifier \p key in the key slots. */ static psa_status_t psa_get_and_lock_key_slot_in_memory( mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); size_t slot_idx; psa_key_slot_t *slot = NULL; if (psa_key_id_is_volatile(key_id)) { slot = get_volatile_key_slot(key_id); /* Check if both the PSA key identifier key_id and the owner * identifier of key match those of the key slot. */ if (slot != NULL && slot->state == PSA_SLOT_FULL && mbedtls_svc_key_id_equal(key, slot->attr.id)) { status = PSA_SUCCESS; } else { status = PSA_ERROR_DOES_NOT_EXIST; } } else { if (!psa_is_valid_key_id(key, 1)) { return PSA_ERROR_INVALID_HANDLE; } for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) { slot = get_persistent_key_slot(slot_idx); /* Only consider slots which are in a full state. */ if ((slot->state == PSA_SLOT_FULL) && (mbedtls_svc_key_id_equal(key, slot->attr.id))) { break; } } status = (slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT) ? PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST; } if (status == PSA_SUCCESS) { status = psa_register_read(slot); if (status == PSA_SUCCESS) { *p_slot = slot; } } return status; } psa_status_t psa_initialize_key_slots(void) { #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] = mbedtls_calloc(PERSISTENT_KEY_CACHE_COUNT, sizeof(*global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX])); if (global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } #else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ /* Nothing to do: program startup and psa_wipe_all_key_slots() both * guarantee that the key slots are initialized to all-zero, which * means that all the key slots are in a valid, empty state. The global * data mutex is already held when calling this function, so no need to * lock it here, to set the flag. */ #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ global_data.key_slots_initialized = 1; return PSA_SUCCESS; } void psa_wipe_all_key_slots(void) { for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) { #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) if (global_data.key_slices[slice_idx] == NULL) { continue; } #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) { psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx); #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) /* When MBEDTLS_PSA_KEY_STORE_DYNAMIC is disabled, calling * psa_wipe_key_slot() on an unused slot is useless, but it * happens to work (because we flip the state to PENDING_DELETION). * * When MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, * psa_wipe_key_slot() needs to have a valid slice_index * field, but that value might not be correct in a * free slot, so we must not call it. * * Bypass the call to psa_wipe_key_slot() if the slot is empty, * but only if MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, to save * a few bytes of code size otherwise. */ if (slot->state == PSA_SLOT_EMPTY) { continue; } #endif slot->var.occupied.registered_readers = 1; slot->state = PSA_SLOT_PENDING_DELETION; (void) psa_wipe_key_slot(slot); } #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) mbedtls_free(global_data.key_slices[slice_idx]); global_data.key_slices[slice_idx] = NULL; #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ } #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) for (size_t slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) { global_data.first_free_slot_index[slice_idx] = 0; } #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ /* The global data mutex is already held when calling this function. */ global_data.key_slots_initialized = 0; } #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) static psa_status_t psa_allocate_volatile_key_slot(psa_key_id_t *key_id, psa_key_slot_t **p_slot) { size_t slice_idx; for (slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) { if (global_data.first_free_slot_index[slice_idx] != FREE_SLOT_INDEX_NONE) { break; } } if (slice_idx == KEY_SLOT_VOLATILE_SLICE_COUNT) { return PSA_ERROR_INSUFFICIENT_MEMORY; } if (global_data.key_slices[slice_idx] == NULL) { global_data.key_slices[slice_idx] = mbedtls_calloc(key_slice_length(slice_idx), sizeof(psa_key_slot_t)); if (global_data.key_slices[slice_idx] == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } } psa_key_slot_t *slice = global_data.key_slices[slice_idx]; size_t slot_idx = global_data.first_free_slot_index[slice_idx]; *key_id = volatile_key_id_of_index(slice_idx, slot_idx); psa_key_slot_t *slot = &slice[slot_idx]; size_t next_free = slot_idx + 1 + slot->var.free.next_free_relative_to_next; if (next_free >= key_slice_length(slice_idx)) { next_free = FREE_SLOT_INDEX_NONE; } global_data.first_free_slot_index[slice_idx] = next_free; /* The .next_free field is not meaningful when the slot is not free, * so give it the same content as freshly initialized memory. */ slot->var.free.next_free_relative_to_next = 0; psa_status_t status = psa_key_slot_state_transition(slot, PSA_SLOT_EMPTY, PSA_SLOT_FILLING); if (status != PSA_SUCCESS) { /* The only reason for failure is if the slot state was not empty. * This indicates that something has gone horribly wrong. * In this case, we leave the slot out of the free list, and stop * modifying it. This minimizes any further corruption. The slot * is a memory leak, but that's a lesser evil. */ return status; } *p_slot = slot; /* We assert at compile time that the slice index fits in uint8_t. */ slot->slice_index = (uint8_t) slice_idx; return PSA_SUCCESS; } psa_status_t psa_free_key_slot(size_t slice_idx, psa_key_slot_t *slot) { if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) { /* This is a cache entry. We don't maintain a free list, so * there's nothing to do. */ return PSA_SUCCESS; } if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) { return PSA_ERROR_CORRUPTION_DETECTED; } psa_key_slot_t *slice = global_data.key_slices[slice_idx]; psa_key_slot_t *slice_end = slice + key_slice_length(slice_idx); if (slot < slice || slot >= slice_end) { /* The slot isn't actually in the slice! We can't detect that * condition for sure, because the pointer comparison itself is * undefined behavior in that case. That same condition makes the * subtraction to calculate the slot index also UB. * Give up now to avoid causing further corruption. */ return PSA_ERROR_CORRUPTION_DETECTED; } size_t slot_idx = slot - slice; size_t next_free = global_data.first_free_slot_index[slice_idx]; if (next_free >= key_slice_length(slice_idx)) { /* The slot was full. The newly freed slot thus becomes the * end of the free list. */ next_free = key_slice_length(slice_idx); } global_data.first_free_slot_index[slice_idx] = slot_idx; slot->var.free.next_free_relative_to_next = (int32_t) next_free - (int32_t) slot_idx - 1; return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, psa_key_slot_t **p_slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t slot_idx; psa_key_slot_t *selected_slot, *unused_persistent_key_slot; if (!psa_get_key_slots_initialized()) { status = PSA_ERROR_BAD_STATE; goto error; } #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) if (volatile_key_id != NULL) { return psa_allocate_volatile_key_slot(volatile_key_id, p_slot); } #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ /* With a dynamic key store, allocate an entry in the cache slice, * applicable only to non-volatile keys that get cached in RAM. * With a static key store, allocate an entry in the sole slice, * applicable to all keys. */ selected_slot = unused_persistent_key_slot = NULL; for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) { psa_key_slot_t *slot = get_key_slot(KEY_SLOT_CACHE_SLICE_INDEX, slot_idx); if (slot->state == PSA_SLOT_EMPTY) { selected_slot = slot; break; } if ((unused_persistent_key_slot == NULL) && (slot->state == PSA_SLOT_FULL) && (!psa_key_slot_has_readers(slot)) && (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime))) { unused_persistent_key_slot = slot; } } /* * If there is no unused key slot and there is at least one unlocked key * slot containing the description of a persistent key, recycle the first * such key slot we encountered. If we later need to operate on the * persistent key we are evicting now, we will reload its description from * storage. */ if ((selected_slot == NULL) && (unused_persistent_key_slot != NULL)) { selected_slot = unused_persistent_key_slot; psa_register_read(selected_slot); status = psa_wipe_key_slot(selected_slot); if (status != PSA_SUCCESS) { goto error; } } if (selected_slot != NULL) { status = psa_key_slot_state_transition(selected_slot, PSA_SLOT_EMPTY, PSA_SLOT_FILLING); if (status != PSA_SUCCESS) { goto error; } #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) selected_slot->slice_index = KEY_SLOT_CACHE_SLICE_INDEX; #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ #if !defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) if (volatile_key_id != NULL) { /* Refresh slot_idx, for when the slot is not the original * selected_slot but rather unused_persistent_key_slot. */ slot_idx = selected_slot - global_data.key_slots; *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + slot_idx; } #endif *p_slot = selected_slot; return PSA_SUCCESS; } status = PSA_ERROR_INSUFFICIENT_MEMORY; error: *p_slot = NULL; return status; } #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot) { psa_status_t status = PSA_SUCCESS; uint8_t *key_data = NULL; size_t key_data_length = 0; status = psa_load_persistent_key(&slot->attr, &key_data, &key_data_length); if (status != PSA_SUCCESS) { goto exit; } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Special handling is required for loading keys associated with a * dynamically registered SE interface. */ const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if (psa_get_se_driver(slot->attr.lifetime, &drv, &drv_context)) { psa_se_key_data_storage_t *data; if (key_data_length != sizeof(*data)) { status = PSA_ERROR_DATA_INVALID; goto exit; } data = (psa_se_key_data_storage_t *) key_data; status = psa_copy_key_material_into_slot( slot, data->slot_number, sizeof(data->slot_number)); goto exit; } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ status = psa_copy_key_material_into_slot(slot, key_data, key_data_length); if (status != PSA_SUCCESS) { goto exit; } exit: psa_free_persistent_key_data(key_data, key_data_length); return status; } #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) static psa_status_t psa_load_builtin_key_into_slot(psa_key_slot_t *slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE; psa_drv_slot_number_t slot_number = 0; size_t key_buffer_size = 0; size_t key_buffer_length = 0; if (!psa_key_id_is_builtin( MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id))) { return PSA_ERROR_DOES_NOT_EXIST; } /* Check the platform function to see whether this key actually exists */ status = mbedtls_psa_platform_get_builtin_key( slot->attr.id, &lifetime, &slot_number); if (status != PSA_SUCCESS) { return status; } /* Set required key attributes to ensure get_builtin_key can retrieve the * full attributes. */ psa_set_key_id(&attributes, slot->attr.id); psa_set_key_lifetime(&attributes, lifetime); /* Get the full key attributes from the driver in order to be able to * calculate the required buffer size. */ status = psa_driver_wrapper_get_builtin_key( slot_number, &attributes, NULL, 0, NULL); if (status != PSA_ERROR_BUFFER_TOO_SMALL) { /* Builtin keys cannot be defined by the attributes alone */ if (status == PSA_SUCCESS) { status = PSA_ERROR_CORRUPTION_DETECTED; } return status; } /* If the key should exist according to the platform, then ask the driver * what its expected size is. */ status = psa_driver_wrapper_get_key_buffer_size(&attributes, &key_buffer_size); if (status != PSA_SUCCESS) { return status; } /* Allocate a buffer of the required size and load the builtin key directly * into the (now properly sized) slot buffer. */ status = psa_allocate_buffer_to_slot(slot, key_buffer_size); if (status != PSA_SUCCESS) { return status; } status = psa_driver_wrapper_get_builtin_key( slot_number, &attributes, slot->key.data, slot->key.bytes, &key_buffer_length); if (status != PSA_SUCCESS) { goto exit; } /* Copy actual key length and core attributes into the slot on success */ slot->key.bytes = key_buffer_length; slot->attr = attributes; exit: if (status != PSA_SUCCESS) { psa_remove_key_data_from_memory(slot); } return status; } #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; *p_slot = NULL; if (!psa_get_key_slots_initialized()) { return PSA_ERROR_BAD_STATE; } #if defined(MBEDTLS_THREADING_C) /* We need to set status as success, otherwise CORRUPTION_DETECTED * would be returned if the lock fails. */ status = PSA_SUCCESS; /* If the key is persistent and not loaded, we cannot unlock the mutex * between checking if the key is loaded and setting the slot as FULL, * as otherwise another thread may load and then destroy the key * in the meantime. */ PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif /* * On success, the pointer to the slot is passed directly to the caller * thus no need to unlock the key slot here. */ status = psa_get_and_lock_key_slot_in_memory(key, p_slot); if (status != PSA_ERROR_DOES_NOT_EXIST) { #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } /* Loading keys from storage requires support for such a mechanism */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \ defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) status = psa_reserve_free_key_slot(NULL, p_slot); if (status != PSA_SUCCESS) { #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } (*p_slot)->attr.id = key; (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; status = PSA_ERROR_DOES_NOT_EXIST; #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) /* Load keys in the 'builtin' range through their own interface */ status = psa_load_builtin_key_into_slot(*p_slot); #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (status == PSA_ERROR_DOES_NOT_EXIST) { status = psa_load_persistent_key_into_slot(*p_slot); } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ if (status != PSA_SUCCESS) { psa_wipe_key_slot(*p_slot); /* If the key does not exist, we need to return * PSA_ERROR_INVALID_HANDLE. */ if (status == PSA_ERROR_DOES_NOT_EXIST) { status = PSA_ERROR_INVALID_HANDLE; } } else { /* Add implicit usage flags. */ psa_extend_key_usage_flags(&(*p_slot)->attr.policy.usage); psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING, PSA_SLOT_FULL); status = psa_register_read(*p_slot); } #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ status = PSA_ERROR_INVALID_HANDLE; #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ if (status != PSA_SUCCESS) { *p_slot = NULL; } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } psa_status_t psa_unregister_read(psa_key_slot_t *slot) { if (slot == NULL) { return PSA_SUCCESS; } if ((slot->state != PSA_SLOT_FULL) && (slot->state != PSA_SLOT_PENDING_DELETION)) { return PSA_ERROR_CORRUPTION_DETECTED; } /* If we are the last reader and the slot is marked for deletion, * we must wipe the slot here. */ if ((slot->state == PSA_SLOT_PENDING_DELETION) && (slot->var.occupied.registered_readers == 1)) { return psa_wipe_key_slot(slot); } if (psa_key_slot_has_readers(slot)) { slot->var.occupied.registered_readers--; return PSA_SUCCESS; } /* * As the return error code may not be handled in case of multiple errors, * do our best to report if there are no registered readers. Assert with * MBEDTLS_TEST_HOOK_TEST_ASSERT that there are registered readers: * if the MBEDTLS_TEST_HOOKS configuration option is enabled and * the function is called as part of the execution of a test suite, the * execution of the test suite is stopped in error if the assertion fails. */ MBEDTLS_TEST_HOOK_TEST_ASSERT(psa_key_slot_has_readers(slot)); return PSA_ERROR_CORRUPTION_DETECTED; } psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_THREADING_C) /* We need to set status as success, otherwise CORRUPTION_DETECTED * would be returned if the lock fails. */ status = PSA_SUCCESS; PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif status = psa_unregister_read(slot); #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime, psa_se_drv_table_entry_t **p_drv) { if (psa_key_lifetime_is_external(lifetime)) { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Check whether a driver is registered against this lifetime */ psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime); if (driver != NULL) { if (p_drv != NULL) { *p_drv = driver; } return PSA_SUCCESS; } #else /* MBEDTLS_PSA_CRYPTO_SE_C */ (void) p_drv; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ /* Key location for external keys gets checked by the wrapper */ return PSA_SUCCESS; } else { /* Local/internal keys are always valid */ return PSA_SUCCESS; } } psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime) { if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { /* Volatile keys are always supported */ return PSA_SUCCESS; } else { /* Persistent keys require storage support */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)) { return PSA_ERROR_INVALID_ARGUMENT; } else { return PSA_SUCCESS; } #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ return PSA_ERROR_NOT_SUPPORTED; #endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ } } psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle) { #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \ defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) psa_status_t status; psa_key_slot_t *slot; status = psa_get_and_lock_key_slot(key, &slot); if (status != PSA_SUCCESS) { *handle = PSA_KEY_HANDLE_INIT; if (status == PSA_ERROR_INVALID_HANDLE) { status = PSA_ERROR_DOES_NOT_EXIST; } return status; } *handle = key; return psa_unregister_read_under_mutex(slot); #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ (void) key; *handle = PSA_KEY_HANDLE_INIT; return PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ } psa_status_t psa_close_key(psa_key_handle_t handle) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; if (psa_key_handle_is_null(handle)) { return PSA_SUCCESS; } #if defined(MBEDTLS_THREADING_C) /* We need to set status as success, otherwise CORRUPTION_DETECTED * would be returned if the lock fails. */ status = PSA_SUCCESS; PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif status = psa_get_and_lock_key_slot_in_memory(handle, &slot); if (status != PSA_SUCCESS) { if (status == PSA_ERROR_DOES_NOT_EXIST) { status = PSA_ERROR_INVALID_HANDLE; } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } if (slot->var.occupied.registered_readers == 1) { status = psa_wipe_key_slot(slot); } else { status = psa_unregister_read(slot); } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } psa_status_t psa_purge_key(mbedtls_svc_key_id_t key) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; #if defined(MBEDTLS_THREADING_C) /* We need to set status as success, otherwise CORRUPTION_DETECTED * would be returned if the lock fails. */ status = PSA_SUCCESS; PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif status = psa_get_and_lock_key_slot_in_memory(key, &slot); if (status != PSA_SUCCESS) { #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) && (slot->var.occupied.registered_readers == 1)) { status = psa_wipe_key_slot(slot); } else { status = psa_unregister_read(slot); } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats) { memset(stats, 0, sizeof(*stats)); for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) { #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) if (global_data.key_slices[slice_idx] == NULL) { continue; } #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) { const psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx); if (slot->state == PSA_SLOT_EMPTY) { ++stats->empty_slots; continue; } if (psa_key_slot_has_readers(slot)) { ++stats->locked_slots; } if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { ++stats->volatile_slots; } else { psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id); ++stats->persistent_slots; if (id > stats->max_open_internal_key_id) { stats->max_open_internal_key_id = id; } } if (PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime) != PSA_KEY_LOCATION_LOCAL_STORAGE) { psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id); ++stats->external_slots; if (id > stats->max_open_external_key_id) { stats->max_open_external_key_id = id; } } } } } #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/ecp_internal_alt.h0000644000176200001440000002504214740737024021415 0ustar liggesusers/** * \file ecp_internal_alt.h * * \brief Function declarations for alternative implementation of elliptic curve * point arithmetic. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. * * * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis * for elliptic curve cryptosystems. In : Cryptographic Hardware and * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. * * * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to * render ECC resistant against Side Channel Attacks. IACR Cryptology * ePrint Archive, 2004, vol. 2004, p. 342. * * * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. * * * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic * Curve Cryptography. * * [6] Digital Signature Standard (DSS), FIPS 186-4. * * * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer * Security (TLS), RFC 4492. * * * [8] * * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. * Springer Science & Business Media, 1 Aug 2000 */ #ifndef MBEDTLS_ECP_INTERNAL_H #define MBEDTLS_ECP_INTERNAL_H #include "mbedtls/build_info.h" #if defined(MBEDTLS_ECP_INTERNAL_ALT) /** * \brief Indicate if the Elliptic Curve Point module extension can * handle the group. * * \param grp The pointer to the elliptic curve group that will be the * basis of the cryptographic computations. * * \return Non-zero if successful. */ unsigned char mbedtls_internal_ecp_grp_capable(const mbedtls_ecp_group *grp); /** * \brief Initialise the Elliptic Curve Point module extension. * * If mbedtls_internal_ecp_grp_capable returns true for a * group, this function has to be able to initialise the * module for it. * * This module can be a driver to a crypto hardware * accelerator, for which this could be an initialise function. * * \param grp The pointer to the group the module needs to be * initialised for. * * \return 0 if successful. */ int mbedtls_internal_ecp_init(const mbedtls_ecp_group *grp); /** * \brief Frees and deallocates the Elliptic Curve Point module * extension. * * \param grp The pointer to the group the module was initialised for. */ void mbedtls_internal_ecp_free(const mbedtls_ecp_group *grp); #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) /** * \brief Randomize jacobian coordinates: * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. * * \param grp Pointer to the group representing the curve. * * \param pt The point on the curve to be randomised, given with Jacobian * coordinates. * * \param f_rng A function pointer to the random number generator. * * \param p_rng A pointer to the random number generator state. * * \return 0 if successful. */ int mbedtls_internal_ecp_randomize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) /** * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. * * The coordinates of Q must be normalized (= affine), * but those of P don't need to. R is not normalized. * * This function is used only as a subrutine of * ecp_mul_comb(). * * Special cases: (1) P or Q is zero, (2) R is zero, * (3) P == Q. * None of these cases can happen as intermediate step in * ecp_mul_comb(): * - at each step, P, Q and R are multiples of the base * point, the factor being less than its order, so none of * them is zero; * - Q is an odd multiple of the base point, P an even * multiple, due to the choice of precomputed points in the * modified comb method. * So branches for these cases do not leak secret information. * * We accept Q->Z being unset (saving memory in tables) as * meaning 1. * * Cost in field operations if done by [5] 3.22: * 1A := 8M + 3S * * \param grp Pointer to the group representing the curve. * * \param R Pointer to a point structure to hold the result. * * \param P Pointer to the first summand, given with Jacobian * coordinates * * \param Q Pointer to the second summand, given with affine * coordinates. * * \return 0 if successful. */ int mbedtls_internal_ecp_add_mixed(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q); #endif /** * \brief Point doubling R = 2 P, Jacobian coordinates. * * Cost: 1D := 3M + 4S (A == 0) * 4M + 4S (A == -3) * 3M + 6S + 1a otherwise * when the implementation is based on the "dbl-1998-cmo-2" * doubling formulas in [8] and standard optimizations are * applied when curve parameter A is one of { 0, -3 }. * * \param grp Pointer to the group representing the curve. * * \param R Pointer to a point structure to hold the result. * * \param P Pointer to the point that has to be doubled, given with * Jacobian coordinates. * * \return 0 if successful. */ #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) int mbedtls_internal_ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P); #endif /** * \brief Normalize jacobian coordinates of an array of (pointers to) * points. * * Using Montgomery's trick to perform only one inversion mod P * the cost is: * 1N(t) := 1I + (6t - 3)M + 1S * (See for example Algorithm 10.3.4. in [9]) * * This function is used only as a subrutine of * ecp_mul_comb(). * * Warning: fails (returning an error) if one of the points is * zero! * This should never happen, see choice of w in ecp_mul_comb(). * * \param grp Pointer to the group representing the curve. * * \param T Array of pointers to the points to normalise. * * \param t_len Number of elements in the array. * * \return 0 if successful, * an error if one of the points is zero. */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) int mbedtls_internal_ecp_normalize_jac_many(const mbedtls_ecp_group *grp, mbedtls_ecp_point *T[], size_t t_len); #endif /** * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. * * Cost in field operations if done by [5] 3.2.1: * 1N := 1I + 3M + 1S * * \param grp Pointer to the group representing the curve. * * \param pt pointer to the point to be normalised. This is an * input/output parameter. * * \return 0 if successful. */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) int mbedtls_internal_ecp_normalize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt); #endif #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) int mbedtls_internal_ecp_double_add_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, const mbedtls_mpi *d); #endif /** * \brief Randomize projective x/z coordinates: * (X, Z) -> (l X, l Z) for random l * * \param grp pointer to the group representing the curve * * \param P the point on the curve to be randomised given with * projective coordinates. This is an input/output parameter. * * \param f_rng a function pointer to the random number generator * * \param p_rng a pointer to the random number generator state * * \return 0 if successful */ #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) int mbedtls_internal_ecp_randomize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /** * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. * * \param grp pointer to the group representing the curve * * \param P pointer to the point to be normalised. This is an * input/output parameter. * * \return 0 if successful */ #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) int mbedtls_internal_ecp_normalize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P); #endif #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #endif /* ecp_internal_alt.h */ webfakes/src/mbedtls/library/ssl_client.c0000644000176200001440000010351314740737024020244 0ustar liggesusers/* * TLS 1.2 and 1.3 client-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_SSL_PROTO_TLS1_2) #include #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "ssl_client.h" #include "ssl_misc.h" #include "ssl_tls13_keys.h" #include "ssl_debug_helpers.h" #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hostname_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; size_t hostname_len; *olen = 0; if (ssl->hostname == NULL) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding server name extension: %s", ssl->hostname)); hostname_len = strlen(ssl->hostname); MBEDTLS_SSL_CHK_BUF_PTR(p, end, hostname_len + 9); /* * Sect. 3, RFC 6066 (TLS Extensions Definitions) * * In order to provide any of the server names, clients MAY include an * extension of type "server_name" in the (extended) client hello. The * "extension_data" field of this extension SHALL contain * "ServerNameList" where: * * struct { * NameType name_type; * select (name_type) { * case host_name: HostName; * } name; * } ServerName; * * enum { * host_name(0), (255) * } NameType; * * opaque HostName<1..2^16-1>; * * struct { * ServerName server_name_list<1..2^16-1> * } ServerNameList; * */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SERVERNAME, p, 0); p += 2; MBEDTLS_PUT_UINT16_BE(hostname_len + 5, p, 0); p += 2; MBEDTLS_PUT_UINT16_BE(hostname_len + 3, p, 0); p += 2; *p++ = MBEDTLS_BYTE_0(MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME); MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0); p += 2; memcpy(p, ssl->hostname, hostname_len); *olen = hostname_len + 9; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SERVERNAME); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ return 0; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ALPN) /* * ssl_write_alpn_ext() * * Structure of the application_layer_protocol_negotiation extension in * ClientHello: * * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len) { unsigned char *p = buf; *out_len = 0; if (ssl->conf->alpn_list == NULL) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding alpn extension")); /* Check we have enough space for the extension type (2 bytes), the * extension length (2 bytes) and the protocol_name_list length (2 bytes). */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0); /* Skip writing extension and list length for now */ p += 6; /* * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; */ for (const char **cur = ssl->conf->alpn_list; *cur != NULL; cur++) { /* * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of * protocol names is less than 255. */ size_t protocol_name_len = strlen(*cur); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + protocol_name_len); *p++ = (unsigned char) protocol_name_len; memcpy(p, *cur, protocol_name_len); p += protocol_name_len; } *out_len = (size_t) (p - buf); /* List length = *out_len - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ MBEDTLS_PUT_UINT16_BE(*out_len - 6, buf, 4); /* Extension length = *out_len - 2 (ext_type) - 2 (ext_len) */ MBEDTLS_PUT_UINT16_BE(*out_len - 4, buf, 2); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ return 0; } #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) /* * Function for writing a supported groups (TLS 1.3) or supported elliptic * curves (TLS 1.2) extension. * * The "extension_data" field of a supported groups extension contains a * "NamedGroupList" value (TLS 1.3 RFC8446): * enum { * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), * x25519(0x001D), x448(0x001E), * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), * ffdhe6144(0x0103), ffdhe8192(0x0104), * ffdhe_private_use(0x01FC..0x01FF), * ecdhe_private_use(0xFE00..0xFEFF), * (0xFFFF) * } NamedGroup; * struct { * NamedGroup named_group_list<2..2^16-1>; * } NamedGroupList; * * The "extension_data" field of a supported elliptic curves extension contains * a "NamedCurveList" value (TLS 1.2 RFC 8422): * enum { * deprecated(1..22), * secp256r1 (23), secp384r1 (24), secp521r1 (25), * x25519(29), x448(30), * reserved (0xFE00..0xFEFF), * deprecated(0xFF01..0xFF02), * (0xFFFF) * } NamedCurve; * struct { * NamedCurve named_curve_list<2..2^16-1> * } NamedCurveList; * * The TLS 1.3 supported groups extension was defined to be a compatible * generalization of the TLS 1.2 supported elliptic curves extension. They both * share the same extension identifier. * */ #define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG 1 #define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG 2 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, int flags, size_t *out_len) { unsigned char *p = buf; unsigned char *named_group_list; /* Start of named_group_list */ size_t named_group_list_len; /* Length of named_group_list */ const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported_groups extension")); /* Check if we have space for header and length fields: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - named_group_list_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); p += 6; named_group_list = p; if (group_list == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *group_list != 0; group_list++) { int propose_group = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("got supported group(%04x)", *group_list)); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG) { #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list) && (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) != MBEDTLS_ECP_DP_NONE)) { propose_group = 1; } #endif #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) { propose_group = 1; } #endif } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) if ((flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG) && mbedtls_ssl_tls12_named_group_is_ecdhe(*group_list) && (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) != MBEDTLS_ECP_DP_NONE)) { propose_group = 1; } #endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC */ if (propose_group) { MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(*group_list, p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(3, ("NamedGroup: %s ( %x )", mbedtls_ssl_named_group_to_str(*group_list), *group_list)); } } /* Length of named_group_list */ named_group_list_len = (size_t) (p - named_group_list); if (named_group_list_len == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("No group available.")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Write extension_type */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, buf, 0); /* Write extension_data_length */ MBEDTLS_PUT_UINT16_BE(named_group_list_len + 2, buf, 2); /* Write length of named_group_list */ MBEDTLS_PUT_UINT16_BE(named_group_list_len, buf, 4); MBEDTLS_SSL_DEBUG_BUF(3, "Supported groups extension", buf + 4, named_group_list_len + 2); *out_len = (size_t) (p - buf); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_SUPPORTED_GROUPS); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ return 0; } #endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC || MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_client_hello_cipher_suites( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, int *tls12_uses_ec, size_t *out_len) { unsigned char *p = buf; const int *ciphersuite_list; unsigned char *cipher_suites; /* Start of the cipher_suites list */ size_t cipher_suites_len; *tls12_uses_ec = 0; *out_len = 0; /* * Ciphersuite list * * This is a list of the symmetric cipher options supported by * the client, specifically the record protection algorithm * ( including secret key length ) and a hash to be used with * HKDF, in descending order of client preference. */ ciphersuite_list = ssl->conf->ciphersuite_list; /* Check there is space for the cipher suite list length (2 bytes). */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p += 2; /* Write cipher_suites * CipherSuite cipher_suites<2..2^16-2>; */ cipher_suites = p; for (size_t i = 0; ciphersuite_list[i] != 0; i++) { int cipher_suite = ciphersuite_list[i]; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); if (mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, ssl->handshake->min_tls_version, ssl->tls_version) != 0) { continue; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)) *tls12_uses_ec |= mbedtls_ssl_ciphersuite_uses_ec(ciphersuite_info); #endif MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, add ciphersuite: %04x, %s", (unsigned int) cipher_suite, ciphersuite_info->name)); /* Check there is space for the cipher suite identifier (2 bytes). */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(cipher_suite, p, 0); p += 2; } /* * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ int renegotiating = 0; #if defined(MBEDTLS_SSL_RENEGOTIATION) renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE); #endif if (!renegotiating) { MBEDTLS_SSL_DEBUG_MSG(3, ("adding EMPTY_RENEGOTIATION_INFO_SCSV")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0); p += 2; } /* Write the cipher_suites length in number of bytes */ cipher_suites_len = (size_t) (p - cipher_suites); MBEDTLS_PUT_UINT16_BE(cipher_suites_len, buf, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, got %" MBEDTLS_PRINTF_SIZET " cipher suites", cipher_suites_len/2)); /* Output the total length of cipher_suites field. */ *out_len = (size_t) (p - buf); return 0; } /* * Structure of the TLS 1.3 ClientHello message: * * struct { * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 * Random random; * opaque legacy_session_id<0..32>; * CipherSuite cipher_suites<2..2^16-2>; * opaque legacy_compression_methods<1..2^8-1>; * Extension extensions<8..2^16-1>; * } ClientHello; * * Structure of the (D)TLS 1.2 ClientHello message: * * struct { * ProtocolVersion client_version; * Random random; * SessionID session_id; * opaque cookie<0..2^8-1>; // DTLS 1.2 ONLY * CipherSuite cipher_suites<2..2^16-2>; * CompressionMethod compression_methods<1..2^8-1>; * select (extensions_present) { * case false: * struct {}; * case true: * Extension extensions<0..2^16-1>; * }; * } ClientHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_client_hello_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, size_t *binders_len) { int ret; mbedtls_ssl_handshake_params *handshake = ssl->handshake; unsigned char *p = buf; unsigned char *p_extensions_len; /* Pointer to extensions length */ size_t output_len; /* Length of buffer used by function */ size_t extensions_len; /* Length of the list of extensions*/ int tls12_uses_ec = 0; *out_len = 0; *binders_len = 0; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) unsigned char propose_tls12 = (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) && (MBEDTLS_SSL_VERSION_TLS1_2 <= ssl->tls_version); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) unsigned char propose_tls13 = (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3) && (MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version); #endif /* * Write client_version (TLS 1.2) or legacy_version (TLS 1.3) * * In all cases this is the TLS 1.2 version. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); mbedtls_ssl_write_version(p, ssl->conf->transport, MBEDTLS_SSL_VERSION_TLS1_2); p += 2; /* ... * Random random; * ... * * The random bytes have been prepared by ssl_prepare_client_hello() into * the handshake->randbytes buffer and are copied here into the output * buffer. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); memcpy(p, handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; /* TLS 1.2: * ... * SessionID session_id; * ... * with * opaque SessionID<0..32>; * * TLS 1.3: * ... * opaque legacy_session_id<0..32>; * ... * * The (legacy) session identifier bytes have been prepared by * ssl_prepare_client_hello() into the ssl->session_negotiate->id buffer * and are copied here into the output buffer. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, ssl->session_negotiate->id_len + 1); *p++ = (unsigned char) ssl->session_negotiate->id_len; memcpy(p, ssl->session_negotiate->id, ssl->session_negotiate->id_len); p += ssl->session_negotiate->id_len; MBEDTLS_SSL_DEBUG_BUF(3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len); /* DTLS 1.2 ONLY * ... * opaque cookie<0..2^8-1>; * ... */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) uint8_t cookie_len = 0; #else uint16_t cookie_len = 0; #endif /* !MBEDTLS_SSL_PROTO_TLS1_3 */ if (handshake->cookie != NULL) { MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", handshake->cookie, handshake->cookie_len); cookie_len = handshake->cookie_len; } MBEDTLS_SSL_CHK_BUF_PTR(p, end, cookie_len + 1); *p++ = (unsigned char) cookie_len; if (cookie_len > 0) { memcpy(p, handshake->cookie, cookie_len); p += cookie_len; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */ /* Write cipher_suites */ ret = ssl_write_client_hello_cipher_suites(ssl, p, end, &tls12_uses_ec, &output_len); if (ret != 0) { return ret; } p += output_len; /* Write legacy_compression_methods (TLS 1.3) or * compression_methods (TLS 1.2) * * For every TLS 1.3 ClientHello, this vector MUST contain exactly * one byte set to zero, which corresponds to the 'null' compression * method in prior versions of TLS. * * For TLS 1.2 ClientHello, for security reasons we do not support * compression anymore, thus also just the 'null' compression method. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); *p++ = 1; *p++ = MBEDTLS_SSL_COMPRESS_NULL; /* Write extensions */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* Keeping track of the included extensions */ handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; #endif /* First write extensions, then the total length */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p_extensions_len = p; p += 2; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /* Write server name extension */ ret = ssl_write_hostname_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ALPN) ret = ssl_write_alpn_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (propose_tls13) { ret = mbedtls_ssl_tls13_write_client_hello_exts(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif #if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) { int ssl_write_supported_groups_ext_flags = 0; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { ssl_write_supported_groups_ext_flags |= SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG; } #endif #if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) if (propose_tls12 && tls12_uses_ec) { ssl_write_supported_groups_ext_flags |= SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG; } #endif if (ssl_write_supported_groups_ext_flags != 0) { ret = ssl_write_supported_groups_ext(ssl, p, end, ssl_write_supported_groups_ext_flags, &output_len); if (ret != 0) { return ret; } p += output_len; } } #endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC || MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) int write_sig_alg_ext = 0; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) write_sig_alg_ext = write_sig_alg_ext || (propose_tls13 && mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl)); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) write_sig_alg_ext = write_sig_alg_ext || propose_tls12; #endif if (write_sig_alg_ext) { ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (propose_tls12) { ret = mbedtls_ssl_tls12_write_client_hello_exts(ssl, p, end, tls12_uses_ec, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* The "pre_shared_key" extension (RFC 8446 Section 4.2.11) * MUST be the last extension in the ClientHello. */ if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) { ret = mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( ssl, p, end, &output_len, binders_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ /* Write the length of the list of extensions. */ extensions_len = (size_t) (p - p_extensions_len) - 2; if (extensions_len == 0) { p = p_extensions_len; } else { MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, total extension length: %" \ MBEDTLS_PRINTF_SIZET, extensions_len)); MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", p_extensions_len, extensions_len); } *out_len = (size_t) (p - buf); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_generate_random(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *randbytes = ssl->handshake->randbytes; size_t gmt_unix_time_len = 0; /* * Generate the random bytes * * TLS 1.2 case: * struct { * uint32 gmt_unix_time; * opaque random_bytes[28]; * } Random; * * TLS 1.3 case: * opaque Random[32]; */ if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t gmt_unix_time = mbedtls_time(NULL); MBEDTLS_PUT_UINT32_BE(gmt_unix_time, randbytes, 0); gmt_unix_time_len = 4; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, current time: %" MBEDTLS_PRINTF_LONGLONG, (long long) gmt_unix_time)); #endif /* MBEDTLS_HAVE_TIME */ } ret = ssl->conf->f_rng(ssl->conf->p_rng, randbytes + gmt_unix_time_len, MBEDTLS_CLIENT_HELLO_RANDOM_LEN - gmt_unix_time_len); return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl) { int ret; size_t session_id_len; mbedtls_ssl_session *session_negotiate = ssl->session_negotiate; if (session_negotiate == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_HAVE_TIME) /* Check if a tls13 ticket has been configured. */ if (ssl->handshake->resume != 0 && session_negotiate->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && session_negotiate->ticket != NULL) { mbedtls_ms_time_t now = mbedtls_ms_time(); mbedtls_ms_time_t age = now - session_negotiate->ticket_reception_time; if (age < 0 || age > (mbedtls_ms_time_t) session_negotiate->ticket_lifetime * 1000) { /* Without valid ticket, disable session resumption.*/ MBEDTLS_SSL_DEBUG_MSG( 3, ("Ticket expired, disable session resumption")); ssl->handshake->resume = 0; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_HAVE_TIME */ /* Bet on the highest configured version if we are not in a TLS 1.2 * renegotiation or session resumption. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { ssl->handshake->min_tls_version = ssl->tls_version; } else #endif { if (ssl->handshake->resume) { ssl->tls_version = session_negotiate->tls_version; ssl->handshake->min_tls_version = ssl->tls_version; } else { ssl->handshake->min_tls_version = ssl->conf->min_tls_version; } } /* * Generate the random bytes, except when responding to a verify request * where we MUST reuse the previously generated random bytes * (RFC 6347 4.2.1). */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->handshake->cookie == NULL)) #endif { #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (!ssl->handshake->hello_retry_request_flag) #endif { ret = ssl_generate_random(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret); return ret; } } } /* * Prepare session identifier. At that point, the length of the session * identifier in the SSL context `ssl->session_negotiate->id_len` is equal * to zero, except in the case of a TLS 1.2 session renegotiation or * session resumption. */ session_id_len = session_negotiate->id_len; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { if (session_id_len < 16 || session_id_len > 32 || #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || #endif ssl->handshake->resume == 0) { session_id_len = 0; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) /* * RFC 5077 section 3.4: "When presenting a ticket, the client MAY * generate and include a Session ID in the TLS ClientHello." */ int renegotiating = 0; #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { renegotiating = 1; } #endif if (!renegotiating) { if ((session_negotiate->ticket != NULL) && (session_negotiate->ticket_len != 0)) { session_id_len = 32; } } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* * Create a legacy session identifier for the purpose of middlebox * compatibility only if one has not been created already, which is * the case if we are here for the TLS 1.3 second ClientHello. * * Versions of TLS before TLS 1.3 supported a "session resumption" * feature which has been merged with pre-shared keys in TLS 1.3 * version. A client which has a cached session ID set by a pre-TLS 1.3 * server SHOULD set this field to that value. In compatibility mode, * this field MUST be non-empty, so a client not offering a pre-TLS 1.3 * session MUST generate a new 32-byte value. This value need not be * random but SHOULD be unpredictable to avoid implementations fixating * on a specific value (also known as ossification). Otherwise, it MUST * be set as a zero-length vector ( i.e., a zero-valued single byte * length field ). */ session_id_len = 32; } #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ if (session_id_len != session_negotiate->id_len) { session_negotiate->id_len = session_id_len; if (session_id_len > 0) { ret = ssl->conf->f_rng(ssl->conf->p_rng, session_negotiate->id, session_id_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "creating session id failed", ret); return ret; } } } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && ssl->handshake->resume) { int hostname_mismatch = ssl->hostname != NULL || session_negotiate->hostname != NULL; if (ssl->hostname != NULL && session_negotiate->hostname != NULL) { hostname_mismatch = strcmp( ssl->hostname, session_negotiate->hostname) != 0; } if (hostname_mismatch) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Hostname mismatch the session ticket, " "disable session resumption.")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } else { return mbedtls_ssl_session_set_hostname(session_negotiate, ssl->hostname); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SERVER_NAME_INDICATION */ return 0; } /* * Write ClientHello handshake message. * Handler for MBEDTLS_SSL_CLIENT_HELLO */ int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl) { int ret = 0; unsigned char *buf; size_t buf_len, msg_len, binders_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write client hello")); MBEDTLS_SSL_PROC_CHK(ssl_prepare_client_hello(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_write_client_hello_body(ssl, buf, buf + buf_len, &msg_len, &binders_len)); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->out_msglen = msg_len + 4; mbedtls_ssl_send_flight_completed(ssl); /* * The two functions below may try to send data on the network and * can return with the MBEDTLS_ERR_SSL_WANT_READ error code when they * fail to do so and the transmission has to be retried later. In that * case as in fatal error cases, we return immediately. But we must have * set the handshake state to the next state at that point to ensure * that we will not write and send again a ClientHello when we * eventually succeed in sending the pending data. */ mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); return ret; } } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */ { ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, msg_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_add_hs_hdr_to_checksum", ret); return ret; } ret = ssl->handshake->update_checksum(ssl, buf, msg_len - binders_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (binders_len > 0) { MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( ssl, buf + msg_len - binders_len, buf + msg_len)); ret = ssl->handshake->update_checksum(ssl, buf + msg_len - binders_len, binders_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len, msg_len)); /* * Set next state. Note that if TLS 1.3 is proposed, this may be * overwritten by mbedtls_ssl_tls13_finalize_client_hello(). */ mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 && MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version) { ret = mbedtls_ssl_tls13_finalize_client_hello(ssl); } #endif } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_CLIENT_HELLO, ssl->handshake->sent_extensions); #endif cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client hello")); return ret; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 || MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_CLI_C */ webfakes/src/mbedtls/library/psa_crypto_rsa.h0000644000176200001440000003767714740737024021163 0ustar liggesusers/* * PSA RSA layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_RSA_H #define PSA_CRYPTO_RSA_H #include #include /** Load the contents of a key buffer into an internal RSA representation * * \param[in] type The type of key contained in \p data. * \param[in] data The buffer from which to load the representation. * \param[in] data_length The size in bytes of \p data. * \param[out] p_rsa Returns a pointer to an RSA context on success. * The caller is responsible for freeing both the * contents of the context and the context itself * when done. */ psa_status_t mbedtls_psa_rsa_load_representation(psa_key_type_t type, const uint8_t *data, size_t data_length, mbedtls_rsa_context **p_rsa); /** Import an RSA key in binary format. * * \note The signature of this function is that of a PSA driver * import_key entry point. This function behaves as an import_key * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes for the key to import. * \param[in] data The buffer containing the key data in import * format. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] key_buffer The buffer containing the key data in output * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p * key_buffer in bytes. * \param[out] bits The key size in number of bits. * * \retval #PSA_SUCCESS The RSA key was imported successfully. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key data is not correctly formatted. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_rsa_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits); /** Export an RSA key to export representation * * \param[in] type The type of key (public/private) to export * \param[in] rsa The internal RSA representation from which to export * \param[out] data The buffer to export to * \param[in] data_size The length of the buffer to export to * \param[out] data_length The amount of bytes written to \p data */ psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type, mbedtls_rsa_context *rsa, uint8_t *data, size_t data_size, size_t *data_length); /** Export a public RSA key or the public part of an RSA key pair in binary * format. * * \note The signature of this function is that of a PSA driver * export_public_key entry point. This function behaves as an * export_public_key entry point as defined in the PSA driver interface * specification. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data. * * \retval #PSA_SUCCESS The RSA public key was exported successfully. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_rsa_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** * \brief Generate an RSA key. * * \param[in] attributes The attributes for the RSA key to generate. * \param[in] custom_data The public exponent to use. * This can be a null pointer if * \c params_data_length is 0. * \param custom_data_length Length of \p custom_data in bytes. * This can be 0, in which case the * public exponent will be 65537. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in * \p key_buffer. * * \retval #PSA_SUCCESS * The key was successfully generated. * \retval #PSA_ERROR_NOT_SUPPORTED * Key length or type not supported. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. */ psa_status_t mbedtls_psa_rsa_generate_key( const psa_key_attributes_t *attributes, const uint8_t *custom_data, size_t custom_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); /** Sign an already-calculated hash with an RSA private key. * * \note The signature of this function is that of a PSA driver * sign_hash entry point. This function behaves as a sign_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the RSA key to use for the * operation. * \param[in] key_buffer The buffer containing the RSA key context. * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * an RSA key. * \param[in] hash The hash or message to sign. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_RSA_KEY_PAIR, \c key_bits, * \p alg) where \c key_bits is the bit-size of the RSA key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t mbedtls_psa_rsa_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Verify the signature a hash or short message using a public RSA key. * * \note The signature of this function is that of a PSA driver * verify_hash entry point. This function behaves as a verify_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the RSA key to use for the * operation. * \param[in] key_buffer The buffer containing the RSA key context. * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * an RSA key. * \param[in] hash The hash or message whose signature is to be * verified. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_rsa_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Encrypt a short message with a public key. * * \param attributes The attributes for the key to import. * \param key_buffer Buffer where the key data is to be written. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the * encryption algorithm. * If the algorithm does not support a * salt, pass \c NULL. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass \c NULL. * * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param salt_length Size of the \p salt buffer in bytes. * If \p salt is \c NULL, pass 0. * \param[out] output Buffer where the encrypted message is to * be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length); /** * \brief Decrypt a short message with a private key. * * \param attributes The attributes for the key to import. * \param key_buffer Buffer where the key data is to be written. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] input The message to decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the * encryption algorithm. * If the algorithm does not support a * salt, pass \c NULL. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass \c NULL. * * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param salt_length Size of the \p salt buffer in bytes. * If \p salt is \c NULL, pass 0. * \param[out] output Buffer where the decrypted message is to * be written. * \param output_size Size of the \c output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_INVALID_PADDING \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length); #endif /* PSA_CRYPTO_RSA_H */ webfakes/src/mbedtls/library/psa_crypto_se.c0000644000176200001440000002776014740737024020770 0ustar liggesusers/* * PSA crypto support for secure element drivers */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #include #include #include "psa/crypto_se_driver.h" #include "psa_crypto_se.h" #if defined(MBEDTLS_PSA_ITS_FILE_C) #include "psa_crypto_its.h" #else /* Native ITS implementation */ #include "psa/error.h" #include "psa/internal_trusted_storage.h" #endif #include "mbedtls/platform.h" /****************************************************************/ /* Driver lookup */ /****************************************************************/ /* This structure is identical to psa_drv_se_context_t declared in * `crypto_se_driver.h`, except that some parts are writable here * (non-const, or pointer to non-const). */ typedef struct { void *persistent_data; size_t persistent_data_size; uintptr_t transient_data; } psa_drv_se_internal_context_t; struct psa_se_drv_table_entry_s { psa_key_location_t location; const psa_drv_se_t *methods; union { psa_drv_se_internal_context_t internal; psa_drv_se_context_t context; } u; }; static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS]; psa_se_drv_table_entry_t *psa_get_se_driver_entry( psa_key_lifetime_t lifetime) { size_t i; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); /* In the driver table, location=0 means an entry that isn't used. * No driver has a location of 0 because it's a reserved value * (which designates transparent keys). Make sure we never return * a driver entry for location 0. */ if (location == 0) { return NULL; } for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { if (driver_table[i].location == location) { return &driver_table[i]; } } return NULL; } const psa_drv_se_t *psa_get_se_driver_methods( const psa_se_drv_table_entry_t *driver) { return driver->methods; } psa_drv_se_context_t *psa_get_se_driver_context( psa_se_drv_table_entry_t *driver) { return &driver->u.context; } int psa_get_se_driver(psa_key_lifetime_t lifetime, const psa_drv_se_t **p_methods, psa_drv_se_context_t **p_drv_context) { psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime); if (p_methods != NULL) { *p_methods = (driver ? driver->methods : NULL); } if (p_drv_context != NULL) { *p_drv_context = (driver ? &driver->u.context : NULL); } return driver != NULL; } /****************************************************************/ /* Persistent data management */ /****************************************************************/ static psa_status_t psa_get_se_driver_its_file_uid( const psa_se_drv_table_entry_t *driver, psa_storage_uid_t *uid) { if (driver->location > PSA_MAX_SE_LOCATION) { return PSA_ERROR_NOT_SUPPORTED; } /* ITS file sizes are limited to 32 bits. */ if (driver->u.internal.persistent_data_size > UINT32_MAX) { return PSA_ERROR_NOT_SUPPORTED; } /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location; return PSA_SUCCESS; } psa_status_t psa_load_se_persistent_data( const psa_se_drv_table_entry_t *driver) { psa_status_t status; psa_storage_uid_t uid; size_t length; status = psa_get_se_driver_its_file_uid(driver, &uid); if (status != PSA_SUCCESS) { return status; } /* Read the amount of persistent data that the driver requests. * If the data in storage is larger, it is truncated. If the data * in storage is smaller, silently keep what is already at the end * of the output buffer. */ /* psa_get_se_driver_its_file_uid ensures that the size_t * persistent_data_size is in range, but compilers don't know that, * so cast to reassure them. */ return psa_its_get(uid, 0, (uint32_t) driver->u.internal.persistent_data_size, driver->u.internal.persistent_data, &length); } psa_status_t psa_save_se_persistent_data( const psa_se_drv_table_entry_t *driver) { psa_status_t status; psa_storage_uid_t uid; status = psa_get_se_driver_its_file_uid(driver, &uid); if (status != PSA_SUCCESS) { return status; } /* psa_get_se_driver_its_file_uid ensures that the size_t * persistent_data_size is in range, but compilers don't know that, * so cast to reassure them. */ return psa_its_set(uid, (uint32_t) driver->u.internal.persistent_data_size, driver->u.internal.persistent_data, 0); } psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location) { psa_storage_uid_t uid; if (location > PSA_MAX_SE_LOCATION) { return PSA_ERROR_NOT_SUPPORTED; } uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location; return psa_its_remove(uid); } psa_status_t psa_find_se_slot_for_key( const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_se_drv_table_entry_t *driver, psa_key_slot_number_t *slot_number) { psa_status_t status; psa_key_location_t key_location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); /* If the location is wrong, it's a bug in the library. */ if (driver->location != key_location) { return PSA_ERROR_CORRUPTION_DETECTED; } /* If the driver doesn't support key creation in any way, give up now. */ if (driver->methods->key_management == NULL) { return PSA_ERROR_NOT_SUPPORTED; } if (psa_get_key_slot_number(attributes, slot_number) == PSA_SUCCESS) { /* The application wants to use a specific slot. Allow it if * the driver supports it. On a system with isolation, * the crypto service must check that the application is * permitted to request this slot. */ psa_drv_se_validate_slot_number_t p_validate_slot_number = driver->methods->key_management->p_validate_slot_number; if (p_validate_slot_number == NULL) { return PSA_ERROR_NOT_SUPPORTED; } status = p_validate_slot_number(&driver->u.context, driver->u.internal.persistent_data, attributes, method, *slot_number); } else if (method == PSA_KEY_CREATION_REGISTER) { /* The application didn't specify a slot number. This doesn't * make sense when registering a slot. */ return PSA_ERROR_INVALID_ARGUMENT; } else { /* The application didn't tell us which slot to use. Let the driver * choose. This is the normal case. */ psa_drv_se_allocate_key_t p_allocate = driver->methods->key_management->p_allocate; if (p_allocate == NULL) { return PSA_ERROR_NOT_SUPPORTED; } status = p_allocate(&driver->u.context, driver->u.internal.persistent_data, attributes, method, slot_number); } return status; } psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver, psa_key_slot_number_t slot_number) { psa_status_t status; psa_status_t storage_status; /* Normally a missing method would mean that the action is not * supported. But psa_destroy_key() is not supposed to return * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should * be able to destroy it. The only use case for a driver that * does not have a way to destroy keys at all is if the keys are * locked in a read-only state: we can use the keys but not * destroy them. Hence, if the driver doesn't support destroying * keys, it's really a lack of permission. */ if (driver->methods->key_management == NULL || driver->methods->key_management->p_destroy == NULL) { return PSA_ERROR_NOT_PERMITTED; } status = driver->methods->key_management->p_destroy( &driver->u.context, driver->u.internal.persistent_data, slot_number); storage_status = psa_save_se_persistent_data(driver); return status == PSA_SUCCESS ? storage_status : status; } psa_status_t psa_init_all_se_drivers(void) { size_t i; for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { psa_se_drv_table_entry_t *driver = &driver_table[i]; if (driver->location == 0) { continue; /* skipping unused entry */ } const psa_drv_se_t *methods = psa_get_se_driver_methods(driver); if (methods->p_init != NULL) { psa_status_t status = methods->p_init( &driver->u.context, driver->u.internal.persistent_data, driver->location); if (status != PSA_SUCCESS) { return status; } status = psa_save_se_persistent_data(driver); if (status != PSA_SUCCESS) { return status; } } } return PSA_SUCCESS; } /****************************************************************/ /* Driver registration */ /****************************************************************/ psa_status_t psa_register_se_driver( psa_key_location_t location, const psa_drv_se_t *methods) { size_t i; psa_status_t status; if (methods->hal_version != PSA_DRV_SE_HAL_VERSION) { return PSA_ERROR_NOT_SUPPORTED; } /* Driver table entries are 0-initialized. 0 is not a valid driver * location because it means a transparent key. */ MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0, "Secure element support requires 0 to mean a local key"); if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) { return PSA_ERROR_INVALID_ARGUMENT; } if (location > PSA_MAX_SE_LOCATION) { return PSA_ERROR_NOT_SUPPORTED; } for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { if (driver_table[i].location == 0) { break; } /* Check that location isn't already in use up to the first free * entry. Since entries are created in order and never deleted, * there can't be a used entry after the first free entry. */ if (driver_table[i].location == location) { return PSA_ERROR_ALREADY_EXISTS; } } if (i == PSA_MAX_SE_DRIVERS) { return PSA_ERROR_INSUFFICIENT_MEMORY; } driver_table[i].location = location; driver_table[i].methods = methods; driver_table[i].u.internal.persistent_data_size = methods->persistent_data_size; if (methods->persistent_data_size != 0) { driver_table[i].u.internal.persistent_data = mbedtls_calloc(1, methods->persistent_data_size); if (driver_table[i].u.internal.persistent_data == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto error; } /* Load the driver's persistent data. On first use, the persistent * data does not exist in storage, and is initialized to * all-bits-zero by the calloc call just above. */ status = psa_load_se_persistent_data(&driver_table[i]); if (status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST) { goto error; } } return PSA_SUCCESS; error: memset(&driver_table[i], 0, sizeof(driver_table[i])); return status; } void psa_unregister_all_se_drivers(void) { size_t i; for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { if (driver_table[i].u.internal.persistent_data != NULL) { mbedtls_free(driver_table[i].u.internal.persistent_data); } } memset(driver_table, 0, sizeof(driver_table)); } /****************************************************************/ /* The end */ /****************************************************************/ #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ webfakes/src/mbedtls/library/bignum_core.c0000644000176200001440000010223714740737024020400 0ustar liggesusers/* * Core bignum functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "constant_time_internal.h" #include "mbedtls/platform.h" #include "bignum_core.h" #include "bn_mul.h" #include "constant_time_internal.h" size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a) { #if defined(__has_builtin) #if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_clz) #define core_clz __builtin_clz #elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_clzl) #define core_clz __builtin_clzl #elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_clzll) #define core_clz __builtin_clzll #endif #endif #if defined(core_clz) return (size_t) core_clz(a); #else size_t j; mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); for (j = 0; j < biL; j++) { if (a & mask) { break; } mask >>= 1; } return j; #endif } size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs) { int i; size_t j; for (i = ((int) A_limbs) - 1; i >= 0; i--) { if (A[i] != 0) { j = biL - mbedtls_mpi_core_clz(A[i]); return (i * biL) + j; } } return 0; } static mbedtls_mpi_uint mpi_bigendian_to_host(mbedtls_mpi_uint a) { if (MBEDTLS_IS_BIG_ENDIAN) { /* Nothing to do on bigendian systems. */ return a; } else { #if defined(MBEDTLS_HAVE_INT32) return (mbedtls_mpi_uint) MBEDTLS_BSWAP32(a); #elif defined(MBEDTLS_HAVE_INT64) return (mbedtls_mpi_uint) MBEDTLS_BSWAP64(a); #endif } } void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A, size_t A_limbs) { mbedtls_mpi_uint *cur_limb_left; mbedtls_mpi_uint *cur_limb_right; if (A_limbs == 0) { return; } /* * Traverse limbs and * - adapt byte-order in each limb * - swap the limbs themselves. * For that, simultaneously traverse the limbs from left to right * and from right to left, as long as the left index is not bigger * than the right index (it's not a problem if limbs is odd and the * indices coincide in the last iteration). */ for (cur_limb_left = A, cur_limb_right = A + (A_limbs - 1); cur_limb_left <= cur_limb_right; cur_limb_left++, cur_limb_right--) { mbedtls_mpi_uint tmp; /* Note that if cur_limb_left == cur_limb_right, * this code effectively swaps the bytes only once. */ tmp = mpi_bigendian_to_host(*cur_limb_left); *cur_limb_left = mpi_bigendian_to_host(*cur_limb_right); *cur_limb_right = tmp; } } /* Whether min <= A, in constant time. * A_limbs must be at least 1. */ mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min, const mbedtls_mpi_uint *A, size_t A_limbs) { /* min <= least significant limb? */ mbedtls_ct_condition_t min_le_lsl = mbedtls_ct_uint_ge(A[0], min); /* limbs other than the least significant one are all zero? */ mbedtls_ct_condition_t msll_mask = MBEDTLS_CT_FALSE; for (size_t i = 1; i < A_limbs; i++) { msll_mask = mbedtls_ct_bool_or(msll_mask, mbedtls_ct_bool(A[i])); } /* min <= A iff the lowest limb of A is >= min or the other limbs * are not all zero. */ return mbedtls_ct_bool_or(msll_mask, min_le_lsl); } mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs) { mbedtls_ct_condition_t ret = MBEDTLS_CT_FALSE, cond = MBEDTLS_CT_FALSE, done = MBEDTLS_CT_FALSE; for (size_t i = limbs; i > 0; i--) { /* * If B[i - 1] < A[i - 1] then A < B is false and the result must * remain 0. * * Again even if we can make a decision, we just mark the result and * the fact that we are done and continue looping. */ cond = mbedtls_ct_uint_lt(B[i - 1], A[i - 1]); done = mbedtls_ct_bool_or(done, cond); /* * If A[i - 1] < B[i - 1] then A < B is true. * * Again even if we can make a decision, we just mark the result and * the fact that we are done and continue looping. */ cond = mbedtls_ct_uint_lt(A[i - 1], B[i - 1]); ret = mbedtls_ct_bool_or(ret, mbedtls_ct_bool_and(cond, mbedtls_ct_bool_not(done))); done = mbedtls_ct_bool_or(done, cond); } /* * If all the limbs were equal, then the numbers are equal, A < B is false * and leaving the result 0 is correct. */ return ret; } void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t limbs, mbedtls_ct_condition_t assign) { if (X == A) { return; } /* This function is very performance-sensitive for RSA. For this reason * we have the loop below, instead of calling mbedtls_ct_memcpy_if * (this is more optimal since here we don't have to handle the case where * we copy awkwardly sized data). */ for (size_t i = 0; i < limbs; i++) { X[i] = mbedtls_ct_mpi_uint_if(assign, A[i], X[i]); } } void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X, mbedtls_mpi_uint *Y, size_t limbs, mbedtls_ct_condition_t swap) { if (X == Y) { return; } for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint tmp = X[i]; X[i] = mbedtls_ct_mpi_uint_if(swap, Y[i], X[i]); Y[i] = mbedtls_ct_mpi_uint_if(swap, tmp, Y[i]); } } int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X, size_t X_limbs, const unsigned char *input, size_t input_length) { const size_t limbs = CHARS_TO_LIMBS(input_length); if (X_limbs < limbs) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } if (X != NULL) { memset(X, 0, X_limbs * ciL); for (size_t i = 0; i < input_length; i++) { size_t offset = ((i % ciL) << 3); X[i / ciL] |= ((mbedtls_mpi_uint) input[i]) << offset; } } return 0; } int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X, size_t X_limbs, const unsigned char *input, size_t input_length) { const size_t limbs = CHARS_TO_LIMBS(input_length); if (X_limbs < limbs) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } /* If X_limbs is 0, input_length must also be 0 (from previous test). * Nothing to do. */ if (X_limbs == 0) { return 0; } memset(X, 0, X_limbs * ciL); /* memcpy() with (NULL, 0) is undefined behaviour */ if (input_length != 0) { size_t overhead = (X_limbs * ciL) - input_length; unsigned char *Xp = (unsigned char *) X; memcpy(Xp + overhead, input, input_length); } mbedtls_mpi_core_bigendian_to_host(X, X_limbs); return 0; } int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A, size_t A_limbs, unsigned char *output, size_t output_length) { size_t stored_bytes = A_limbs * ciL; size_t bytes_to_copy; if (stored_bytes < output_length) { bytes_to_copy = stored_bytes; } else { bytes_to_copy = output_length; /* The output buffer is smaller than the allocated size of A. * However A may fit if its leading bytes are zero. */ for (size_t i = bytes_to_copy; i < stored_bytes; i++) { if (GET_BYTE(A, i) != 0) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } } } for (size_t i = 0; i < bytes_to_copy; i++) { output[i] = GET_BYTE(A, i); } if (stored_bytes < output_length) { /* Write trailing 0 bytes */ memset(output + stored_bytes, 0, output_length - stored_bytes); } return 0; } int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *X, size_t X_limbs, unsigned char *output, size_t output_length) { size_t stored_bytes; size_t bytes_to_copy; unsigned char *p; stored_bytes = X_limbs * ciL; if (stored_bytes < output_length) { /* There is enough space in the output buffer. Write initial * null bytes and record the position at which to start * writing the significant bytes. In this case, the execution * trace of this function does not depend on the value of the * number. */ bytes_to_copy = stored_bytes; p = output + output_length - stored_bytes; memset(output, 0, output_length - stored_bytes); } else { /* The output buffer is smaller than the allocated size of X. * However X may fit if its leading bytes are zero. */ bytes_to_copy = output_length; p = output; for (size_t i = bytes_to_copy; i < stored_bytes; i++) { if (GET_BYTE(X, i) != 0) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } } } for (size_t i = 0; i < bytes_to_copy; i++) { p[bytes_to_copy - i - 1] = GET_BYTE(X, i); } return 0; } void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, size_t count) { size_t i, v0, v1; mbedtls_mpi_uint r0 = 0, r1; v0 = count / biL; v1 = count & (biL - 1); if (v0 > limbs || (v0 == limbs && v1 > 0)) { memset(X, 0, limbs * ciL); return; } /* * shift by count / limb_size */ if (v0 > 0) { for (i = 0; i < limbs - v0; i++) { X[i] = X[i + v0]; } for (; i < limbs; i++) { X[i] = 0; } } /* * shift by count % limb_size */ if (v1 > 0) { for (i = limbs; i > 0; i--) { r1 = X[i - 1] << (biL - v1); X[i - 1] >>= v1; X[i - 1] |= r0; r0 = r1; } } } void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs, size_t count) { size_t i, v0, v1; mbedtls_mpi_uint r0 = 0, r1; v0 = count / (biL); v1 = count & (biL - 1); /* * shift by count / limb_size */ if (v0 > 0) { for (i = limbs; i > v0; i--) { X[i - 1] = X[i - v0 - 1]; } for (; i > 0; i--) { X[i - 1] = 0; } } /* * shift by count % limb_size */ if (v1 > 0) { for (i = v0; i < limbs; i++) { r1 = X[i] >> (biL - v1); X[i] <<= v1; X[i] |= r0; r0 = r1; } } } mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs) { mbedtls_mpi_uint c = 0; for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint t = c + A[i]; c = (t < A[i]); t += B[i]; c += (t < B[i]); X[i] = t; } return c; } mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t limbs, unsigned cond) { mbedtls_mpi_uint c = 0; mbedtls_ct_condition_t do_add = mbedtls_ct_bool(cond); for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint add = mbedtls_ct_mpi_uint_if_else_0(do_add, A[i]); mbedtls_mpi_uint t = c + X[i]; c = (t < X[i]); t += add; c += (t < add); X[i] = t; } return c; } mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs) { mbedtls_mpi_uint c = 0; for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint z = (A[i] < c); mbedtls_mpi_uint t = A[i] - c; c = (t < B[i]) + z; X[i] = t - B[i]; } return c; } mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *d, size_t d_len, const mbedtls_mpi_uint *s, size_t s_len, mbedtls_mpi_uint b) { mbedtls_mpi_uint c = 0; /* carry */ /* * It is a documented precondition of this function that d_len >= s_len. * If that's not the case, we swap these round: this turns what would be * a buffer overflow into an incorrect result. */ if (d_len < s_len) { s_len = d_len; } size_t excess_len = d_len - s_len; size_t steps_x8 = s_len / 8; size_t steps_x1 = s_len & 7; while (steps_x8--) { MULADDC_X8_INIT MULADDC_X8_CORE MULADDC_X8_STOP } while (steps_x1--) { MULADDC_X1_INIT MULADDC_X1_CORE MULADDC_X1_STOP } while (excess_len--) { *d += c; c = (*d < c); d++; } return c; } void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t A_limbs, const mbedtls_mpi_uint *B, size_t B_limbs) { memset(X, 0, (A_limbs + B_limbs) * ciL); for (size_t i = 0; i < B_limbs; i++) { (void) mbedtls_mpi_core_mla(X + i, A_limbs + 1, A, A_limbs, B[i]); } } /* * Fast Montgomery initialization (thanks to Tom St Denis). */ mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N) { mbedtls_mpi_uint x = N[0]; x += ((N[0] + 2) & 4) << 1; for (unsigned int i = biL; i >= 8; i /= 2) { x *= (2 - (N[0] * x)); } return ~x + 1; } void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t B_limbs, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, mbedtls_mpi_uint *T) { memset(T, 0, (2 * AN_limbs + 1) * ciL); for (size_t i = 0; i < AN_limbs; i++) { /* T = (T + u0*B + u1*N) / 2^biL */ mbedtls_mpi_uint u0 = A[i]; mbedtls_mpi_uint u1 = (T[0] + u0 * B[0]) * mm; (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, B, B_limbs, u0); (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, N, AN_limbs, u1); T++; } /* * The result we want is (T >= N) ? T - N : T. * * For better constant-time properties in this function, we always do the * subtraction, with the result in X. * * We also look to see if there was any carry in the final additions in the * loop above. */ mbedtls_mpi_uint carry = T[AN_limbs]; mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, T, N, AN_limbs); /* * Using R as the Montgomery radix (auxiliary modulus) i.e. 2^(biL*AN_limbs): * * T can be in one of 3 ranges: * * 1) T < N : (carry, borrow) = (0, 1): we want T * 2) N <= T < R : (carry, borrow) = (0, 0): we want X * 3) T >= R : (carry, borrow) = (1, 1): we want X * * and (carry, borrow) = (1, 0) can't happen. * * So the correct return value is already in X if (carry ^ borrow) = 0, * but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1. */ mbedtls_ct_memcpy_if(mbedtls_ct_bool(carry ^ borrow), (unsigned char *) X, (unsigned char *) T, NULL, AN_limbs * sizeof(mbedtls_mpi_uint)); } int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X, const mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, N->n * 2 * biL)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(X, N->n)); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest, const mbedtls_mpi_uint *table, size_t limbs, size_t count, size_t index) { for (size_t i = 0; i < count; i++, table += limbs) { mbedtls_ct_condition_t assign = mbedtls_ct_uint_eq(i, index); mbedtls_mpi_core_cond_assign(dest, table, limbs, assign); } } /* Fill X with n_bytes random bytes. * X must already have room for those bytes. * The ordering of the bytes returned from the RNG is suitable for * deterministic ECDSA (see RFC 6979 §3.3 and the specification of * mbedtls_mpi_core_random()). */ int mbedtls_mpi_core_fill_random( mbedtls_mpi_uint *X, size_t X_limbs, size_t n_bytes, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t limbs = CHARS_TO_LIMBS(n_bytes); const size_t overhead = (limbs * ciL) - n_bytes; if (X_limbs < limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } memset(X, 0, overhead); memset((unsigned char *) X + limbs * ciL, 0, (X_limbs - limbs) * ciL); MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X + overhead, n_bytes)); mbedtls_mpi_core_bigendian_to_host(X, limbs); cleanup: return ret; } int mbedtls_mpi_core_random(mbedtls_mpi_uint *X, mbedtls_mpi_uint min, const mbedtls_mpi_uint *N, size_t limbs, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_ct_condition_t ge_lower = MBEDTLS_CT_TRUE, lt_upper = MBEDTLS_CT_FALSE; size_t n_bits = mbedtls_mpi_core_bitlen(N, limbs); size_t n_bytes = (n_bits + 7) / 8; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * When min == 0, each try has at worst a probability 1/2 of failing * (the msb has a probability 1/2 of being 0, and then the result will * be < N), so after 30 tries failure probability is a most 2**(-30). * * When N is just below a power of 2, as is the case when generating * a random scalar on most elliptic curves, 1 try is enough with * overwhelming probability. When N is just above a power of 2, * as when generating a random scalar on secp224k1, each try has * a probability of failing that is almost 1/2. * * The probabilities are almost the same if min is nonzero but negligible * compared to N. This is always the case when N is crypto-sized, but * it's convenient to support small N for testing purposes. When N * is small, use a higher repeat count, otherwise the probability of * failure is macroscopic. */ int count = (n_bytes > 4 ? 30 : 250); /* * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA) * when f_rng is a suitably parametrized instance of HMAC_DRBG: * - use the same byte ordering; * - keep the leftmost n_bits bits of the generated octet string; * - try until result is in the desired range. * This also avoids any bias, which is especially important for ECDSA. */ do { MBEDTLS_MPI_CHK(mbedtls_mpi_core_fill_random(X, limbs, n_bytes, f_rng, p_rng)); mbedtls_mpi_core_shift_r(X, limbs, 8 * n_bytes - n_bits); if (--count == 0) { ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; goto cleanup; } ge_lower = mbedtls_mpi_core_uint_le_mpi(min, X, limbs); lt_upper = mbedtls_mpi_core_lt_ct(X, N, limbs); } while (mbedtls_ct_bool_and(ge_lower, lt_upper) == MBEDTLS_CT_FALSE); cleanup: return ret; } static size_t exp_mod_get_window_size(size_t Ebits) { #if MBEDTLS_MPI_WINDOW_SIZE >= 6 return (Ebits > 671) ? 6 : (Ebits > 239) ? 5 : (Ebits > 79) ? 4 : 1; #elif MBEDTLS_MPI_WINDOW_SIZE == 5 return (Ebits > 239) ? 5 : (Ebits > 79) ? 4 : 1; #elif MBEDTLS_MPI_WINDOW_SIZE > 1 return (Ebits > 79) ? MBEDTLS_MPI_WINDOW_SIZE : 1; #else (void) Ebits; return 1; #endif } size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs) { const size_t wsize = exp_mod_get_window_size(E_limbs * biL); const size_t welem = ((size_t) 1) << wsize; /* How big does each part of the working memory pool need to be? */ const size_t table_limbs = welem * AN_limbs; const size_t select_limbs = AN_limbs; const size_t temp_limbs = 2 * AN_limbs + 1; return table_limbs + select_limbs + temp_limbs; } static void exp_mod_precompute_window(const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, const mbedtls_mpi_uint *RR, size_t welem, mbedtls_mpi_uint *Wtable, mbedtls_mpi_uint *temp) { /* W[0] = 1 (in Montgomery presentation) */ memset(Wtable, 0, AN_limbs * ciL); Wtable[0] = 1; mbedtls_mpi_core_montmul(Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp); /* W[1] = A (already in Montgomery presentation) */ mbedtls_mpi_uint *W1 = Wtable + AN_limbs; memcpy(W1, A, AN_limbs * ciL); /* W[i+1] = W[i] * W[1], i >= 2 */ mbedtls_mpi_uint *Wprev = W1; for (size_t i = 2; i < welem; i++) { mbedtls_mpi_uint *Wcur = Wprev + AN_limbs; mbedtls_mpi_core_montmul(Wcur, Wprev, W1, AN_limbs, N, AN_limbs, mm, temp); Wprev = Wcur; } } #if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C) // Set to a default that is neither MBEDTLS_MPI_IS_PUBLIC nor MBEDTLS_MPI_IS_SECRET int mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC + MBEDTLS_MPI_IS_SECRET + 1; #endif /* * This function calculates the indices of the exponent where the exponentiation algorithm should * start processing. * * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value, * this function is not constant time with respect to the exponent (parameter E). */ static inline void exp_mod_calc_first_bit_optionally_safe(const mbedtls_mpi_uint *E, size_t E_limbs, int E_public, size_t *E_limb_index, size_t *E_bit_index) { if (E_public == MBEDTLS_MPI_IS_PUBLIC) { /* * Skip leading zero bits. */ size_t E_bits = mbedtls_mpi_core_bitlen(E, E_limbs); if (E_bits == 0) { /* * If E is 0 mbedtls_mpi_core_bitlen() returns 0. Even if that is the case, we will want * to represent it as a single 0 bit and as such the bitlength will be 1. */ E_bits = 1; } *E_limb_index = E_bits / biL; *E_bit_index = E_bits % biL; #if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C) mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC; #endif } else { /* * Here we need to be constant time with respect to E and can't do anything better than * start at the first allocated bit. */ *E_limb_index = E_limbs; *E_bit_index = 0; #if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C) // Only mark the codepath safe if there wasn't an unsafe codepath before if (mbedtls_mpi_optionally_safe_codepath != MBEDTLS_MPI_IS_PUBLIC) { mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_SECRET; } #endif } } /* * Warning! If the parameter window_public has MBEDTLS_MPI_IS_PUBLIC as its value, this function is * not constant time with respect to the window parameter and consequently the exponent of the * exponentiation (parameter E of mbedtls_mpi_core_exp_mod_optionally_safe). */ static inline void exp_mod_table_lookup_optionally_safe(mbedtls_mpi_uint *Wselect, mbedtls_mpi_uint *Wtable, size_t AN_limbs, size_t welem, mbedtls_mpi_uint window, int window_public) { if (window_public == MBEDTLS_MPI_IS_PUBLIC) { memcpy(Wselect, Wtable + window * AN_limbs, AN_limbs * ciL); #if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C) mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC; #endif } else { /* Select Wtable[window] without leaking window through * memory access patterns. */ mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable, AN_limbs, welem, window); #if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C) // Only mark the codepath safe if there wasn't an unsafe codepath before if (mbedtls_mpi_optionally_safe_codepath != MBEDTLS_MPI_IS_PUBLIC) { mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_SECRET; } #endif } } /* Exponentiation: X := A^E mod N. * * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value, * this function is not constant time with respect to the exponent (parameter E). * * A must already be in Montgomery form. * * As in other bignum functions, assume that AN_limbs and E_limbs are nonzero. * * RR must contain 2^{2*biL} mod N. * * The algorithm is a variant of Left-to-right k-ary exponentiation: HAC 14.82 * (The difference is that the body in our loop processes a single bit instead * of a full window.) */ static void mbedtls_mpi_core_exp_mod_optionally_safe(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *E, size_t E_limbs, int E_public, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T) { /* We'll process the bits of E from most significant * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant * (limb_index=0, E_bit_index=0). */ size_t E_limb_index; size_t E_bit_index; exp_mod_calc_first_bit_optionally_safe(E, E_limbs, E_public, &E_limb_index, &E_bit_index); const size_t wsize = exp_mod_get_window_size(E_limb_index * biL); const size_t welem = ((size_t) 1) << wsize; /* This is how we will use the temporary storage T, which must have space * for table_limbs, select_limbs and (2 * AN_limbs + 1) for montmul. */ const size_t table_limbs = welem * AN_limbs; const size_t select_limbs = AN_limbs; /* Pointers to specific parts of the temporary working memory pool */ mbedtls_mpi_uint *const Wtable = T; mbedtls_mpi_uint *const Wselect = Wtable + table_limbs; mbedtls_mpi_uint *const temp = Wselect + select_limbs; /* * Window precomputation */ const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N); /* Set Wtable[i] = A^i (in Montgomery representation) */ exp_mod_precompute_window(A, N, AN_limbs, mm, RR, welem, Wtable, temp); /* * Fixed window exponentiation */ /* X = 1 (in Montgomery presentation) initially */ memcpy(X, Wtable, AN_limbs * ciL); /* At any given time, window contains window_bits bits from E. * window_bits can go up to wsize. */ size_t window_bits = 0; mbedtls_mpi_uint window = 0; do { /* Square */ mbedtls_mpi_core_montmul(X, X, X, AN_limbs, N, AN_limbs, mm, temp); /* Move to the next bit of the exponent */ if (E_bit_index == 0) { --E_limb_index; E_bit_index = biL - 1; } else { --E_bit_index; } /* Insert next exponent bit into window */ ++window_bits; window <<= 1; window |= (E[E_limb_index] >> E_bit_index) & 1; /* Clear window if it's full. Also clear the window at the end, * when we've finished processing the exponent. */ if (window_bits == wsize || (E_bit_index == 0 && E_limb_index == 0)) { exp_mod_table_lookup_optionally_safe(Wselect, Wtable, AN_limbs, welem, window, E_public); /* Multiply X by the selected element. */ mbedtls_mpi_core_montmul(X, X, Wselect, AN_limbs, N, AN_limbs, mm, temp); window = 0; window_bits = 0; } } while (!(E_bit_index == 0 && E_limb_index == 0)); } void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *E, size_t E_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T) { mbedtls_mpi_core_exp_mod_optionally_safe(X, A, N, AN_limbs, E, E_limbs, MBEDTLS_MPI_IS_SECRET, RR, T); } void mbedtls_mpi_core_exp_mod_unsafe(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *E, size_t E_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T) { mbedtls_mpi_core_exp_mod_optionally_safe(X, A, N, AN_limbs, E, E_limbs, MBEDTLS_MPI_IS_PUBLIC, RR, T); } mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, mbedtls_mpi_uint c, /* doubles as carry */ size_t limbs) { for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint s = A[i]; mbedtls_mpi_uint t = s - c; c = (t > s); X[i] = t; } return c; } mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A, size_t limbs) { volatile const mbedtls_mpi_uint *force_read_A = A; mbedtls_mpi_uint bits = 0; for (size_t i = 0; i < limbs; i++) { bits |= force_read_A[i]; } return mbedtls_ct_bool(bits); } void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, const mbedtls_mpi_uint *rr, mbedtls_mpi_uint *T) { mbedtls_mpi_core_montmul(X, A, rr, AN_limbs, N, AN_limbs, mm, T); } void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, mbedtls_mpi_uint *T) { const mbedtls_mpi_uint Rinv = 1; /* 1/R in Mont. rep => 1 */ mbedtls_mpi_core_montmul(X, A, &Rinv, 1, N, AN_limbs, mm, T); } #endif /* MBEDTLS_BIGNUM_C */ webfakes/src/mbedtls/library/x509write_crt.c0000644000176200001440000006047214740737024020543 0ustar liggesusers/* * X.509 certificate writing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * - certificates: RFC 5280, updated by RFC 6818 * - CSRs: PKCS#10 v1.7 aka RFC 2986 * - attributes: PKCS#9 v2.0 aka RFC 2985 */ #include "common.h" #if defined(MBEDTLS_X509_CRT_WRITE_C) #include "mbedtls/x509_crt.h" #include "x509_internal.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/md.h" #include #include #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif /* MBEDTLS_PEM_WRITE_C */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "psa_util_internal.h" #include "mbedtls/psa_util.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx) { memset(ctx, 0, sizeof(mbedtls_x509write_cert)); ctx->version = MBEDTLS_X509_CRT_VERSION_3; } void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx) { if (ctx == NULL) { return; } mbedtls_asn1_free_named_data_list(&ctx->subject); mbedtls_asn1_free_named_data_list(&ctx->issuer); mbedtls_asn1_free_named_data_list(&ctx->extensions); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_cert)); } void mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx, int version) { ctx->version = version; } void mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg) { ctx->md_alg = md_alg; } void mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key) { ctx->subject_key = key; } void mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key) { ctx->issuer_key = key; } int mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx, const char *subject_name) { return mbedtls_x509_string_to_names(&ctx->subject, subject_name); } int mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx, const char *issuer_name) { return mbedtls_x509_string_to_names(&ctx->issuer, issuer_name); } #if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial) { int ret; size_t tmp_len; /* Ensure that the MPI value fits into the buffer */ tmp_len = mbedtls_mpi_size(serial); if (tmp_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } ctx->serial_len = tmp_len; ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len); if (ret < 0) { return ret; } return 0; } #endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx, unsigned char *serial, size_t serial_len) { if (serial_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } ctx->serial_len = serial_len; memcpy(ctx->serial, serial, serial_len); return 0; } int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, const char *not_before, const char *not_after) { if (strlen(not_before) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || strlen(not_after) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } strncpy(ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN); strncpy(ctx->not_after, not_after, MBEDTLS_X509_RFC5280_UTC_TIME_LEN); ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; return 0; } int mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx, const mbedtls_x509_san_list *san_list) { return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); } int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len) { return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, critical, val, val_len); } int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx, int is_ca, int max_pathlen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[9]; unsigned char *c = buf + sizeof(buf); size_t len = 0; memset(buf, 0, sizeof(buf)); if (is_ca && max_pathlen > 127) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } if (is_ca) { if (max_pathlen >= 0) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, max_pathlen)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(&c, buf, 1)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, MBEDTLS_OID_SIZE(MBEDTLS_OID_BASIC_CONSTRAINTS), is_ca, buf + sizeof(buf) - len, len); } #if defined(MBEDTLS_MD_CAN_SHA1) static int mbedtls_x509write_crt_set_key_identifier(mbedtls_x509write_cert *ctx, int is_ca, unsigned char tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ unsigned char *c = buf + sizeof(buf); size_t len = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t hash_length; #endif /* MBEDTLS_USE_PSA_CRYPTO */ memset(buf, 0, sizeof(buf)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, is_ca ? ctx->issuer_key : ctx->subject_key)); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_compute(PSA_ALG_SHA_1, buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20, 20, &hash_length); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } #else ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20); if (ret != 0) { return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ c = buf + sizeof(buf) - 20; len = 20; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, tag)); if (is_ca) { // writes AuthorityKeyIdentifier sequence MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); } if (is_ca) { return mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER), 0, buf + sizeof(buf) - len, len); } else { return mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER), 0, buf + sizeof(buf) - len, len); } } int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx) { return mbedtls_x509write_crt_set_key_identifier(ctx, 0, MBEDTLS_ASN1_OCTET_STRING); } int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx) { return mbedtls_x509write_crt_set_key_identifier(ctx, 1, (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0)); } #endif /* MBEDTLS_MD_CAN_SHA1 */ int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx, unsigned int key_usage) { unsigned char buf[5] = { 0 }, ku[2] = { 0 }; unsigned char *c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT | MBEDTLS_X509_KU_DATA_ENCIPHERMENT | MBEDTLS_X509_KU_KEY_AGREEMENT | MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_CRL_SIGN | MBEDTLS_X509_KU_ENCIPHER_ONLY | MBEDTLS_X509_KU_DECIPHER_ONLY; /* Check that nothing other than the allowed flags is set */ if ((key_usage & ~allowed_bits) != 0) { return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } c = buf + 5; MBEDTLS_PUT_UINT16_LE(key_usage, ku, 0); ret = mbedtls_asn1_write_named_bitstring(&c, buf, ku, 9); if (ret < 0) { return ret; } else if (ret < 3 || ret > 5) { return MBEDTLS_ERR_X509_INVALID_FORMAT; } ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), 1, c, (size_t) ret); if (ret != 0) { return ret; } return 0; } int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, const mbedtls_asn1_sequence *exts) { unsigned char buf[256]; unsigned char *c = buf + sizeof(buf); int ret; size_t len = 0; const mbedtls_asn1_sequence *last_ext = NULL; const mbedtls_asn1_sequence *ext; memset(buf, 0, sizeof(buf)); /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */ if (exts == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } /* Iterate over exts backwards, so we write them out in the requested order */ while (last_ext != exts) { for (ext = exts; ext->next != last_ext; ext = ext->next) { } if (ext->buf.tag != MBEDTLS_ASN1_OID) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ext->buf.p, ext->buf.len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ext->buf.len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OID)); last_ext = ext; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_EXTENDED_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE), 1, c, len); } int mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx, unsigned char ns_cert_type) { unsigned char buf[4] = { 0 }; unsigned char *c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; c = buf + 4; ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); if (ret < 3 || ret > 4) { return ret; } ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), 0, c, (size_t) ret); if (ret != 0) { return ret; } return 0; } static int x509_write_time(unsigned char **p, unsigned char *start, const char *t, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; /* * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) */ if (t[0] < '2' || (t[0] == '2' && t[1] == '0' && t[2] < '5')) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, (const unsigned char *) t + 2, size - 2)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_UTC_TIME)); } else { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, (const unsigned char *) t, size)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_GENERALIZED_TIME)); } return (int) len; } int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; size_t hash_length = 0; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_algorithm_t psa_algorithm; #endif /* MBEDTLS_USE_PSA_CRYPTO */ size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; mbedtls_pk_type_t pk_alg; int write_sig_null_par; /* * Prepare data to be signed at the end of the target buffer */ c = buf + size; /* Signature algorithm needed in TBS, and later for actual signature */ /* There's no direct way of extracting a signature algorithm * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_RSA)) { pk_alg = MBEDTLS_PK_RSA; } else if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_ECDSA)) { pk_alg = MBEDTLS_PK_ECDSA; } else { return MBEDTLS_ERR_X509_INVALID_ALG; } if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len)) != 0) { return ret; } /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ /* Only for v3 */ if (ctx->version == MBEDTLS_X509_CRT_VERSION_3) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf, ctx->extensions)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3)); } /* * SubjectPublicKeyInfo */ MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->subject_key, buf, (size_t) (c - buf))); c -= pub_len; len += pub_len; /* * Subject ::= Name */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, ctx->subject)); /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } */ sub_len = 0; MBEDTLS_ASN1_CHK_ADD(sub_len, x509_write_time(&c, buf, ctx->not_after, MBEDTLS_X509_RFC5280_UTC_TIME_LEN)); MBEDTLS_ASN1_CHK_ADD(sub_len, x509_write_time(&c, buf, ctx->not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN)); len += sub_len; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* * Issuer ::= Name */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, ctx->issuer)); /* * Signature ::= AlgorithmIdentifier */ if (pk_alg == MBEDTLS_PK_ECDSA) { /* * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and * https://www.rfc-editor.org/rfc/rfc5758#section-3. */ write_sig_null_par = 0; } else { write_sig_null_par = 1; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, sig_oid, strlen(sig_oid), 0, write_sig_null_par)); /* * Serial ::= INTEGER * * Written data is: * - "ctx->serial_len" bytes for the raw serial buffer * - if MSb of "serial" is 1, then prepend an extra 0x00 byte * - 1 byte for the length * - 1 byte for the TAG */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ctx->serial, ctx->serial_len)); if (*c & 0x80) { if (c - buf < 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } *(--c) = 0x0; len++; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ctx->serial_len + 1)); } else { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ctx->serial_len)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_INTEGER)); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ /* Can be omitted for v1 */ if (ctx->version != MBEDTLS_X509_CRT_VERSION_1) { sub_len = 0; MBEDTLS_ASN1_CHK_ADD(sub_len, mbedtls_asn1_write_int(&c, buf, ctx->version)); len += sub_len; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* * Make signature */ /* Compute hash of CRT. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm = mbedtls_md_psa_alg_from_type(ctx->md_alg); status = psa_hash_compute(psa_algorithm, c, len, hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } #else if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash)) != 0) { return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if ((ret = mbedtls_pk_sign(ctx->issuer_key, ctx->md_alg, hash, hash_length, sig, sizeof(sig), &sig_len, f_rng, p_rng)) != 0) { return ret; } /* Move CRT to the front of the buffer to have space * for the signature. */ memmove(buf, c, len); c = buf + len; /* Add signature at the end of the buffer, * making sure that it doesn't underflow * into the CRT buffer. */ c2 = buf + size; MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, c, sig_oid, sig_oid_len, sig, sig_len, pk_alg)); /* * Memory layout after this step: * * buf c=buf+len c2 buf+size * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm] */ /* Move raw CRT to just before the signature. */ c = c2 - len; memmove(c, buf, len); len += sig_and_oid_len; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" #define PEM_END_CRT "-----END CERTIFICATE-----\n" #if defined(MBEDTLS_PEM_WRITE_C) int mbedtls_x509write_crt_pem(mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; if ((ret = mbedtls_x509write_crt_der(crt, buf, size, f_rng, p_rng)) < 0) { return ret; } if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT, buf + size - ret, ret, buf, size, &olen)) != 0) { return ret; } return 0; } #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CRT_WRITE_C */ webfakes/src/mbedtls/library/psa_util.c0000644000176200001440000005031514740737024017726 0ustar liggesusers/* * PSA hashing layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" /* This is needed for MBEDTLS_ERR_XXX macros */ #include #if defined(MBEDTLS_ASN1_WRITE_C) #include #include #endif #include "psa_util_internal.h" #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include #if defined(MBEDTLS_MD_LIGHT) #include #endif #if defined(MBEDTLS_LMS_C) #include #endif #if defined(MBEDTLS_SSL_TLS_C) && \ (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) #include #endif #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #include #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #include #endif #if defined(MBEDTLS_PK_C) #include #endif #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) #include #endif #include /* PSA_SUCCESS is kept at the top of each error table since * it's the most common status when everything functions properly. */ #if defined(MBEDTLS_MD_LIGHT) const mbedtls_error_pair_t psa_to_md_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_MD_BAD_INPUT_DATA }, { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_MD_ALLOC_FAILED } }; #endif #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) const mbedtls_error_pair_t psa_to_cipher_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA }, { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_CIPHER_ALLOC_FAILED } }; #endif #if defined(MBEDTLS_LMS_C) const mbedtls_error_pair_t psa_to_lms_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_LMS_BAD_INPUT_DATA } }; #endif #if defined(MBEDTLS_SSL_TLS_C) && \ (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) const mbedtls_error_pair_t psa_to_ssl_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_SSL_ALLOC_FAILED }, { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE }, { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_SSL_INVALID_MAC }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_SSL_BAD_INPUT_DATA }, { PSA_ERROR_BAD_STATE, MBEDTLS_ERR_SSL_INTERNAL_ERROR }, { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL } }; #endif #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) const mbedtls_error_pair_t psa_to_pk_rsa_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE }, { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_RSA_RNG_FAILED }, { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_RSA_VERIFY_FAILED }, { PSA_ERROR_INVALID_PADDING, MBEDTLS_ERR_RSA_INVALID_PADDING } }; #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_ECP_BAD_INPUT_DATA }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_ECP_BAD_INPUT_DATA }, { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE }, { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL }, { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_ECP_RANDOM_FAILED }, { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_ECP_VERIFY_FAILED } }; #endif int psa_generic_status_to_mbedtls(psa_status_t status) { switch (status) { case PSA_SUCCESS: return 0; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; case PSA_ERROR_CORRUPTION_DETECTED: return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; case PSA_ERROR_COMMUNICATION_FAILURE: case PSA_ERROR_HARDWARE_FAILURE: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; case PSA_ERROR_NOT_PERMITTED: default: return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } } int psa_status_to_mbedtls(psa_status_t status, const mbedtls_error_pair_t *local_translations, size_t local_errors_num, int (*fallback_f)(psa_status_t)) { for (size_t i = 0; i < local_errors_num; i++) { if (status == local_translations[i].psa_status) { return local_translations[i].mbedtls_error; } } return fallback_f(status); } #if defined(MBEDTLS_PK_C) int psa_pk_status_to_mbedtls(psa_status_t status) { switch (status) { case PSA_ERROR_INVALID_HANDLE: return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; case PSA_ERROR_BUFFER_TOO_SMALL: return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; case PSA_ERROR_INVALID_ARGUMENT: return MBEDTLS_ERR_PK_INVALID_ALG; case PSA_ERROR_NOT_PERMITTED: return MBEDTLS_ERR_PK_TYPE_MISMATCH; case PSA_ERROR_INSUFFICIENT_MEMORY: return MBEDTLS_ERR_PK_ALLOC_FAILED; case PSA_ERROR_BAD_STATE: return MBEDTLS_ERR_PK_BAD_INPUT_DATA; case PSA_ERROR_DATA_CORRUPT: case PSA_ERROR_DATA_INVALID: case PSA_ERROR_STORAGE_FAILURE: return MBEDTLS_ERR_PK_FILE_IO_ERROR; default: return psa_generic_status_to_mbedtls(status); } } #endif /* MBEDTLS_PK_C */ /****************************************************************/ /* Key management */ /****************************************************************/ #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid, size_t *bits) { switch (grpid) { #if defined(MBEDTLS_ECP_HAVE_SECP192R1) case MBEDTLS_ECP_DP_SECP192R1: *bits = 192; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP224R1) case MBEDTLS_ECP_DP_SECP224R1: *bits = 224; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP256R1) case MBEDTLS_ECP_DP_SECP256R1: *bits = 256; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP384R1) case MBEDTLS_ECP_DP_SECP384R1: *bits = 384; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP521R1) case MBEDTLS_ECP_DP_SECP521R1: *bits = 521; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_BP256R1) case MBEDTLS_ECP_DP_BP256R1: *bits = 256; return PSA_ECC_FAMILY_BRAINPOOL_P_R1; #endif #if defined(MBEDTLS_ECP_HAVE_BP384R1) case MBEDTLS_ECP_DP_BP384R1: *bits = 384; return PSA_ECC_FAMILY_BRAINPOOL_P_R1; #endif #if defined(MBEDTLS_ECP_HAVE_BP512R1) case MBEDTLS_ECP_DP_BP512R1: *bits = 512; return PSA_ECC_FAMILY_BRAINPOOL_P_R1; #endif #if defined(MBEDTLS_ECP_HAVE_CURVE25519) case MBEDTLS_ECP_DP_CURVE25519: *bits = 255; return PSA_ECC_FAMILY_MONTGOMERY; #endif #if defined(MBEDTLS_ECP_HAVE_SECP192K1) case MBEDTLS_ECP_DP_SECP192K1: *bits = 192; return PSA_ECC_FAMILY_SECP_K1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP224K1) /* secp224k1 is not and will not be supported in PSA (#3541). */ #endif #if defined(MBEDTLS_ECP_HAVE_SECP256K1) case MBEDTLS_ECP_DP_SECP256K1: *bits = 256; return PSA_ECC_FAMILY_SECP_K1; #endif #if defined(MBEDTLS_ECP_HAVE_CURVE448) case MBEDTLS_ECP_DP_CURVE448: *bits = 448; return PSA_ECC_FAMILY_MONTGOMERY; #endif default: *bits = 0; return 0; } } mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family, size_t bits) { switch (family) { case PSA_ECC_FAMILY_SECP_R1: switch (bits) { #if defined(PSA_WANT_ECC_SECP_R1_192) case 192: return MBEDTLS_ECP_DP_SECP192R1; #endif #if defined(PSA_WANT_ECC_SECP_R1_224) case 224: return MBEDTLS_ECP_DP_SECP224R1; #endif #if defined(PSA_WANT_ECC_SECP_R1_256) case 256: return MBEDTLS_ECP_DP_SECP256R1; #endif #if defined(PSA_WANT_ECC_SECP_R1_384) case 384: return MBEDTLS_ECP_DP_SECP384R1; #endif #if defined(PSA_WANT_ECC_SECP_R1_521) case 521: return MBEDTLS_ECP_DP_SECP521R1; #endif } break; case PSA_ECC_FAMILY_BRAINPOOL_P_R1: switch (bits) { #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) case 256: return MBEDTLS_ECP_DP_BP256R1; #endif #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) case 384: return MBEDTLS_ECP_DP_BP384R1; #endif #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) case 512: return MBEDTLS_ECP_DP_BP512R1; #endif } break; case PSA_ECC_FAMILY_MONTGOMERY: switch (bits) { #if defined(PSA_WANT_ECC_MONTGOMERY_255) case 255: return MBEDTLS_ECP_DP_CURVE25519; #endif #if defined(PSA_WANT_ECC_MONTGOMERY_448) case 448: return MBEDTLS_ECP_DP_CURVE448; #endif } break; case PSA_ECC_FAMILY_SECP_K1: switch (bits) { #if defined(PSA_WANT_ECC_SECP_K1_192) case 192: return MBEDTLS_ECP_DP_SECP192K1; #endif #if defined(PSA_WANT_ECC_SECP_K1_224) /* secp224k1 is not and will not be supported in PSA (#3541). */ #endif #if defined(PSA_WANT_ECC_SECP_K1_256) case 256: return MBEDTLS_ECP_DP_SECP256K1; #endif } break; } return MBEDTLS_ECP_DP_NONE; } #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ /* Wrapper function allowing the classic API to use the PSA RNG. * * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls * `psa_generate_random(...)`. The state parameter is ignored since the * PSA API doesn't support passing an explicit state. */ int mbedtls_psa_get_random(void *p_rng, unsigned char *output, size_t output_size) { /* This function takes a pointer to the RNG state because that's what * classic mbedtls functions using an RNG expect. The PSA RNG manages * its own state internally and doesn't let the caller access that state. * So we just ignore the state parameter, and in practice we'll pass * NULL. */ (void) p_rng; psa_status_t status = psa_generate_random(output, output_size); if (status == PSA_SUCCESS) { return 0; } else { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } } #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ #if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** * \brief Convert a single raw coordinate to DER ASN.1 format. The output der * buffer is filled backward (i.e. starting from its end). * * \param raw_buf Buffer containing the raw coordinate to be * converted. * \param raw_len Length of raw_buf in bytes. This must be > 0. * \param der_buf_start Pointer to the beginning of the buffer which * will be filled with the DER converted data. * \param der_buf_end End of the buffer used to store the DER output. * * \return On success, the amount of data (in bytes) written to * the DER buffer. * \return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der * buffer is too small to contain all the converted data. * \return MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw * coordinate is null (i.e. all zeros). * * \warning Raw and der buffer must not be overlapping. */ static int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len, unsigned char *der_buf_start, unsigned char *der_buf_end) { unsigned char *p = der_buf_end; int len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* ASN.1 DER encoding requires minimal length, so skip leading 0s. * Provided input MPIs should not be 0, but as a failsafe measure, still * detect that and return error in case. */ while (*raw_buf == 0x00) { ++raw_buf; --raw_len; if (raw_len == 0) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } } len = (int) raw_len; /* Copy the raw coordinate to the end of der_buf. */ if ((p - der_buf_start) < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } p -= len; memcpy(p, raw_buf, len); /* If MSb is 1, ASN.1 requires that we prepend a 0. */ if (*p & 0x80) { if ((p - der_buf_start) < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } --p; *p = 0x00; ++len; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER)); return len; } int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len, unsigned char *der, size_t der_size, size_t *der_len) { unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; const size_t coordinate_len = PSA_BITS_TO_BYTES(bits); size_t len = 0; unsigned char *p = der + der_size; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (raw_len != (2 * coordinate_len)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } if (coordinate_len > sizeof(r)) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } /* Since raw and der buffers might overlap, dump r and s before starting * the conversion. */ memcpy(r, raw, coordinate_len); memcpy(s, raw + coordinate_len, coordinate_len); /* der buffer will initially be written starting from its end so we pick s * first and then r. */ ret = convert_raw_to_der_single_int(s, coordinate_len, der, p); if (ret < 0) { return ret; } p -= ret; len += ret; ret = convert_raw_to_der_single_int(r, coordinate_len, der, p); if (ret < 0) { return ret; } p -= ret; len += ret; /* Add ASN.1 header (len + tag). */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* memmove the content of der buffer to its beginnig. */ memmove(der, p, len); *der_len = len; return 0; } /** * \brief Convert a single integer from ASN.1 DER format to raw. * * \param der Buffer containing the DER integer value to be * converted. * \param der_len Length of the der buffer in bytes. * \param raw Output buffer that will be filled with the * converted data. This should be at least * coordinate_size bytes and it must be zeroed before * calling this function. * \param coordinate_size Size (in bytes) of a single coordinate in raw * format. * * \return On success, the amount of DER data parsed from the * provided der buffer. * \return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag * is missing in the der buffer. * \return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer * is null (i.e. all zeros) or if the output raw buffer * is too small to contain the converted raw value. * * \warning Der and raw buffers must not be overlapping. */ static int convert_der_to_raw_single_int(unsigned char *der, size_t der_len, unsigned char *raw, size_t coordinate_size) { unsigned char *p = der; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t unpadded_len, padding_len = 0; /* Get the length of ASN.1 element (i.e. the integer we need to parse). */ ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len, MBEDTLS_ASN1_INTEGER); if (ret != 0) { return ret; } /* It's invalid to have: * - unpadded_len == 0. * - MSb set without a leading 0x00 (leading 0x00 is checked below). */ if (((unpadded_len == 0) || (*p & 0x80) != 0)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } /* Skip possible leading zero */ if (*p == 0x00) { p++; unpadded_len--; /* It is not allowed to have more than 1 leading zero. * Ignore the case in which unpadded_len = 0 because that's a 0 encoded * in ASN.1 format (i.e. 020100). */ if ((unpadded_len > 0) && (*p == 0x00)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } } if (unpadded_len > coordinate_size) { /* Parsed number is longer than the maximum expected value. */ return MBEDTLS_ERR_ASN1_INVALID_DATA; } padding_len = coordinate_size - unpadded_len; /* raw buffer was already zeroed by the calling function so zero-padding * operation is skipped here. */ memcpy(raw + padding_len, p, unpadded_len); p += unpadded_len; return (int) (p - der); } int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len, unsigned char *raw, size_t raw_size, size_t *raw_len) { unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE]; unsigned char *p = (unsigned char *) der; size_t data_len; size_t coordinate_size = PSA_BITS_TO_BYTES(bits); int ret; /* The output raw buffer should be at least twice the size of a raw * coordinate in order to store r and s. */ if (raw_size < coordinate_size * 2) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } if (2 * coordinate_size > sizeof(raw_tmp)) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } /* Check that the provided input DER buffer has the right header. */ ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return ret; } memset(raw_tmp, 0, 2 * coordinate_size); /* Extract r */ ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size); if (ret < 0) { return ret; } p += ret; data_len -= ret; /* Extract s */ ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size, coordinate_size); if (ret < 0) { return ret; } p += ret; data_len -= ret; /* Check that we consumed all the input der data. */ if ((size_t) (p - der) != der_len) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } memcpy(raw, raw_tmp, 2 * coordinate_size); *raw_len = 2 * coordinate_size; return 0; } #endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */ webfakes/src/mbedtls/library/ssl_tls12_server.c0000644000176200001440000047232414740737024021332 0ustar liggesusers/* * TLS server-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "ssl_misc.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif #endif #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) int mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl, const unsigned char *info, size_t ilen) { if (ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } mbedtls_free(ssl->cli_id); if ((ssl->cli_id = mbedtls_calloc(1, ilen)) == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ssl->cli_id, info, ilen); ssl->cli_id_len = ilen; return 0; } void mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf, mbedtls_ssl_cookie_write_t *f_cookie_write, mbedtls_ssl_cookie_check_t *f_cookie_check, void *p_cookie) { conf->f_cookie_write = f_cookie_write; conf->f_cookie_check = f_cookie_check; conf->p_cookie = p_cookie; } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_has_psk_or_cb(mbedtls_ssl_config const *conf) { if (conf->f_psk != NULL) { return 1; } if (conf->psk_identity_len == 0 || conf->psk_identity == NULL) { return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { return 1; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (conf->psk != NULL && conf->psk_len != 0) { return 1; } return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { /* Check verify-data in constant-time. The length OTOH is no secret */ if (len != 1 + ssl->verify_data_len || buf[0] != ssl->verify_data_len || mbedtls_ct_memcmp(buf + 1, ssl->peer_verify_data, ssl->verify_data_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching renegotiation info")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ { if (len != 1 || buf[0] != 0x0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-zero length renegotiation info")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; } return 0; } #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) /* * Function for parsing a supported groups (TLS 1.3) or supported elliptic * curves (TLS 1.2) extension. * * The "extension_data" field of a supported groups extension contains a * "NamedGroupList" value (TLS 1.3 RFC8446): * enum { * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), * x25519(0x001D), x448(0x001E), * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), * ffdhe6144(0x0103), ffdhe8192(0x0104), * ffdhe_private_use(0x01FC..0x01FF), * ecdhe_private_use(0xFE00..0xFEFF), * (0xFFFF) * } NamedGroup; * struct { * NamedGroup named_group_list<2..2^16-1>; * } NamedGroupList; * * The "extension_data" field of a supported elliptic curves extension contains * a "NamedCurveList" value (TLS 1.2 RFC 8422): * enum { * deprecated(1..22), * secp256r1 (23), secp384r1 (24), secp521r1 (25), * x25519(29), x448(30), * reserved (0xFE00..0xFEFF), * deprecated(0xFF01..0xFF02), * (0xFFFF) * } NamedCurve; * struct { * NamedCurve named_curve_list<2..2^16-1> * } NamedCurveList; * * The TLS 1.3 supported groups extension was defined to be a compatible * generalization of the TLS 1.2 supported elliptic curves extension. They both * share the same extension identifier. * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_groups_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t list_size, our_size; const unsigned char *p; uint16_t *curves_tls_id; if (len < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_size = MBEDTLS_GET_UINT16_BE(buf, 0); if (list_size + 2 != len || list_size % 2 != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Should never happen unless client duplicates the extension */ if (ssl->handshake->curves_tls_id != NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* Don't allow our peer to make us allocate too much memory, * and leave room for a final 0 */ our_size = list_size / 2 + 1; if (our_size > MBEDTLS_ECP_DP_MAX) { our_size = MBEDTLS_ECP_DP_MAX; } if ((curves_tls_id = mbedtls_calloc(our_size, sizeof(*curves_tls_id))) == NULL) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } ssl->handshake->curves_tls_id = curves_tls_id; p = buf + 2; while (list_size > 0 && our_size > 1) { uint16_t curr_tls_id = MBEDTLS_GET_UINT16_BE(p, 0); if (mbedtls_ssl_get_ecp_group_id_from_tls_id(curr_tls_id) != MBEDTLS_ECP_DP_NONE) { *curves_tls_id++ = curr_tls_id; our_size--; } list_size -= 2; p += 2; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t list_size; const unsigned char *p; if (len == 0 || (size_t) (buf[0] + 1) != len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_size = buf[0]; p = buf + 1; while (list_size > 0) { if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || p[0] == MBEDTLS_ECP_PF_COMPRESSED) { #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) ssl->handshake->ecdh_ctx.point_format = p[0]; #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx, p[0]); #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(4, ("point format selected: %d", p[0])); return 0; } list_size--; p++; } return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) if (ssl->handshake->psa_pake_ctx_is_ok != 1) #else if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) #endif /* MBEDTLS_USE_PSA_CRYPTO */ { MBEDTLS_SSL_DEBUG_MSG(3, ("skip ecjpake kkpp extension")); return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_psa_ecjpake_read_round( &ssl->handshake->psa_pake_ctx, buf, len, MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return ret; } #else if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx, buf, len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_one", ret); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Only mark the extension as OK when we're sure it is */ ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->session_negotiate->mfl_code = buf[0]; return 0; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t peer_cid_len; /* CID extension only makes sense in DTLS */ if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* * struct { * opaque cid<0..2^8-1>; * } ConnectionId; */ if (len < 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } peer_cid_len = *buf++; len--; if (len != peer_cid_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Ignore CID if the user has disabled its use. */ if (ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { /* Leave ssl->handshake->cid_in_use in its default * value of MBEDTLS_SSL_CID_DISABLED. */ MBEDTLS_SSL_DEBUG_MSG(3, ("Client sent CID extension, but CID disabled")); return 0; } if (peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; memcpy(ssl->handshake->peer_cid, buf, peer_cid_len); MBEDTLS_SSL_DEBUG_MSG(3, ("Use of CID extension negotiated")); MBEDTLS_SSL_DEBUG_BUF(3, "Client CID", buf, peer_cid_len); return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ((void) buf); if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED) { ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; } return 0; } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ((void) buf); if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) { ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; } return 0; } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_session session; mbedtls_ssl_session_init(&session); if (ssl->conf->f_ticket_parse == NULL || ssl->conf->f_ticket_write == NULL) { return 0; } /* Remember the client asked us to send a new ticket */ ssl->handshake->new_session_ticket = 1; MBEDTLS_SSL_DEBUG_MSG(3, ("ticket length: %" MBEDTLS_PRINTF_SIZET, len)); if (len == 0) { return 0; } #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(3, ("ticket rejected: renegotiating")); return 0; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ /* * Failures are ok: just ignore the ticket and proceed. */ if ((ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket, &session, buf, len)) != 0) { mbedtls_ssl_session_free(&session); if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) { MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic")); } else if (ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) { MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired")); } else { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_parse", ret); } return 0; } /* * Keep the session ID sent by the client, since we MUST send it back to * inform them we're accepting the ticket (RFC 5077 section 3.4) */ session.id_len = ssl->session_negotiate->id_len; memcpy(&session.id, ssl->session_negotiate->id, session.id_len); mbedtls_ssl_session_free(ssl->session_negotiate); memcpy(ssl->session_negotiate, &session, sizeof(mbedtls_ssl_session)); /* Zeroize instead of free as we copied the content */ mbedtls_platform_zeroize(&session, sizeof(mbedtls_ssl_session)); MBEDTLS_SSL_DEBUG_MSG(3, ("session successfully restored from ticket")); ssl->handshake->resume = 1; /* Don't send a new ticket after all, this one is OK */ ssl->handshake->new_session_ticket = 0; return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_DTLS_SRTP) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET; size_t i, j; size_t profile_length; uint16_t mki_length; /*! 2 bytes for profile length and 1 byte for mki len */ const size_t size_of_lengths = 3; /* If use_srtp is not configured, just ignore the extension */ if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->conf->dtls_srtp_profile_list == NULL) || (ssl->conf->dtls_srtp_profile_list_len == 0)) { return 0; } /* RFC5764 section 4.1.1 * uint8 SRTPProtectionProfile[2]; * * struct { * SRTPProtectionProfiles SRTPProtectionProfiles; * opaque srtp_mki<0..255>; * } UseSRTPData; * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; */ /* * Min length is 5: at least one protection profile(2 bytes) * and length(2 bytes) + srtp_mki length(1 byte) * Check here that we have at least 2 bytes of protection profiles length * and one of srtp_mki length */ if (len < size_of_lengths) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; /* first 2 bytes are protection profile length(in bytes) */ profile_length = (buf[0] << 8) | buf[1]; buf += 2; /* The profile length cannot be bigger than input buffer size - lengths fields */ if (profile_length > len - size_of_lengths || profile_length % 2 != 0) { /* profiles are 2 bytes long, so the length must be even */ mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * parse the extension list values are defined in * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml */ for (j = 0; j < profile_length; j += 2) { uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1]; client_protection = mbedtls_ssl_check_srtp_profile_value(protection_profile_value); if (client_protection != MBEDTLS_TLS_SRTP_UNSET) { MBEDTLS_SSL_DEBUG_MSG(3, ("found srtp profile: %s", mbedtls_ssl_get_srtp_profile_as_string( client_protection))); } else { continue; } /* check if suggested profile is in our list */ for (i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) { if (client_protection == ssl->conf->dtls_srtp_profile_list[i]) { ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; MBEDTLS_SSL_DEBUG_MSG(3, ("selected srtp profile: %s", mbedtls_ssl_get_srtp_profile_as_string( client_protection))); break; } } if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET) { break; } } buf += profile_length; /* buf points to the mki length */ mki_length = *buf; buf++; if (mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH || mki_length + profile_length + size_of_lengths != len) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Parse the mki only if present and mki is supported locally */ if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED && mki_length > 0) { ssl->dtls_srtp_info.mki_len = mki_length; memcpy(ssl->dtls_srtp_info.mki_value, buf, mki_length); MBEDTLS_SSL_DEBUG_BUF(3, "using mki", ssl->dtls_srtp_info.mki_value, ssl->dtls_srtp_info.mki_len); } return 0; } #endif /* MBEDTLS_SSL_DTLS_SRTP */ /* * Auxiliary functions for ServerHello parsing and related actions */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /* * Return 0 if the given key uses one of the acceptable curves, -1 otherwise */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_key_curve(mbedtls_pk_context *pk, uint16_t *curves_tls_id) { uint16_t *curr_tls_id = curves_tls_id; mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(pk); mbedtls_ecp_group_id curr_grp_id; while (*curr_tls_id != 0) { curr_grp_id = mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id); if (curr_grp_id == grp_id) { return 0; } curr_tls_id++; } return -1; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED */ /* * Try picking a certificate for this ciphersuite, * return 0 on success and -1 on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_pick_cert(mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info) { mbedtls_ssl_key_cert *cur, *list; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(ciphersuite_info); psa_key_usage_t pk_usage = mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(ciphersuite_info); #else mbedtls_pk_type_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ uint32_t flags; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_key_cert != NULL) { list = ssl->handshake->sni_key_cert; } else #endif list = ssl->conf->key_cert; int pk_alg_is_none = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) pk_alg_is_none = (pk_alg == PSA_ALG_NONE); #else pk_alg_is_none = (pk_alg == MBEDTLS_PK_NONE); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (pk_alg_is_none) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite requires certificate")); if (list == NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("server has no certificate")); return -1; } for (cur = list; cur != NULL; cur = cur->next) { flags = 0; MBEDTLS_SSL_DEBUG_CRT(3, "candidate certificate chain, certificate", cur->cert); int key_type_matches = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) key_type_matches = ((ssl->conf->f_async_sign_start != NULL || ssl->conf->f_async_decrypt_start != NULL || mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)) && mbedtls_pk_can_do_ext(&cur->cert->pk, pk_alg, pk_usage)); #else key_type_matches = ( mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)); #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #else key_type_matches = mbedtls_pk_can_do(&cur->cert->pk, pk_alg); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (!key_type_matches) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: key type")); continue; } /* * This avoids sending the client a cert it'll reject based on * keyUsage or other extensions. * * It also allows the user to provision different certificates for * different uses based on keyUsage, eg if they want to avoid signing * and decrypting with the same RSA key. */ if (mbedtls_ssl_check_cert_usage(cur->cert, ciphersuite_info, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_VERSION_TLS1_2, &flags) != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: " "(extended) key usage extension")); continue; } #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) if (pk_alg == MBEDTLS_PK_ECDSA && ssl_check_key_curve(&cur->cert->pk, ssl->handshake->curves_tls_id) != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: elliptic curve")); continue; } #endif /* If we get there, we got a winner */ break; } /* Do not update ssl->handshake->key_cert unless there is a match */ if (cur != NULL) { ssl->handshake->key_cert = cur; MBEDTLS_SSL_DEBUG_CRT(3, "selected certificate chain, certificate", ssl->handshake->key_cert->cert); return 0; } return -1; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* * Check if a given ciphersuite is suitable for use with our config/keys/etc * Sets ciphersuite_info only if the suite matches. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id, const mbedtls_ssl_ciphersuite_t **ciphersuite_info) { const mbedtls_ssl_ciphersuite_t *suite_info; #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) mbedtls_pk_type_t sig_type; #endif suite_info = mbedtls_ssl_ciphersuite_from_id(suite_id); if (suite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("trying ciphersuite: %#04x (%s)", (unsigned int) suite_id, suite_info->name)); if (suite_info->min_tls_version > ssl->tls_version || suite_info->max_tls_version < ssl->tls_version) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: version")); return 0; } #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && (ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK) == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: ecjpake " "not configured or ext missing")); return 0; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) if (mbedtls_ssl_ciphersuite_uses_ec(suite_info) && (ssl->handshake->curves_tls_id == NULL || ssl->handshake->curves_tls_id[0] == 0)) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: " "no common elliptic curve")); return 0; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) /* If the ciphersuite requires a pre-shared key and we don't * have one, skip it now rather than failing later */ if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) && ssl_conf_has_psk_or_cb(ssl->conf) == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: no pre-shared key")); return 0; } #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) /* * Final check: if ciphersuite requires us to have a * certificate/key of a particular type: * - select the appropriate certificate if we have one, or * - try the next ciphersuite if we don't * This must be done last since we modify the key_cert list. */ if (ssl_pick_cert(ssl, suite_info) != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: " "no suitable certificate")); return 0; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* If the ciphersuite requires signing, check whether * a suitable hash algorithm is present. */ sig_type = mbedtls_ssl_get_ciphersuite_sig_alg(suite_info); if (sig_type != MBEDTLS_PK_NONE && mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( ssl, mbedtls_ssl_sig_from_pk_alg(sig_type)) == MBEDTLS_SSL_HASH_NONE) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: no suitable hash algorithm " "for signature algorithm %u", (unsigned) sig_type)); return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ *ciphersuite_info = suite_info; return 0; } /* This function doesn't alert on errors that happen early during ClientHello parsing because they might indicate that the client is not talking SSL/TLS at all and would not understand our alert. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) { int ret, got_common_suite; size_t i, j; size_t ciph_offset, comp_offset, ext_offset; size_t msg_len, ciph_len, sess_len, comp_len, ext_len; #if defined(MBEDTLS_SSL_PROTO_DTLS) size_t cookie_offset, cookie_len; #endif unsigned char *buf, *p, *ext; #if defined(MBEDTLS_SSL_RENEGOTIATION) int renegotiation_info_seen = 0; #endif int handshake_failure = 0; const int *ciphersuites; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; /* If there is no signature-algorithm extension present, * we need to fall back to the default values for allowed * signature-hash pairs. */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) int sig_hash_alg_ext_present = 0; #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); int renegotiating; #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) read_record_header: #endif /* * If renegotiating, then the input was read with mbedtls_ssl_read_record(), * otherwise read it ourselves manually in order to support SSLv2 * ClientHello, which doesn't use the same record layer format. * Otherwise in a scenario of TLS 1.3/TLS 1.2 version negotiation, the * ClientHello has been already fully fetched by the TLS 1.3 code and the * flag ssl->keep_current_message is raised. */ renegotiating = 0; #if defined(MBEDTLS_SSL_RENEGOTIATION) renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE); #endif if (!renegotiating && !ssl->keep_current_message) { if ((ret = mbedtls_ssl_fetch_input(ssl, 5)) != 0) { /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); return ret; } } buf = ssl->in_hdr; MBEDTLS_SSL_DEBUG_BUF(4, "record header", buf, mbedtls_ssl_in_hdr_len(ssl)); /* * TLS Client Hello * * Record layer: * 0 . 0 message type * 1 . 2 protocol version * 3 . 11 DTLS: epoch + record sequence number * 3 . 4 message length */ MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message type: %d", buf[0])); if (buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message len.: %d", MBEDTLS_GET_UINT16_BE(ssl->in_len, 0))); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, protocol version: [%d:%d]", buf[1], buf[2])); /* For DTLS if this is the initial handshake, remember the client sequence * number to use it in our next message (RFC 6347 4.2.1) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM #if defined(MBEDTLS_SSL_RENEGOTIATION) && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE #endif ) { /* Epoch should be 0 for initial handshakes */ if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, sizeof(ssl->cur_out_ctr) - 2); #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if (mbedtls_ssl_dtls_replay_check(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("replayed record, discarding")); ssl->next_record_offset = 0; ssl->in_left = 0; goto read_record_header; } /* No MAC to check yet, so we can update right now */ mbedtls_ssl_dtls_replay_update(ssl); #endif } #endif /* MBEDTLS_SSL_PROTO_DTLS */ msg_len = MBEDTLS_GET_UINT16_BE(ssl->in_len, 0); #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { /* Set by mbedtls_ssl_read_record() */ msg_len = ssl->in_hslen; } else #endif { if (ssl->keep_current_message) { ssl->keep_current_message = 0; } else { if (msg_len > MBEDTLS_SSL_IN_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } if ((ret = mbedtls_ssl_fetch_input(ssl, mbedtls_ssl_in_hdr_len(ssl) + msg_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); return ret; } /* Done reading this record, get ready for the next one */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len(ssl); } else #endif ssl->in_left = 0; } } buf = ssl->in_msg; MBEDTLS_SSL_DEBUG_BUF(4, "record contents", buf, msg_len); ret = ssl->handshake->update_checksum(ssl, buf, msg_len); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } /* * Handshake layer: * 0 . 0 handshake type * 1 . 3 handshake length * 4 . 5 DTLS only: message sequence number * 6 . 8 DTLS only: fragment offset * 9 . 11 DTLS only: fragment length */ if (msg_len < mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake type: %d", buf[0])); if (buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } { size_t handshake_len = MBEDTLS_GET_UINT24_BE(buf, 1); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake len.: %u", (unsigned) handshake_len)); /* The record layer has a record size limit of 2^14 - 1 and * fragmentation is not supported, so buf[1] should be zero. */ if (buf[1] != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != 0", (unsigned) buf[1])); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* We don't support fragmentation of ClientHello (yet?) */ if (msg_len != mbedtls_ssl_hs_hdr_len(ssl) + handshake_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != %u + %u", (unsigned) msg_len, (unsigned) mbedtls_ssl_hs_hdr_len(ssl), (unsigned) handshake_len)); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* * Copy the client's handshake message_seq on initial handshakes, * check sequence number on renego. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { /* This couldn't be done in ssl_prepare_handshake_record() */ unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); if (cli_msg_seq != ssl->handshake->in_msg_seq) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message_seq: " "%u (expected %u)", cli_msg_seq, ssl->handshake->in_msg_seq)); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->handshake->in_msg_seq++; } else #endif { unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); ssl->handshake->out_msg_seq = cli_msg_seq; ssl->handshake->in_msg_seq = cli_msg_seq + 1; } { /* * For now we don't support fragmentation, so make sure * fragment_offset == 0 and fragment_length == length */ size_t fragment_offset, fragment_length, length; fragment_offset = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6); fragment_length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9); length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1); MBEDTLS_SSL_DEBUG_MSG( 4, ("fragment_offset=%u fragment_length=%u length=%u", (unsigned) fragment_offset, (unsigned) fragment_length, (unsigned) length)); if (fragment_offset != 0 || length != fragment_length) { MBEDTLS_SSL_DEBUG_MSG(1, ("ClientHello fragmentation not supported")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ buf += mbedtls_ssl_hs_hdr_len(ssl); msg_len -= mbedtls_ssl_hs_hdr_len(ssl); /* * ClientHello layout: * 0 . 1 protocol version * 2 . 33 random bytes (starting with 4 bytes of Unix time) * 34 . 34 session id length (1 byte) * 35 . 34+x session id, where x = session id length from byte 34 * 35+x . 35+x DTLS only: cookie length (1 byte) * 36+x . .. DTLS only: cookie * .. . .. ciphersuite list length (2 bytes) * .. . .. ciphersuite list * .. . .. compression alg. list length (1 byte) * .. . .. compression alg. list * .. . .. extensions length (2 bytes, optional) * .. . .. extensions (optional) */ /* * Minimal length (with everything empty and extensions omitted) is * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can * read at least up to session id length without worrying. */ if (msg_len < 38) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Check and save the protocol version */ MBEDTLS_SSL_DEBUG_BUF(3, "client hello, version", buf, 2); ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf, ssl->conf->transport); ssl->session_negotiate->tls_version = ssl->tls_version; ssl->session_negotiate->endpoint = ssl->conf->endpoint; if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) { MBEDTLS_SSL_DEBUG_MSG(1, ("server only supports TLS 1.2")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } /* * Save client random (inc. Unix time) */ MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", buf + 2, 32); memcpy(ssl->handshake->randbytes, buf + 2, 32); /* * Check the session ID length and save session ID */ sess_len = buf[34]; if (sess_len > sizeof(ssl->session_negotiate->id) || sess_len + 34 + 2 > msg_len) { /* 2 for cipherlist length field */ MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", buf + 35, sess_len); ssl->session_negotiate->id_len = sess_len; memset(ssl->session_negotiate->id, 0, sizeof(ssl->session_negotiate->id)); memcpy(ssl->session_negotiate->id, buf + 35, ssl->session_negotiate->id_len); /* * Check the cookie length and content */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { cookie_offset = 35 + sess_len; cookie_len = buf[cookie_offset]; if (cookie_offset + 1 + cookie_len + 2 > msg_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", buf + cookie_offset + 1, cookie_len); #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) if (ssl->conf->f_cookie_check != NULL #if defined(MBEDTLS_SSL_RENEGOTIATION) && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE #endif ) { if (ssl->conf->f_cookie_check(ssl->conf->p_cookie, buf + cookie_offset + 1, cookie_len, ssl->cli_id, ssl->cli_id_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification failed")); ssl->handshake->cookie_verify_result = 1; } else { MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification passed")); ssl->handshake->cookie_verify_result = 0; } } else #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ { /* We know we didn't send a cookie, so it should be empty */ if (cookie_len != 0) { /* This may be an attacker's probe, so don't send an alert */ MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification skipped")); } /* * Check the ciphersuitelist length (will be parsed later) */ ciph_offset = cookie_offset + 1 + cookie_len; } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ ciph_offset = 35 + sess_len; ciph_len = MBEDTLS_GET_UINT16_BE(buf, ciph_offset); if (ciph_len < 2 || ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ (ciph_len % 2) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, ciphersuitelist", buf + ciph_offset + 2, ciph_len); /* * Check the compression algorithm's length. * The list contents are ignored because implementing * MBEDTLS_SSL_COMPRESS_NULL is mandatory and is the only * option supported by Mbed TLS. */ comp_offset = ciph_offset + 2 + ciph_len; comp_len = buf[comp_offset]; if (comp_len < 1 || comp_len > 16 || comp_len + comp_offset + 1 > msg_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, compression", buf + comp_offset + 1, comp_len); /* * Check the extension length */ ext_offset = comp_offset + 1 + comp_len; if (msg_len > ext_offset) { if (msg_len < ext_offset + 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ext_len = MBEDTLS_GET_UINT16_BE(buf, ext_offset); if (msg_len != ext_offset + 2 + ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } else { ext_len = 0; } ext = buf + ext_offset + 2; MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", ext, ext_len); while (ext_len != 0) { unsigned int ext_id; unsigned int ext_size; if (ext_len < 4) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ext_id = MBEDTLS_GET_UINT16_BE(ext, 0); ext_size = MBEDTLS_GET_UINT16_BE(ext, 2); if (ext_size + 4 > ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } switch (ext_id) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) case MBEDTLS_TLS_EXT_SERVERNAME: MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension")); ret = mbedtls_ssl_parse_server_name_ext(ssl, ext + 4, ext + 4 + ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: MBEDTLS_SSL_DEBUG_MSG(3, ("found renegotiation extension")); #if defined(MBEDTLS_SSL_RENEGOTIATION) renegotiation_info_seen = 1; #endif ret = ssl_parse_renegotiation_info(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) case MBEDTLS_TLS_EXT_SIG_ALG: MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension")); ret = mbedtls_ssl_parse_sig_alg_ext(ssl, ext + 4, ext + 4 + ext_size); if (ret != 0) { return ret; } sig_hash_alg_ext_present = 1; break; #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: MBEDTLS_SSL_DEBUG_MSG(3, ("found supported elliptic curves extension")); ret = ssl_parse_supported_groups_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: MBEDTLS_SSL_DEBUG_MSG(3, ("found supported point formats extension")); ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; ret = ssl_parse_supported_point_formats(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || \ MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: MBEDTLS_SSL_DEBUG_MSG(3, ("found ecjpake kkpp extension")); ret = ssl_parse_ecjpake_kkpp(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: MBEDTLS_SSL_DEBUG_MSG(3, ("found max fragment length extension")); ret = ssl_parse_max_fragment_length_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) case MBEDTLS_TLS_EXT_CID: MBEDTLS_SSL_DEBUG_MSG(3, ("found CID extension")); ret = ssl_parse_cid_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: MBEDTLS_SSL_DEBUG_MSG(3, ("found encrypt then mac extension")); ret = ssl_parse_encrypt_then_mac_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: MBEDTLS_SSL_DEBUG_MSG(3, ("found extended master secret extension")); ret = ssl_parse_extended_ms_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_TLS_EXT_SESSION_TICKET: MBEDTLS_SSL_DEBUG_MSG(3, ("found session ticket extension")); ret = ssl_parse_session_ticket_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_ALPN) case MBEDTLS_TLS_EXT_ALPN: MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); ret = mbedtls_ssl_parse_alpn_ext(ssl, ext + 4, ext + 4 + ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_DTLS_SRTP) case MBEDTLS_TLS_EXT_USE_SRTP: MBEDTLS_SSL_DEBUG_MSG(3, ("found use_srtp extension")); ret = ssl_parse_use_srtp_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_DTLS_SRTP */ default: MBEDTLS_SSL_DEBUG_MSG(3, ("unknown extension found: %u (ignoring)", ext_id)); } ext_len -= 4 + ext_size; ext += 4 + ext_size; } #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* * Try to fall back to default hash SHA1 if the client * hasn't provided any preferred signature-hash combinations. */ if (!sig_hash_alg_ext_present) { uint16_t *received_sig_algs = ssl->handshake->received_sig_algs; const uint16_t default_sig_algs[] = { #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA1), #endif #if defined(MBEDTLS_RSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA1), #endif MBEDTLS_TLS_SIG_NONE }; MBEDTLS_STATIC_ASSERT(sizeof(default_sig_algs) / sizeof(default_sig_algs[0]) <= MBEDTLS_RECEIVED_SIG_ALGS_SIZE, "default_sig_algs is too big"); memcpy(received_sig_algs, default_sig_algs, sizeof(default_sig_algs)); } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /* * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ for (i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2) { if (p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO) { MBEDTLS_SSL_DEBUG_MSG(3, ("received TLS_EMPTY_RENEGOTIATION_INFO ")); #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { MBEDTLS_SSL_DEBUG_MSG(1, ("received RENEGOTIATION SCSV " "during renegotiation")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; break; } } /* * Renegotiation security checks */ if (ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation, breaking off handshake")); handshake_failure = 1; } #if defined(MBEDTLS_SSL_RENEGOTIATION) else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && renegotiation_info_seen == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension missing (secure)")); handshake_failure = 1; } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) { MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation not allowed")); handshake_failure = 1; } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && renegotiation_info_seen == 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension present (legacy)")); handshake_failure = 1; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ if (handshake_failure == 1) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* * Server certification selection (after processing TLS extensions) */ if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret); return ret; } #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) ssl->handshake->sni_name = NULL; ssl->handshake->sni_name_len = 0; #endif /* * Search for a matching ciphersuite * (At the end because we need information from the EC-based extensions * and certificate from the SNI callback triggered by the SNI extension * or certificate from server certificate selection callback.) */ got_common_suite = 0; ciphersuites = ssl->conf->ciphersuite_list; ciphersuite_info = NULL; if (ssl->conf->respect_cli_pref == MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) { for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { for (i = 0; ciphersuites[i] != 0; i++) { if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) { continue; } got_common_suite = 1; if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], &ciphersuite_info)) != 0) { return ret; } if (ciphersuite_info != NULL) { goto have_ciphersuite; } } } } else { for (i = 0; ciphersuites[i] != 0; i++) { for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) { continue; } got_common_suite = 1; if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], &ciphersuite_info)) != 0) { return ret; } if (ciphersuite_info != NULL) { goto have_ciphersuite; } } } } if (got_common_suite) { MBEDTLS_SSL_DEBUG_MSG(1, ("got ciphersuites in common, " "but none of them usable")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("got no ciphersuites in common")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } have_ciphersuite: MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %s", ciphersuite_info->name)); ssl->session_negotiate->ciphersuite = ciphersuites[i]; ssl->handshake->ciphersuite_info = ciphersuite_info; ssl->state++; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_recv_flight_completed(ssl); } #endif /* Debugging-only output for testsuite */ #if defined(MBEDTLS_DEBUG_C) && \ defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg(ciphersuite_info); if (sig_alg != MBEDTLS_PK_NONE) { unsigned int sig_hash = mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg)); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext: %u", sig_hash)); } else { MBEDTLS_SSL_DEBUG_MSG(3, ("no hash algorithm for signature algorithm " "%u - should not happen", (unsigned) sig_alg)); } #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client hello")); return 0; } #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) static void ssl_write_cid_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; size_t ext_len; const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; /* Skip writing the extension if we don't want to use it or if * the client hasn't offered it. */ if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_DISABLED) { return; } /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX * which is at most 255, so the increment cannot overflow. */ if (end < p || (size_t) (end - p) < (unsigned) (ssl->own_cid_len + 5)) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding CID extension")); /* * struct { * opaque cid<0..2^8-1>; * } ConnectionId; */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_CID, p, 0); p += 2; ext_len = (size_t) ssl->own_cid_len + 1; MBEDTLS_PUT_UINT16_BE(ext_len, p, 0); p += 2; *p++ = (uint8_t) ssl->own_cid_len; memcpy(p, ssl->own_cid, ssl->own_cid_len); *olen = ssl->own_cid_len + 5; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) static void ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; const mbedtls_ssl_ciphersuite_t *suite = NULL; /* * RFC 7366: "If a server receives an encrypt-then-MAC request extension * from a client and then selects a stream or Authenticated Encryption * with Associated Data (AEAD) ciphersuite, it MUST NOT send an * encrypt-then-MAC response extension back to the client." */ suite = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite); if (suite == NULL) { ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; } else { mbedtls_ssl_mode_t ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite( ssl->session_negotiate->encrypt_then_mac, suite); if (ssl_mode != MBEDTLS_SSL_MODE_CBC_ETM) { ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; } } if (ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding encrypt then mac extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) static void ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; if (ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding extended master secret " "extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) static void ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; if (ssl->handshake->new_session_ticket == 0) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding session ticket extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ static void ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; if (ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, secure renegotiation extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0); p += 2; #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { *p++ = 0x00; *p++ = (ssl->verify_data_len * 2 + 1) & 0xFF; *p++ = ssl->verify_data_len * 2 & 0xFF; memcpy(p, ssl->peer_verify_data, ssl->verify_data_len); p += ssl->verify_data_len; memcpy(p, ssl->own_verify_data, ssl->verify_data_len); p += ssl->verify_data_len; } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ { *p++ = 0x00; *p++ = 0x01; *p++ = 0x00; } *olen = (size_t) (p - buf); } #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) static void ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; if (ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, max_fragment_length extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0); p += 2; *p++ = 0x00; *p++ = 1; *p++ = ssl->session_negotiate->mfl_code; *olen = 5; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; ((void) ssl); if ((ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT) == 0) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, supported_point_formats extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0); p += 2; *p++ = 0x00; *p++ = 2; *p++ = 1; *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; *olen = 6; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t kkpp_len; *olen = 0; /* Skip costly computation if not needed */ if (ssl->handshake->ciphersuite_info->key_exchange != MBEDTLS_KEY_EXCHANGE_ECJPAKE) { return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, ecjpake kkpp extension")); if (end - p < 4) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); return; } MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0); p += 2; #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, p + 2, (size_t) (end - p - 2), &kkpp_len, MBEDTLS_ECJPAKE_ROUND_ONE); if (ret != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); return; } #else ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx, p + 2, (size_t) (end - p - 2), &kkpp_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_one", ret); return; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0); p += 2; *olen = kkpp_len + 4; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_DTLS_SRTP) && defined(MBEDTLS_SSL_PROTO_DTLS) static void ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { size_t mki_len = 0, ext_len = 0; uint16_t profile_value = 0; const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET)) { return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding use_srtp extension")); if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) { mki_len = ssl->dtls_srtp_info.mki_len; } /* The extension total size is 9 bytes : * - 2 bytes for the extension tag * - 2 bytes for the total size * - 2 bytes for the protection profile length * - 2 bytes for the protection profile * - 1 byte for the mki length * + the actual mki length * Check we have enough room in the output buffer */ if ((size_t) (end - buf) < mki_len + 9) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); return; } /* extension */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, buf, 0); /* * total length 5 and mki value: only one profile(2 bytes) * and length(2 bytes) and srtp_mki ) */ ext_len = 5 + mki_len; MBEDTLS_PUT_UINT16_BE(ext_len, buf, 2); /* protection profile length: 2 */ buf[4] = 0x00; buf[5] = 0x02; profile_value = mbedtls_ssl_check_srtp_profile_value( ssl->dtls_srtp_info.chosen_dtls_srtp_profile); if (profile_value != MBEDTLS_TLS_SRTP_UNSET) { MBEDTLS_PUT_UINT16_BE(profile_value, buf, 6); } else { MBEDTLS_SSL_DEBUG_MSG(1, ("use_srtp extension invalid profile")); return; } buf[8] = mki_len & 0xFF; memcpy(&buf[9], ssl->dtls_srtp_info.mki_value, mki_len); *olen = 9 + mki_len; } #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = ssl->out_msg + 4; unsigned char *cookie_len_byte; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello verify request")); /* * struct { * ProtocolVersion server_version; * opaque cookie<0..2^8-1>; * } HelloVerifyRequest; */ /* The RFC is not clear on this point, but sending the actual negotiated * version looks like the most interoperable thing to do. */ mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version); MBEDTLS_SSL_DEBUG_BUF(3, "server version", p, 2); p += 2; /* If we get here, f_cookie_check is not null */ if (ssl->conf->f_cookie_write == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("inconsistent cookie callbacks")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Skip length byte until we know the length */ cookie_len_byte = p++; if ((ret = ssl->conf->f_cookie_write(ssl->conf->p_cookie, &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, ssl->cli_id, ssl->cli_id_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_cookie_write", ret); return ret; } *cookie_len_byte = (unsigned char) (p - (cookie_len_byte + 1)); MBEDTLS_SSL_DEBUG_BUF(3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte); ssl->out_msglen = (size_t) (p - ssl->out_msg); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); return ret; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello verify request")); return 0; } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ static void ssl_handle_id_based_session_resumption(mbedtls_ssl_context *ssl) { int ret; mbedtls_ssl_session session_tmp; mbedtls_ssl_session * const session = ssl->session_negotiate; /* Resume is 0 by default, see ssl_handshake_init(). * It may be already set to 1 by ssl_parse_session_ticket_ext(). */ if (ssl->handshake->resume == 1) { return; } if (session->id_len == 0) { return; } if (ssl->conf->f_get_cache == NULL) { return; } #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { return; } #endif mbedtls_ssl_session_init(&session_tmp); ret = ssl->conf->f_get_cache(ssl->conf->p_cache, session->id, session->id_len, &session_tmp); if (ret != 0) { goto exit; } if (session->ciphersuite != session_tmp.ciphersuite) { /* Mismatch between cached and negotiated session */ goto exit; } /* Move semantics */ mbedtls_ssl_session_free(session); *session = session_tmp; memset(&session_tmp, 0, sizeof(session_tmp)); MBEDTLS_SSL_DEBUG_MSG(3, ("session successfully restored from cache")); ssl->handshake->resume = 1; exit: mbedtls_ssl_session_free(&session_tmp); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_server_hello(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t t; #endif int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen, ext_len = 0, n; unsigned char *buf, *p; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello")); #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->cookie_verify_result != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("client hello was not authenticated")); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello")); return ssl_write_hello_verify_request(ssl); } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ /* * 0 . 0 handshake type * 1 . 3 handshake length * 4 . 5 protocol version * 6 . 9 UNIX time() * 10 . 37 random bytes */ buf = ssl->out_msg; p = buf + 4; mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version); p += 2; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen version: [%d:%d]", buf[4], buf[5])); #if defined(MBEDTLS_HAVE_TIME) t = mbedtls_time(NULL); MBEDTLS_PUT_UINT32_BE(t, p, 0); p += 4; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, current time: %" MBEDTLS_PRINTF_LONGLONG, (long long) t)); #else if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 4)) != 0) { return ret; } p += 4; #endif /* MBEDTLS_HAVE_TIME */ if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 20)) != 0) { return ret; } p += 20; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* * RFC 8446 * TLS 1.3 has a downgrade protection mechanism embedded in the server's * random value. TLS 1.3 servers which negotiate TLS 1.2 or below in * response to a ClientHello MUST set the last 8 bytes of their Random * value specially in their ServerHello. */ if (mbedtls_ssl_conf_is_tls13_enabled(ssl->conf)) { static const unsigned char magic_tls12_downgrade_string[] = { 'D', 'O', 'W', 'N', 'G', 'R', 'D', 1 }; MBEDTLS_STATIC_ASSERT( sizeof(magic_tls12_downgrade_string) == 8, "magic_tls12_downgrade_string does not have the expected size"); memcpy(p, magic_tls12_downgrade_string, sizeof(magic_tls12_downgrade_string)); } else #endif { if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 8)) != 0) { return ret; } } p += 8; memcpy(ssl->handshake->randbytes + 32, buf + 6, 32); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", buf + 6, 32); ssl_handle_id_based_session_resumption(ssl); if (ssl->handshake->resume == 0) { /* * New session, create a new session id, * unless we're about to issue a session ticket */ ssl->state++; #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl->handshake->new_session_ticket != 0) { ssl->session_negotiate->id_len = n = 0; memset(ssl->session_negotiate->id, 0, 32); } else #endif /* MBEDTLS_SSL_SESSION_TICKETS */ { ssl->session_negotiate->id_len = n = 32; if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, ssl->session_negotiate->id, n)) != 0) { return ret; } } } else { /* * Resuming a session */ n = ssl->session_negotiate->id_len; ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); return ret; } } /* * 38 . 38 session id length * 39 . 38+n session id * 39+n . 40+n chosen ciphersuite * 41+n . 41+n chosen compression alg. * 42+n . 43+n extensions length * 44+n . 43+n+m extensions */ *p++ = (unsigned char) ssl->session_negotiate->id_len; memcpy(p, ssl->session_negotiate->id, ssl->session_negotiate->id_len); p += ssl->session_negotiate->id_len; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n)); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, session id", buf + 39, n); MBEDTLS_SSL_DEBUG_MSG(3, ("%s session has been resumed", ssl->handshake->resume ? "a" : "no")); MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0); p += 2; *p++ = MBEDTLS_BYTE_0(MBEDTLS_SSL_COMPRESS_NULL); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %s", mbedtls_ssl_get_ciphersuite_name(ssl->session_negotiate->ciphersuite))); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, compress alg.: 0x%02X", (unsigned int) MBEDTLS_SSL_COMPRESS_NULL)); /* * First write extensions, then the total length */ ssl_write_renegotiation_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) ssl_write_max_fragment_length_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl_write_cid_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) ssl_write_encrypt_then_mac_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) ssl_write_extended_ms_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) ssl_write_session_ticket_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) const mbedtls_ssl_ciphersuite_t *suite = mbedtls_ssl_ciphersuite_from_id(ssl->session_negotiate->ciphersuite); if (suite != NULL && mbedtls_ssl_ciphersuite_uses_ec(suite)) { ssl_write_supported_point_formats_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_ALPN) unsigned char *end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN - 4; if ((ret = mbedtls_ssl_write_alpn_ext(ssl, p + 2 + ext_len, end, &olen)) != 0) { return ret; } ext_len += olen; #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) ssl_write_use_srtp_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len)); if (ext_len > 0) { MBEDTLS_PUT_UINT16_BE(ext_len, p, 0); p += 2 + ext_len; } ssl->out_msglen = (size_t) (p - buf); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; ret = mbedtls_ssl_write_handshake_msg(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello")); return ret; } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; uint16_t dn_size, total_dn_size; /* excluding length bytes */ size_t ct_len, sa_len; /* including length bytes */ unsigned char *buf, *p; const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; const mbedtls_x509_crt *crt; int authmode; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request")); ssl->state++; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) { authmode = ssl->handshake->sni_authmode; } else #endif authmode = ssl->conf->authmode; if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info) || authmode == MBEDTLS_SSL_VERIFY_NONE) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request")); return 0; } /* * 0 . 0 handshake type * 1 . 3 handshake length * 4 . 4 cert type count * 5 .. m-1 cert types * m .. m+1 sig alg length (TLS 1.2 only) * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) * n .. n+1 length of all DNs * n+2 .. n+3 length of DN 1 * n+4 .. ... Distinguished Name #1 * ... .. ... length of DN 2, etc. */ buf = ssl->out_msg; p = buf + 4; /* * Supported certificate types * * ClientCertificateType certificate_types<1..2^8-1>; * enum { (255) } ClientCertificateType; */ ct_len = 0; #if defined(MBEDTLS_RSA_C) p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; #endif p[0] = (unsigned char) ct_len++; p += ct_len; sa_len = 0; /* * Add signature_algorithms for verify (TLS 1.2) * * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; * * struct { * HashAlgorithm hash; * SignatureAlgorithm signature; * } SignatureAndHashAlgorithm; * * enum { (255) } HashAlgorithm; * enum { (255) } SignatureAlgorithm; */ const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); if (sig_alg == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { unsigned char hash = MBEDTLS_BYTE_1(*sig_alg); if (mbedtls_ssl_set_calc_verify_md(ssl, hash)) { continue; } if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) { continue; } /* Write elements at offsets starting from 1 (offset 0 is for the * length). Thus the offset of each element is the length of the * partial list including that element. */ sa_len += 2; MBEDTLS_PUT_UINT16_BE(*sig_alg, p, sa_len); } /* Fill in list length. */ MBEDTLS_PUT_UINT16_BE(sa_len, p, 0); sa_len += 2; p += sa_len; /* * DistinguishedName certificate_authorities<0..2^16-1>; * opaque DistinguishedName<1..2^16-1>; */ p += 2; total_dn_size = 0; if (ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED) { /* NOTE: If trusted certificates are provisioned * via a CA callback (configured through * `mbedtls_ssl_conf_ca_cb()`, then the * CertificateRequest is currently left empty. */ #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->dn_hints != NULL) { crt = ssl->handshake->dn_hints; } else #endif if (ssl->conf->dn_hints != NULL) { crt = ssl->conf->dn_hints; } else #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_ca_chain != NULL) { crt = ssl->handshake->sni_ca_chain; } else #endif crt = ssl->conf->ca_chain; while (crt != NULL && crt->version != 0) { /* It follows from RFC 5280 A.1 that this length * can be represented in at most 11 bits. */ dn_size = (uint16_t) crt->subject_raw.len; if (end < p || (size_t) (end - p) < 2 + (size_t) dn_size) { MBEDTLS_SSL_DEBUG_MSG(1, ("skipping CAs: buffer too short")); break; } MBEDTLS_PUT_UINT16_BE(dn_size, p, 0); p += 2; memcpy(p, crt->subject_raw.p, dn_size); p += dn_size; MBEDTLS_SSL_DEBUG_BUF(3, "requested DN", p - dn_size, dn_size); total_dn_size += (unsigned short) (2 + dn_size); crt = crt->next; } } ssl->out_msglen = (size_t) (p - buf); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; MBEDTLS_PUT_UINT16_BE(total_dn_size, ssl->out_msg, 4 + ct_len + sa_len); ret = mbedtls_ssl_write_handshake_msg(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request")); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if (defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)) #if defined(MBEDTLS_USE_PSA_CRYPTO) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_pk_context *pk; mbedtls_pk_type_t pk_type; psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; unsigned char buf[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; size_t key_len; #if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) uint16_t tls_id = 0; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; mbedtls_ecp_group_id grp_id; mbedtls_ecp_keypair *key; #endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */ pk = mbedtls_ssl_own_key(ssl); if (pk == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } pk_type = mbedtls_pk_get_type(pk); switch (pk_type) { case MBEDTLS_PK_OPAQUE: #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ if (!mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) { return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } /* Get the attributes of the key previously parsed by PK module in * order to extract its type and length (in bits). */ status = psa_get_key_attributes(pk->priv_id, &key_attributes); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } ssl->handshake->xxdh_psa_type = psa_get_key_type(&key_attributes); ssl->handshake->xxdh_psa_bits = psa_get_key_bits(&key_attributes); #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) if (pk_type != MBEDTLS_PK_OPAQUE) { /* PK_ECKEY[_DH] and PK_ECDSA instead as parsed from the PK * module and only have ECDSA capabilities. Since we need * them for ECDH later, we export and then re-import them with * proper flags and algorithm. Of course We also set key's type * and bits that we just got above. */ key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type)); psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits); status = psa_export_key(pk->priv_id, buf, sizeof(buf), &key_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_import_key(&key_attributes, buf, key_len, &ssl->handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } /* Set this key as owned by the TLS library: it will be its duty * to clear it exit. */ ssl->handshake->xxdh_psa_privkey_is_external = 0; ret = 0; break; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ /* Opaque key is created by the user (externally from Mbed TLS) * so we assume it already has the right algorithm and flags * set. Just copy its ID as reference. */ ssl->handshake->xxdh_psa_privkey = pk->priv_id; ssl->handshake->xxdh_psa_privkey_is_external = 1; ret = 0; break; #if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: key = mbedtls_pk_ec_rw(*pk); grp_id = mbedtls_pk_get_ec_group_id(pk); if (grp_id == MBEDTLS_ECP_DP_NONE) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); if (tls_id == 0) { /* This elliptic curve is not supported */ return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* If the above conversion to TLS ID was fine, then also this one will be, so there is no need to check the return value here */ mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type, &ssl->handshake->xxdh_psa_bits); ssl->handshake->xxdh_psa_type = key_type; key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type)); psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits); ret = mbedtls_ecp_write_key_ext(key, &key_len, buf, sizeof(buf)); if (ret != 0) { mbedtls_platform_zeroize(buf, sizeof(buf)); break; } status = psa_import_key(&key_attributes, buf, key_len, &ssl->handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); mbedtls_platform_zeroize(buf, sizeof(buf)); break; } mbedtls_platform_zeroize(buf, sizeof(buf)); ret = 0; break; #endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */ default: ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } exit: psa_reset_key_attributes(&key_attributes); mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } #else /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl); if (private_key == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no server private key")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_ECKEY)) { MBEDTLS_SSL_DEBUG_MSG(1, ("server key not ECDH capable")); return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx, mbedtls_pk_ec_ro(*mbedtls_ssl_own_key(ssl)), MBEDTLS_ECDH_OURS)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret); return ret; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ defined(MBEDTLS_SSL_ASYNC_PRIVATE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_resume_server_key_exchange(mbedtls_ssl_context *ssl, size_t *signature_len) { /* Append the signature to ssl->out_msg, leaving 2 bytes for the * signature length which will be added in ssl_write_server_key_exchange * after the call to ssl_prepare_server_key_exchange. * ssl_write_server_key_exchange also takes care of incrementing * ssl->out_msglen. */ unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; size_t sig_max_len = (ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN - sig_start); int ret = ssl->conf->f_async_resume(ssl, sig_start, signature_len, sig_max_len); if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { ssl->handshake->async_in_progress = 0; mbedtls_ssl_set_async_operation_data(ssl, NULL); } MBEDTLS_SSL_DEBUG_RET(2, "ssl_resume_server_key_exchange", ret); return ret; } #endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ /* Prepare the ServerKeyExchange message, up to and including * calculating the signature if any, but excluding formatting the * signature and sending the message. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, size_t *signature_len) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) unsigned char *dig_signed = NULL; #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ (void) ciphersuite_info; /* unused in some configurations */ #if !defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) (void) signature_len; #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf); #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf); #endif #endif ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ /* * * Part 1: Provide key exchange parameters for chosen ciphersuite. * */ /* * - ECJPAKE key exchanges */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char *out_p = ssl->out_msg + ssl->out_msglen; unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen; size_t output_offset = 0; size_t output_len = 0; /* * The first 3 bytes are: * [0] MBEDTLS_ECP_TLS_NAMED_CURVE * [1, 2] elliptic curve's TLS ID * * However since we only support secp256r1 for now, we hardcode its * TLS ID here */ uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( MBEDTLS_ECP_DP_SECP256R1); if (tls_id == 0) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } *out_p = MBEDTLS_ECP_TLS_NAMED_CURVE; MBEDTLS_PUT_UINT16_BE(tls_id, out_p, 1); output_offset += 3; ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, out_p + output_offset, end_p - out_p - output_offset, &output_len, MBEDTLS_ECJPAKE_ROUND_TWO); if (ret != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); return ret; } output_offset += output_len; ssl->out_msglen += output_offset; #else size_t len = 0; ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, ssl->out_msg + ssl->out_msglen, MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_two", ret); return ret; } ssl->out_msglen += len; #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ /* * For (EC)DHE key exchanges with PSK, parameters are prefixed by support * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, * we use empty support identity hints here. **/ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { ssl->out_msg[ssl->out_msglen++] = 0x00; ssl->out_msg[ssl->out_msglen++] = 0x00; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ /* * - DHE key exchanges */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_dhe(ciphersuite_info)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; if (ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("no DH parameters set")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * Ephemeral DH parameters: * * struct { * opaque dh_p<1..2^16-1>; * opaque dh_g<1..2^16-1>; * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ if ((ret = mbedtls_dhm_set_group(&ssl->handshake->dhm_ctx, &ssl->conf->dhm_P, &ssl->conf->dhm_G)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_set_group", ret); return ret; } if ((ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), ssl->out_msg + ssl->out_msglen, &len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_params", ret); return ret; } #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) dig_signed = ssl->out_msg + ssl->out_msglen; #endif ssl->out_msglen += len; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: X ", &ssl->handshake->dhm_ctx.X); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: P ", &ssl->handshake->dhm_ctx.P); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: G ", &ssl->handshake->dhm_ctx.G); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GX", &ssl->handshake->dhm_ctx.GX); } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED */ /* * - ECDHE key exchanges */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_ecdhe(ciphersuite_info)) { /* * Ephemeral ECDH parameters: * * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ uint16_t *curr_tls_id = ssl->handshake->curves_tls_id; const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; /* Match our preference list against the offered curves */ if ((group_list == NULL) || (curr_tls_id == NULL)) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *group_list != 0; group_list++) { for (curr_tls_id = ssl->handshake->curves_tls_id; *curr_tls_id != 0; curr_tls_id++) { if (*curr_tls_id == *group_list) { goto curve_matching_done; } } } curve_matching_done: if (*curr_tls_id == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("no matching curve for ECDHE")); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MSG(2, ("ECDHE curve: %s", mbedtls_ssl_get_curve_name_from_tls_id(*curr_tls_id))); #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_GENERIC_ERROR; psa_key_attributes_t key_attributes; mbedtls_ssl_handshake_params *handshake = ssl->handshake; uint8_t *p = ssl->out_msg + ssl->out_msglen; const size_t header_size = 4; // curve_type(1), namedcurve(2), // data length(1) const size_t data_length_size = 1; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; size_t ec_bits = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); /* Convert EC's TLS ID to PSA key type. */ if (mbedtls_ssl_get_psa_curve_info_from_tls_id(*curr_tls_id, &key_type, &ec_bits) == PSA_ERROR_NOT_SUPPORTED) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid ecc group parse.")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } handshake->xxdh_psa_type = key_type; handshake->xxdh_psa_bits = ec_bits; key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); /* * ECParameters curve_params * * First byte is curve_type, always named_curve */ *p++ = MBEDTLS_ECP_TLS_NAMED_CURVE; /* * Next two bytes are the namedcurve value */ MBEDTLS_PUT_UINT16_BE(*curr_tls_id, p, 0); p += 2; /* Generate ECDH private key. */ status = psa_generate_key(&key_attributes, &handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret); return ret; } /* * ECPoint public * * First byte is data length. * It will be filled later. p holds now the data length location. */ /* Export the public part of the ECDH private key from PSA. * Make one byte space for the length. */ unsigned char *own_pubkey = p + data_length_size; size_t own_pubkey_max_len = (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN - (own_pubkey - ssl->out_msg)); status = psa_export_public_key(handshake->xxdh_psa_privkey, own_pubkey, own_pubkey_max_len, &len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret); (void) psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return ret; } /* Store the length of the exported public key. */ *p = (uint8_t) len; /* Determine full message length. */ len += header_size; #else mbedtls_ecp_group_id curr_grp_id = mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id); if ((ret = mbedtls_ecdh_setup(&ssl->handshake->ecdh_ctx, curr_grp_id)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecp_group_load", ret); return ret; } if ((ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, ssl->out_msg + ssl->out_msglen, MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_make_params", ret); return ret; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Q); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) dig_signed = ssl->out_msg + ssl->out_msglen; #endif ssl->out_msglen += len; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ /* * * Part 2: For key exchanges involving the server signing the * exchange parameters, compute and add the signature here. * */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) { if (dig_signed == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } size_t dig_signed_len = (size_t) (ssl->out_msg + ssl->out_msglen - dig_signed); size_t hashlen = 0; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * 2.1: Choose hash algorithm: * For TLS 1.2, obey signature-hash-algorithm extension * to choose appropriate hash. */ mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info); unsigned char sig_hash = (unsigned char) mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg)); mbedtls_md_type_t md_alg = mbedtls_ssl_md_alg_from_hash(sig_hash); /* For TLS 1.2, obey signature-hash-algorithm extension * (RFC 5246, Sec. 7.4.1.4.1). */ if (sig_alg == MBEDTLS_PK_NONE || md_alg == MBEDTLS_MD_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); /* (... because we choose a cipher suite * only if there is a matching hash.) */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("pick hash algorithm %u for signing", (unsigned) md_alg)); /* * 2.2: Compute the hash to be signed */ if (md_alg != MBEDTLS_MD_NONE) { ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen, dig_signed, dig_signed_len, md_alg); if (ret != 0) { return ret; } } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "parameters hash", hash, hashlen); /* * 2.3: Compute and add the signature */ /* * We need to specify signature and hash algorithm explicitly through * a prefix to the signature. * * struct { * HashAlgorithm hash; * SignatureAlgorithm signature; * } SignatureAndHashAlgorithm; * * struct { * SignatureAndHashAlgorithm algorithm; * opaque signature<0..2^16-1>; * } DigitallySigned; * */ ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_hash_from_md_alg(md_alg); ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_sig_from_pk_alg(sig_alg); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ssl->conf->f_async_sign_start != NULL) { ret = ssl->conf->f_async_sign_start(ssl, mbedtls_ssl_own_cert(ssl), md_alg, hash, hashlen); switch (ret) { case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: /* act as if f_async_sign was null */ break; case 0: ssl->handshake->async_in_progress = 1; return ssl_resume_server_key_exchange(ssl, signature_len); case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: ssl->handshake->async_in_progress = 1; return MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS; default: MBEDTLS_SSL_DEBUG_RET(1, "f_async_sign_start", ret); return ret; } } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ if (mbedtls_ssl_own_key(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no private key")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } /* Append the signature to ssl->out_msg, leaving 2 bytes for the * signature length which will be added in ssl_write_server_key_exchange * after the call to ssl_prepare_server_key_exchange. * ssl_write_server_key_exchange also takes care of incrementing * ssl->out_msglen. */ if ((ret = mbedtls_pk_sign(mbedtls_ssl_own_key(ssl), md_alg, hash, hashlen, ssl->out_msg + ssl->out_msglen + 2, out_buf_len - ssl->out_msglen - 2, signature_len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_sign", ret); return ret; } } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ return 0; } /* Prepare the ServerKeyExchange message and send it. For ciphersuites * that do not include a ServerKeyExchange message, do nothing. Either * way, if successful, move on to the next step in the SSL state * machine. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_server_key_exchange(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t signature_len = 0; #if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; #endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server key exchange")); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) /* Extract static ECDH parameters and abort if ServerKeyExchange * is not needed. */ if (mbedtls_ssl_ciphersuite_no_pfs(ciphersuite_info)) { /* For suites involving ECDH, extract DH parameters * from certificate at this point. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) if (mbedtls_ssl_ciphersuite_uses_ecdh(ciphersuite_info)) { ret = ssl_get_ecdh_params_from_cert(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_get_ecdh_params_from_cert", ret); return ret; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ /* Key exchanges not involving ephemeral keys don't use * ServerKeyExchange, so end here. */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write server key exchange")); ssl->state++; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ defined(MBEDTLS_SSL_ASYNC_PRIVATE) /* If we have already prepared the message and there is an ongoing * signature operation, resume signing. */ if (ssl->handshake->async_in_progress != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("resuming signature operation")); ret = ssl_resume_server_key_exchange(ssl, &signature_len); } else #endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ { /* ServerKeyExchange is needed. Prepare the message. */ ret = ssl_prepare_server_key_exchange(ssl, &signature_len); } if (ret != 0) { /* If we're starting to write a new message, set ssl->out_msglen * to 0. But if we're resuming after an asynchronous message, * out_msglen is the amount of data written so far and mst be * preserved. */ if (ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server key exchange (pending)")); } else { ssl->out_msglen = 0; } return ret; } /* If there is a signature, write its length. * ssl_prepare_server_key_exchange already wrote the signature * itself at its proper place in the output buffer. */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if (signature_len != 0) { ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_1(signature_len); ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_0(signature_len); MBEDTLS_SSL_DEBUG_BUF(3, "my signature", ssl->out_msg + ssl->out_msglen, signature_len); /* Skip over the already-written signature */ ssl->out_msglen += signature_len; } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ /* Add header and send. */ ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server key exchange")); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_server_hello_done(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello done")); ssl->out_msglen = 4; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; ssl->state++; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_send_flight_completed(ssl); } #endif if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); return ret; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello done")); return 0; } #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_dh_public(mbedtls_ssl_context *ssl, unsigned char **p, const unsigned char *end) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t n; /* * Receive G^Y mod P, premaster = (G^Y)^X mod P */ if (*p + 2 > end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } n = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; if (*p + n > end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if ((ret = mbedtls_dhm_read_public(&ssl->handshake->dhm_ctx, *p, n)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_read_public", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } *p += n; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GY", &ssl->handshake->dhm_ctx.GY); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_resume_decrypt_pms(mbedtls_ssl_context *ssl, unsigned char *peer_pms, size_t *peer_pmslen, size_t peer_pmssize) { int ret = ssl->conf->f_async_resume(ssl, peer_pms, peer_pmslen, peer_pmssize); if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { ssl->handshake->async_in_progress = 0; mbedtls_ssl_set_async_operation_data(ssl, NULL); } MBEDTLS_SSL_DEBUG_RET(2, "ssl_decrypt_encrypted_pms", ret); return ret; } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_decrypt_encrypted_pms(mbedtls_ssl_context *ssl, const unsigned char *p, const unsigned char *end, unsigned char *peer_pms, size_t *peer_pmslen, size_t peer_pmssize) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *own_cert = mbedtls_ssl_own_cert(ssl); if (own_cert == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no local certificate")); return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; } mbedtls_pk_context *public_key = &own_cert->pk; mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl); size_t len = mbedtls_pk_get_len(public_key); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) /* If we have already started decoding the message and there is an ongoing * decryption operation, resume signing. */ if (ssl->handshake->async_in_progress != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("resuming decryption operation")); return ssl_resume_decrypt_pms(ssl, peer_pms, peer_pmslen, peer_pmssize); } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ /* * Prepare to decrypt the premaster using own private RSA key */ if (p + 2 > end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (*p++ != MBEDTLS_BYTE_1(len) || *p++ != MBEDTLS_BYTE_0(len)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (p + len != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Decrypt the premaster secret */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ssl->conf->f_async_decrypt_start != NULL) { ret = ssl->conf->f_async_decrypt_start(ssl, mbedtls_ssl_own_cert(ssl), p, len); switch (ret) { case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: /* act as if f_async_decrypt_start was null */ break; case 0: ssl->handshake->async_in_progress = 1; return ssl_resume_decrypt_pms(ssl, peer_pms, peer_pmslen, peer_pmssize); case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: ssl->handshake->async_in_progress = 1; return MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS; default: MBEDTLS_SSL_DEBUG_RET(1, "f_async_decrypt_start", ret); return ret; } } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_RSA)) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no RSA private key")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } ret = mbedtls_pk_decrypt(private_key, p, len, peer_pms, peer_pmslen, peer_pmssize, ssl->conf->f_rng, ssl->conf->p_rng); return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl, const unsigned char *p, const unsigned char *end, size_t pms_offset) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *pms = ssl->handshake->premaster + pms_offset; unsigned char ver[2]; unsigned char fake_pms[48], peer_pms[48]; size_t peer_pmslen; mbedtls_ct_condition_t diff; /* In case of a failure in decryption, the decryption may write less than * 2 bytes of output, but we always read the first two bytes. It doesn't * matter in the end because diff will be nonzero in that case due to * ret being nonzero, and we only care whether diff is 0. * But do initialize peer_pms and peer_pmslen for robustness anyway. This * also makes memory analyzers happy (don't access uninitialized memory, * even if it's an unsigned char). */ peer_pms[0] = peer_pms[1] = ~0; peer_pmslen = 0; ret = ssl_decrypt_encrypted_pms(ssl, p, end, peer_pms, &peer_pmslen, sizeof(peer_pms)); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { return ret; } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ mbedtls_ssl_write_version(ver, ssl->conf->transport, ssl->session_negotiate->tls_version); /* Avoid data-dependent branches while checking for invalid * padding, to protect against timing-based Bleichenbacher-type * attacks. */ diff = mbedtls_ct_bool(ret); diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pmslen, 48)); diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[0], ver[0])); diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[1], ver[1])); /* * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding * must not cause the connection to end immediately; instead, send a * bad_record_mac later in the handshake. * To protect against timing-based variants of the attack, we must * not have any branch that depends on whether the decryption was * successful. In particular, always generate the fake premaster secret, * regardless of whether it will ultimately influence the output or not. */ ret = ssl->conf->f_rng(ssl->conf->p_rng, fake_pms, sizeof(fake_pms)); if (ret != 0) { /* It's ok to abort on an RNG failure, since this does not reveal * anything about the RSA decryption. */ return ret; } #if defined(MBEDTLS_SSL_DEBUG_ALL) if (diff != MBEDTLS_CT_FALSE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); } #endif if (sizeof(ssl->handshake->premaster) < pms_offset || sizeof(ssl->handshake->premaster) - pms_offset < 48) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->handshake->pmslen = 48; /* Set pms to either the true or the fake PMS, without * data-dependent branches. */ mbedtls_ct_memcpy_if(diff, pms, fake_pms, peer_pms, ssl->handshake->pmslen); return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_psk_identity(mbedtls_ssl_context *ssl, unsigned char **p, const unsigned char *end) { int ret = 0; uint16_t n; if (ssl_conf_has_psk_or_cb(ssl->conf) == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no pre-shared key")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } /* * Receive client pre-shared key identity name */ if (end - *p < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } n = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; if (n == 0 || n > end - *p) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (ssl->conf->f_psk != NULL) { if (ssl->conf->f_psk(ssl->conf->p_psk, ssl, *p, n) != 0) { ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; } } else { /* Identity is not a big secret since clients send it in the clear, * but treat it carefully anyway, just in case */ if (n != ssl->conf->psk_identity_len || mbedtls_ct_memcmp(ssl->conf->psk_identity, *p, n) != 0) { ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; } } if (ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) { MBEDTLS_SSL_DEBUG_BUF(3, "Unknown PSK identity", *p, n); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY); return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; } *p += n; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; unsigned char *p, *end; ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client key exchange")); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ (defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)) if ((ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) && (ssl->handshake->async_in_progress != 0)) { /* We've already read a record and there is an asynchronous * operation in progress to decrypt it. So skip reading the * record. */ MBEDTLS_SSL_DEBUG_MSG(3, ("will resume decryption of previously-read record")); } else #endif if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); end = ssl->in_msg + ssl->in_hslen; if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA) { if ((ret = ssl_parse_client_dh_public(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_dh_public"), ret); return ret; } if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, ssl->handshake->premaster, MBEDTLS_PREMASTER_SIZE, &ssl->handshake->pmslen, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) { #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t data_len = (size_t) (*p++); size_t buf_len = (size_t) (end - p); psa_status_t status = PSA_ERROR_GENERIC_ERROR; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_DEBUG_MSG(3, ("Read the peer's public key.")); /* * We must have at least two bytes (1 for length, at least 1 for data) */ if (buf_len < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid buffer length: %" MBEDTLS_PRINTF_SIZET, buf_len)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } if (data_len < 1 || data_len > buf_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid data length: %" MBEDTLS_PRINTF_SIZET " > %" MBEDTLS_PRINTF_SIZET, data_len, buf_len)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* Store peer's ECDH public key. */ if (data_len > sizeof(handshake->xxdh_psa_peerkey)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %" MBEDTLS_PRINTF_SIZET " > %" MBEDTLS_PRINTF_SIZET, data_len, sizeof(handshake->xxdh_psa_peerkey))); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } memcpy(handshake->xxdh_psa_peerkey, p, data_len); handshake->xxdh_psa_peerkey_len = data_len; /* Compute ECDH shared secret. */ status = psa_raw_key_agreement( PSA_ALG_ECDH, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, handshake->premaster, sizeof(handshake->premaster), &handshake->pmslen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret); if (handshake->xxdh_psa_privkey_is_external == 0) { (void) psa_destroy_key(handshake->xxdh_psa_privkey); } handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return ret; } if (handshake->xxdh_psa_privkey_is_external == 0) { status = psa_destroy_key(handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); return ret; } } handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; #else if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx, p, (size_t) (end - p))) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_QP); if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, ssl->handshake->premaster, MBEDTLS_MPI_MAX_SIZE, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Z); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK) { if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); return ret; } if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ssl->handshake->async_in_progress != 0) { /* There is an asynchronous operation in progress to * decrypt the encrypted premaster secret, so skip * directly to resuming this operation. */ MBEDTLS_SSL_DEBUG_MSG(3, ("PSK identity already parsed")); /* Update p to skip the PSK identity. ssl_parse_encrypted_pms * won't actually use it, but maintain p anyway for robustness. */ p += ssl->conf->psk_identity_len + 2; } else #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); return ret; } if ((ret = ssl_parse_encrypted_pms(ssl, p, end, 2)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_encrypted_pms"), ret); return ret; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); return ret; } if ((ret = ssl_parse_client_dh_public(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_dh_public"), ret); return ret; } if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } #if defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char *pms = ssl->handshake->premaster; unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster); size_t pms_len; /* Write length only when we know the actual value */ if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, pms + 2, pms_end - (pms + 2), &pms_len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return ret; } MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0); pms += 2 + pms_len; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); #else if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; size_t ecpoint_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return ret; } /* Keep a copy of the peer's public key */ if (p >= end) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return MBEDTLS_ERR_SSL_DECODE_ERROR; } ecpoint_len = *(p++); if ((size_t) (end - p) < ecpoint_len) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* When FFDH is enabled, the array handshake->xxdh_psa_peer_key size takes into account the sizes of the FFDH keys which are at least 2048 bits. The size of the array is thus greater than 256 bytes which is greater than any possible value of ecpoint_len (type uint8_t) and the check below can be skipped.*/ #if !defined(PSA_WANT_ALG_FFDH) if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #else MBEDTLS_STATIC_ASSERT(sizeof(handshake->xxdh_psa_peerkey) >= UINT8_MAX, "peer key buffer too small"); #endif memcpy(handshake->xxdh_psa_peerkey, p, ecpoint_len); handshake->xxdh_psa_peerkey_len = ecpoint_len; p += ecpoint_len; /* As RFC 5489 section 2, the premaster secret is formed as follows: * - a uint16 containing the length (in octets) of the ECDH computation * - the octet string produced by the ECDH computation * - a uint16 containing the length (in octets) of the PSK * - the PSK itself */ unsigned char *psm = ssl->handshake->premaster; const unsigned char * const psm_end = psm + sizeof(ssl->handshake->premaster); /* uint16 to store length (in octets) of the ECDH computation */ const size_t zlen_size = 2; size_t zlen = 0; /* Compute ECDH shared secret. */ status = psa_raw_key_agreement(PSA_ALG_ECDH, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, psm + zlen_size, psm_end - (psm + zlen_size), &zlen); destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } else if (destruction_status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(destruction_status); } /* Write the ECDH computation length before the ECDH computation */ MBEDTLS_PUT_UINT16_BE(zlen, psm, 0); psm += zlen_size + zlen; #else /* MBEDTLS_USE_PSA_CRYPTO */ if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); return ret; } if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx, p, (size_t) (end - p))) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_QP); if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) { if ((ret = ssl_parse_encrypted_pms(ssl, p, end, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_parse_encrypted_pms_secret"), ret); return ret; } } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_psa_ecjpake_read_round( &ssl->handshake->psa_pake_ctx, p, (size_t) (end - p), MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret); return ret; } #else ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx, p, (size_t) (end - p)); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_two", ret); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ret = mbedtls_ecjpake_derive_secret(&ssl->handshake->ecjpake_ctx, ssl->handshake->premaster, 32, &ssl->handshake->pmslen, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_derive_secret", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); return ret; } ssl->state++; MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client key exchange")); return 0; } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t i, sig_len; unsigned char hash[48]; unsigned char *hash_start = hash; size_t hashlen; mbedtls_pk_type_t pk_alg; mbedtls_md_type_t md_alg; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; mbedtls_pk_context *peer_pk; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); ssl->state++; return 0; } #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if (ssl->session_negotiate->peer_cert == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); ssl->state++; return 0; } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert_digest == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); ssl->state++; return 0; } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* Read the message without adding it to the checksum */ ret = mbedtls_ssl_read_record(ssl, 0 /* no checksum update */); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_read_record"), ret); return ret; } ssl->state++; /* Process the message contents */ if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } i = mbedtls_ssl_hs_hdr_len(ssl); #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert == NULL) { /* Should never happen */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } peer_pk = &ssl->session_negotiate->peer_cert->pk; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* * struct { * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only * opaque signature<0..2^16-1>; * } DigitallySigned; */ if (i + 2 > ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Hash */ md_alg = mbedtls_ssl_md_alg_from_hash(ssl->in_msg[i]); if (md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md(ssl, ssl->in_msg[i])) { MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg" " for verify message")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if !defined(MBEDTLS_MD_SHA1) if (MBEDTLS_MD_SHA1 == md_alg) { hash_start += 16; } #endif /* Info from md_alg will be used instead */ hashlen = 0; i++; /* * Signature */ if ((pk_alg = mbedtls_ssl_pk_alg_from_sig(ssl->in_msg[i])) == MBEDTLS_PK_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg" " for verify message")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* * Check the certificate's key type matches the signature alg */ if (!mbedtls_pk_can_do(peer_pk, pk_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("sig_alg doesn't match cert key")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } i++; if (i + 2 > ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } sig_len = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i); i += 2; if (i + sig_len != ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Calculate hash and verify signature */ { size_t dummy_hlen; ret = ssl->handshake->calc_verify(ssl, hash, &dummy_hlen); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret); return ret; } } if ((ret = mbedtls_pk_verify(peer_pk, md_alg, hash_start, hashlen, ssl->in_msg + i, sig_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify", ret); return ret; } ret = mbedtls_ssl_update_handshake_status(ssl); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify")); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t tlen; uint32_t lifetime; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write new session ticket")); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; /* * struct { * uint32 ticket_lifetime_hint; * opaque ticket<0..2^16-1>; * } NewSessionTicket; * * 4 . 7 ticket_lifetime_hint (0 = unspecified) * 8 . 9 ticket_len (n) * 10 . 9+n ticket content */ #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->ticket_creation_time = mbedtls_ms_time(); #endif if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket, ssl->session_negotiate, ssl->out_msg + 10, ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, &tlen, &lifetime)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_write", ret); tlen = 0; } MBEDTLS_PUT_UINT32_BE(lifetime, ssl->out_msg, 4); MBEDTLS_PUT_UINT16_BE(tlen, ssl->out_msg, 8); ssl->out_msglen = 10 + tlen; /* * Morally equivalent to updating ssl->state, but NewSessionTicket and * ChangeCipherSpec share the same state. */ ssl->handshake->new_session_ticket = 0; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket")); return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * SSL handshake -- server side -- single step */ int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl) { int ret = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("server state: %d", ssl->state)); switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: ssl->state = MBEDTLS_SSL_CLIENT_HELLO; break; /* * <== ClientHello */ case MBEDTLS_SSL_CLIENT_HELLO: ret = ssl_parse_client_hello(ssl); break; #if defined(MBEDTLS_SSL_PROTO_DTLS) case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED; #endif /* * ==> ServerHello * Certificate * ( ServerKeyExchange ) * ( CertificateRequest ) * ServerHelloDone */ case MBEDTLS_SSL_SERVER_HELLO: ret = ssl_write_server_hello(ssl); break; case MBEDTLS_SSL_SERVER_CERTIFICATE: ret = mbedtls_ssl_write_certificate(ssl); break; case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: ret = ssl_write_server_key_exchange(ssl); break; case MBEDTLS_SSL_CERTIFICATE_REQUEST: ret = ssl_write_certificate_request(ssl); break; case MBEDTLS_SSL_SERVER_HELLO_DONE: ret = ssl_write_server_hello_done(ssl); break; /* * <== ( Certificate/Alert ) * ClientKeyExchange * ( CertificateVerify ) * ChangeCipherSpec * Finished */ case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = mbedtls_ssl_parse_certificate(ssl); break; case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: ret = ssl_parse_client_key_exchange(ssl); break; case MBEDTLS_SSL_CERTIFICATE_VERIFY: ret = ssl_parse_certificate_verify(ssl); break; case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: ret = mbedtls_ssl_parse_change_cipher_spec(ssl); break; case MBEDTLS_SSL_CLIENT_FINISHED: ret = mbedtls_ssl_parse_finished(ssl); break; /* * ==> ( NewSessionTicket ) * ChangeCipherSpec * Finished */ case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl->handshake->new_session_ticket != 0) { ret = ssl_write_new_session_ticket(ssl); } else #endif ret = mbedtls_ssl_write_change_cipher_spec(ssl); break; case MBEDTLS_SSL_SERVER_FINISHED: ret = mbedtls_ssl_write_finished(ssl); break; case MBEDTLS_SSL_FLUSH_BUFFERS: MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: mbedtls_ssl_handshake_wrapup(ssl); break; default: MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return ret; } void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order) { conf->respect_cli_pref = order; } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_2 */ webfakes/src/mbedtls/library/constant_time_internal.h0000644000176200001440000005037714740737024022666 0ustar liggesusers/** * Constant-time functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H #define MBEDTLS_CONSTANT_TIME_INTERNAL_H #include #include #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif /* The constant-time interface provides various operations that are likely * to result in constant-time code that does not branch or use conditional * instructions for secret data (for secret pointers, this also applies to * the data pointed to). * * It has three main parts: * * - boolean operations * These are all named mbedtls_ct__. * They operate over and return mbedtls_ct_condition_t. * All arguments are considered secret. * example: bool x = y | z => x = mbedtls_ct_bool_or(y, z) * example: bool x = y == z => x = mbedtls_ct_uint_eq(y, z) * * - conditional data selection * These are all named mbedtls_ct__if and mbedtls_ct__if_else_0 * All arguments are considered secret. * example: size_t a = x ? b : c => a = mbedtls_ct_size_if(x, b, c) * example: unsigned a = x ? b : 0 => a = mbedtls_ct_uint_if_else_0(x, b) * * - block memory operations * Only some arguments are considered secret, as documented for each * function. * example: if (x) memcpy(...) => mbedtls_ct_memcpy_if(x, ...) * * mbedtls_ct_condition_t must be treated as opaque and only created and * manipulated via the functions in this header. The compiler should never * be able to prove anything about its value at compile-time. * * mbedtls_ct_uint_t is an unsigned integer type over which constant time * operations may be performed via the functions in this header. It is as big * as the larger of size_t and mbedtls_mpi_uint, i.e. it is safe to cast * to/from "unsigned int", "size_t", and "mbedtls_mpi_uint" (and any other * not-larger integer types). * * For Arm (32-bit, 64-bit and Thumb), x86 and x86-64, assembly implementations * are used to ensure that the generated code is constant time. For other * architectures, it uses a plain C fallback designed to yield constant-time code * (this has been observed to be constant-time on latest gcc, clang and MSVC * as of May 2023). * * For readability, the static inline definitions are separated out into * constant_time_impl.h. */ #if (SIZE_MAX > 0xffffffffffffffffULL) /* Pointer size > 64-bit */ typedef size_t mbedtls_ct_condition_t; typedef size_t mbedtls_ct_uint_t; typedef ptrdiff_t mbedtls_ct_int_t; #define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(SIZE_MAX)) #elif (SIZE_MAX > 0xffffffff) || defined(MBEDTLS_HAVE_INT64) /* 32-bit < pointer size <= 64-bit, or 64-bit MPI */ typedef uint64_t mbedtls_ct_condition_t; typedef uint64_t mbedtls_ct_uint_t; typedef int64_t mbedtls_ct_int_t; #define MBEDTLS_CT_SIZE_64 #define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT64_MAX)) #else /* Pointer size <= 32-bit, and no 64-bit MPIs */ typedef uint32_t mbedtls_ct_condition_t; typedef uint32_t mbedtls_ct_uint_t; typedef int32_t mbedtls_ct_int_t; #define MBEDTLS_CT_SIZE_32 #define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT32_MAX)) #endif #define MBEDTLS_CT_FALSE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(0)) /* ============================================================================ * Boolean operations */ /** Convert a number into a mbedtls_ct_condition_t. * * \param x Number to convert. * * \return MBEDTLS_CT_TRUE if \p x != 0, or MBEDTLS_CT_FALSE if \p x == 0 * */ static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x); /** Boolean "not equal" operation. * * Functionally equivalent to: * * \p x != \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x != \p y, otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "equals" operation. * * Functionally equivalent to: * * \p x == \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x == \p y, otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "less than" operation. * * Functionally equivalent to: * * \p x < \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x < \p y, otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "greater than" operation. * * Functionally equivalent to: * * \p x > \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x > \p y, otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "greater or equal" operation. * * Functionally equivalent to: * * \p x >= \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x >= \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "less than or equal" operation. * * Functionally equivalent to: * * \p x <= \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x <= \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean not-equals operation. * * Functionally equivalent to: * * \p x != \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \note This is more efficient than mbedtls_ct_uint_ne if both arguments are * mbedtls_ct_condition_t. * * \return MBEDTLS_CT_TRUE if \p x != \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y); /** Boolean "and" operation. * * Functionally equivalent to: * * \p x && \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x && \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y); /** Boolean "or" operation. * * Functionally equivalent to: * * \p x || \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x || \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y); /** Boolean "not" operation. * * Functionally equivalent to: * * ! \p x * * \param x The value to invert * * \return MBEDTLS_CT_FALSE if \p x, otherwise MBEDTLS_CT_TRUE. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x); /* ============================================================================ * Data selection operations */ /** Choose between two size_t values. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition, size_t if1, size_t if0); /** Choose between two unsigned values. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition, unsigned if1, unsigned if0); /** Choose between two mbedtls_ct_condition_t values. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition, mbedtls_ct_condition_t if1, mbedtls_ct_condition_t if0); #if defined(MBEDTLS_BIGNUM_C) /** Choose between two mbedtls_mpi_uint values. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, \ mbedtls_mpi_uint if1, \ mbedtls_mpi_uint if0); #endif /** Choose between an unsigned value and 0. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_uint_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1); /** Choose between an mbedtls_ct_condition_t and 0. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_bool_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition, mbedtls_ct_condition_t if1); /** Choose between a size_t value and 0. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_size_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1); #if defined(MBEDTLS_BIGNUM_C) /** Choose between an mbedtls_mpi_uint value and 0. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_mpi_uint_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition, mbedtls_mpi_uint if1); #endif /** Constant-flow char selection * * \param low Secret. Bottom of range * \param high Secret. Top of range * \param c Secret. Value to compare to range * \param t Secret. Value to return, if in range * * \return \p t if \p low <= \p c <= \p high, 0 otherwise. */ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, unsigned char high, unsigned char c, unsigned char t); /** Choose between two error values. The values must be in the range [-32767..0]. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0); /** Choose between an error value and 0. The error value must be in the range [-32767..0]. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1); /* ============================================================================ * Block memory operations */ #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) /** Conditionally set a block of memory to zero. * * Regardless of the condition, every byte will be read once and written to * once. * * \param condition Secret. Condition to test. * \param buf Secret. Pointer to the start of the buffer. * \param len Number of bytes to set to zero. * * \warning Unlike mbedtls_platform_zeroize, this does not have the same guarantees * about not being optimised away if the memory is never read again. */ void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len); /** Shift some data towards the left inside a buffer. * * Functionally equivalent to: * * memmove(start, start + offset, total - offset); * memset(start + (total - offset), 0, offset); * * Timing independence comes at the expense of performance. * * \param start Secret. Pointer to the start of the buffer. * \param total Total size of the buffer. * \param offset Secret. Offset from which to copy \p total - \p offset bytes. */ void mbedtls_ct_memmove_left(void *start, size_t total, size_t offset); #endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */ /** Conditional memcpy. * * Functionally equivalent to: * * if (condition) { * memcpy(dest, src1, len); * } else { * if (src2 != NULL) * memcpy(dest, src2, len); * } * * It will always read len bytes from src1. * If src2 != NULL, it will always read len bytes from src2. * If src2 == NULL, it will instead read len bytes from dest (as if src2 == dest). * * \param condition The condition * \param dest Secret. Destination pointer. * \param src1 Secret. Pointer to copy from (if \p condition == MBEDTLS_CT_TRUE). * This may be equal to \p dest, but may not overlap in other ways. * \param src2 Secret (contents only - may branch to determine if this parameter is NULL). * Pointer to copy from (if \p condition == MBEDTLS_CT_FALSE and \p src2 is not NULL). May be NULL. * This may be equal to \p dest, but may not overlap it in other ways. It may overlap with \p src1. * \param len Number of bytes to copy. */ void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition, unsigned char *dest, const unsigned char *src1, const unsigned char *src2, size_t len ); /** Copy data from a secret position. * * Functionally equivalent to: * * memcpy(dst, src + offset, len) * * This function copies \p len bytes from \p src + \p offset to * \p dst, with a code flow and memory access pattern that does not depend on * \p offset, but only on \p offset_min, \p offset_max and \p len. * * \note This function reads from \p dest, but the value that * is read does not influence the result and this * function's behavior is well-defined regardless of the * contents of the buffers. This may result in false * positives from static or dynamic analyzers, especially * if \p dest is not initialized. * * \param dest Secret. The destination buffer. This must point to a writable * buffer of at least \p len bytes. * \param src Secret. The base of the source buffer. This must point to a * readable buffer of at least \p offset_max + \p len * bytes. Shouldn't overlap with \p dest * \param offset Secret. The offset in the source buffer from which to copy. * This must be no less than \p offset_min and no greater * than \p offset_max. * \param offset_min The minimal value of \p offset. * \param offset_max The maximal value of \p offset. * \param len The number of bytes to copy. */ void mbedtls_ct_memcpy_offset(unsigned char *dest, const unsigned char *src, size_t offset, size_t offset_min, size_t offset_max, size_t len); /* Documented in include/mbedtls/constant_time.h. a and b are secret. int mbedtls_ct_memcmp(const void *a, const void *b, size_t n); */ #if defined(MBEDTLS_NIST_KW_C) /** Constant-time buffer comparison without branches. * * Similar to mbedtls_ct_memcmp, except that the result only depends on part of * the input data - differences in the head or tail are ignored. Functionally equivalent to: * * memcmp(a + skip_head, b + skip_head, size - skip_head - skip_tail) * * Time taken depends on \p n, but not on \p skip_head or \p skip_tail . * * Behaviour is undefined if ( \p skip_head + \p skip_tail) > \p n. * * \param a Secret. Pointer to the first buffer, containing at least \p n bytes. May not be NULL. * \param b Secret. Pointer to the second buffer, containing at least \p n bytes. May not be NULL. * \param n The number of bytes to examine (total size of the buffers). * \param skip_head Secret. The number of bytes to treat as non-significant at the start of the buffer. * These bytes will still be read. * \param skip_tail Secret. The number of bytes to treat as non-significant at the end of the buffer. * These bytes will still be read. * * \return Zero if the contents of the two buffers are the same, otherwise non-zero. */ int mbedtls_ct_memcmp_partial(const void *a, const void *b, size_t n, size_t skip_head, size_t skip_tail); #endif /* Include the implementation of static inline functions above. */ #include "constant_time_impl.h" #endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */ webfakes/src/mbedtls/library/pk.c0000644000176200001440000014514514740737024016526 0ustar liggesusers/* * Public Key abstraction layer * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PK_C) #include "mbedtls/pk.h" #include "pk_wrap.h" #include "pkwrite.h" #include "pk_internal.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #include "rsa_internal.h" #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #endif #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include "psa_util_internal.h" #include "mbedtls/psa_util.h" #endif #include #include #define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \ (PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \ PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE /* * Initialise a mbedtls_pk_context */ void mbedtls_pk_init(mbedtls_pk_context *ctx) { ctx->pk_info = NULL; ctx->pk_ctx = NULL; #if defined(MBEDTLS_USE_PSA_CRYPTO) ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) memset(ctx->pub_raw, 0, sizeof(ctx->pub_raw)); ctx->pub_raw_len = 0; ctx->ec_family = 0; ctx->ec_bits = 0; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } /* * Free (the components of) a mbedtls_pk_context */ void mbedtls_pk_free(mbedtls_pk_context *ctx) { if (ctx == NULL) { return; } if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) { ctx->pk_info->ctx_free_func(ctx->pk_ctx); } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* The ownership of the priv_id key for opaque keys is external of the PK * module. It's the user responsibility to clear it after use. */ if ((ctx->pk_info != NULL) && (ctx->pk_info->type != MBEDTLS_PK_OPAQUE)) { psa_destroy_key(ctx->priv_id); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context)); } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* * Initialize a restart context */ void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx) { ctx->pk_info = NULL; ctx->rs_ctx = NULL; } /* * Free the components of a restart context */ void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx) { if (ctx == NULL || ctx->pk_info == NULL || ctx->pk_info->rs_free_func == NULL) { return; } ctx->pk_info->rs_free_func(ctx->rs_ctx); ctx->pk_info = NULL; ctx->rs_ctx = NULL; } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* * Get pk_info structure from type */ const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type) { switch (pk_type) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: return &mbedtls_rsa_info; #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) case MBEDTLS_PK_ECKEY: return &mbedtls_eckey_info; case MBEDTLS_PK_ECKEY_DH: return &mbedtls_eckeydh_info; #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) case MBEDTLS_PK_ECDSA: return &mbedtls_ecdsa_info; #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ /* MBEDTLS_PK_RSA_ALT omitted on purpose */ default: return NULL; } } /* * Initialise context */ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info) { if (info == NULL || ctx->pk_info != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if ((info->ctx_alloc_func != NULL) && ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL)) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } ctx->pk_info = info; return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) /* * Initialise a PSA-wrapping context */ int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, const mbedtls_svc_key_id_t key) { const mbedtls_pk_info_t *info = NULL; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t type; if (ctx == NULL || ctx->pk_info != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } type = psa_get_key_type(&attributes); psa_reset_key_attributes(&attributes); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { info = &mbedtls_ecdsa_opaque_info; } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { info = &mbedtls_rsa_opaque_info; } else { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } ctx->pk_info = info; ctx->priv_id = key; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* * Initialize an RSA-alt context */ int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, mbedtls_pk_rsa_alt_decrypt_func decrypt_func, mbedtls_pk_rsa_alt_sign_func sign_func, mbedtls_pk_rsa_alt_key_len_func key_len_func) { mbedtls_rsa_alt_context *rsa_alt; const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; if (ctx->pk_info != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } ctx->pk_info = info; rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; rsa_alt->key = key; rsa_alt->decrypt_func = decrypt_func; rsa_alt->sign_func = sign_func; rsa_alt->key_len_func = key_len_func; return 0; } #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ /* * Tell if a PK can do the operations of the given type */ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type) { /* A context with null pk_info is not set up yet and can't do anything. * For backward compatibility, also accept NULL instead of a context * pointer. */ if (ctx == NULL || ctx->pk_info == NULL) { return 0; } return ctx->pk_info->can_do(type); } #if defined(MBEDTLS_USE_PSA_CRYPTO) /* * Tell if a PK can do the operations of the given PSA algorithm */ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, psa_key_usage_t usage) { psa_key_usage_t key_usage; /* A context with null pk_info is not set up yet and can't do anything. * For backward compatibility, also accept NULL instead of a context * pointer. */ if (ctx == NULL || ctx->pk_info == NULL) { return 0; } /* Filter out non allowed algorithms */ if (PSA_ALG_IS_ECDSA(alg) == 0 && PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 && PSA_ALG_IS_RSA_PSS(alg) == 0 && alg != PSA_ALG_RSA_PKCS1V15_CRYPT && PSA_ALG_IS_ECDH(alg) == 0) { return 0; } /* Filter out non allowed usage flags */ if (usage == 0 || (usage & ~(PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE)) != 0) { return 0; } /* Wildcard hash is not allowed */ if (PSA_ALG_IS_SIGN_HASH(alg) && PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) { return 0; } if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) { mbedtls_pk_type_t type; if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) { type = MBEDTLS_PK_ECKEY; } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { type = MBEDTLS_PK_RSA; } else if (PSA_ALG_IS_RSA_PSS(alg)) { type = MBEDTLS_PK_RSASSA_PSS; } else { return 0; } if (ctx->pk_info->can_do(type) == 0) { return 0; } switch (type) { case MBEDTLS_PK_ECKEY: key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE; break; case MBEDTLS_PK_RSA: case MBEDTLS_PK_RSASSA_PSS: key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT; break; default: /* Should never happen */ return 0; } return (key_usage & usage) == usage; } psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status; status = psa_get_key_attributes(ctx->priv_id, &attributes); if (status != PSA_SUCCESS) { return 0; } psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes); /* Key's enrollment is available only when an Mbed TLS implementation of PSA * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined. * Even though we don't officially support using other implementations of PSA * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations * separated. */ #if defined(MBEDTLS_PSA_CRYPTO_C) psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes); #endif /* MBEDTLS_PSA_CRYPTO_C */ key_usage = psa_get_key_usage_flags(&attributes); psa_reset_key_attributes(&attributes); if ((key_usage & usage) != usage) { return 0; } /* * Common case: the key alg [or alg2] only allows alg. * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH * directly. * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with * a fixed hash on key_alg [or key_alg2]. */ if (alg == key_alg) { return 1; } #if defined(MBEDTLS_PSA_CRYPTO_C) if (alg == key_alg2) { return 1; } #endif /* MBEDTLS_PSA_CRYPTO_C */ /* * If key_alg [or key_alg2] is a hash-and-sign with a wildcard for the hash, * and alg is the same hash-and-sign family with any hash, * then alg is compliant with this key alg */ if (PSA_ALG_IS_SIGN_HASH(alg)) { if (PSA_ALG_IS_SIGN_HASH(key_alg) && PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH && (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) { return 1; } #if defined(MBEDTLS_PSA_CRYPTO_C) if (PSA_ALG_IS_SIGN_HASH(key_alg2) && PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH && (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) { return 1; } #endif /* MBEDTLS_PSA_CRYPTO_C */ } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #if defined(MBEDTLS_RSA_C) static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa, int want_crypt) { if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { if (want_crypt) { mbedtls_md_type_t md_type = (mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa); return PSA_ALG_RSA_OAEP(mbedtls_md_psa_alg_from_type(md_type)); } else { return PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH); } } else { if (want_crypt) { return PSA_ALG_RSA_PKCS1V15_CRYPT; } else { return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH); } } } #endif /* MBEDTLS_RSA_C */ int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk, psa_key_usage_t usage, psa_key_attributes_t *attributes) { mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk); psa_key_usage_t more_usage = usage; if (usage == PSA_KEY_USAGE_SIGN_MESSAGE) { more_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE; } else if (usage == PSA_KEY_USAGE_SIGN_HASH) { more_usage |= PSA_KEY_USAGE_VERIFY_HASH; } else if (usage == PSA_KEY_USAGE_DECRYPT) { more_usage |= PSA_KEY_USAGE_ENCRYPT; } more_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY; int want_private = !(usage == PSA_KEY_USAGE_VERIFY_MESSAGE || usage == PSA_KEY_USAGE_VERIFY_HASH || usage == PSA_KEY_USAGE_ENCRYPT); switch (pk_type) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: { int want_crypt = 0; /* 0: sign/verify; 1: encrypt/decrypt */ switch (usage) { case PSA_KEY_USAGE_SIGN_MESSAGE: case PSA_KEY_USAGE_SIGN_HASH: case PSA_KEY_USAGE_VERIFY_MESSAGE: case PSA_KEY_USAGE_VERIFY_HASH: /* Nothing to do. */ break; case PSA_KEY_USAGE_DECRYPT: case PSA_KEY_USAGE_ENCRYPT: want_crypt = 1; break; default: return MBEDTLS_ERR_PK_TYPE_MISMATCH; } /* Detect the presence of a private key in a way that works both * in CRT and non-CRT configurations. */ mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk); int has_private = (mbedtls_rsa_check_privkey(rsa) == 0); if (want_private && !has_private) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } psa_set_key_type(attributes, (want_private ? PSA_KEY_TYPE_RSA_KEY_PAIR : PSA_KEY_TYPE_RSA_PUBLIC_KEY)); psa_set_key_bits(attributes, mbedtls_pk_get_bitlen(pk)); psa_set_key_algorithm(attributes, psa_algorithm_for_rsa(rsa, want_crypt)); break; } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: { int sign_ok = (pk_type != MBEDTLS_PK_ECKEY_DH); int derive_ok = (pk_type != MBEDTLS_PK_ECDSA); #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) psa_ecc_family_t family = pk->ec_family; size_t bits = pk->ec_bits; int has_private = 0; if (pk->priv_id != MBEDTLS_SVC_KEY_ID_INIT) { has_private = 1; } #else const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk); int has_private = (ec->d.n != 0); size_t bits = 0; psa_ecc_family_t family = mbedtls_ecc_group_to_psa(ec->grp.id, &bits); #endif psa_algorithm_t alg = 0; switch (usage) { case PSA_KEY_USAGE_SIGN_MESSAGE: case PSA_KEY_USAGE_SIGN_HASH: case PSA_KEY_USAGE_VERIFY_MESSAGE: case PSA_KEY_USAGE_VERIFY_HASH: if (!sign_ok) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } #if defined(MBEDTLS_ECDSA_DETERMINISTIC) alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH); #else alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH); #endif break; case PSA_KEY_USAGE_DERIVE: alg = PSA_ALG_ECDH; if (!derive_ok) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } break; default: return MBEDTLS_ERR_PK_TYPE_MISMATCH; } if (want_private && !has_private) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } psa_set_key_type(attributes, (want_private ? PSA_KEY_TYPE_ECC_KEY_PAIR(family) : PSA_KEY_TYPE_ECC_PUBLIC_KEY(family))); psa_set_key_bits(attributes, bits); psa_set_key_algorithm(attributes, alg); break; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) case MBEDTLS_PK_RSA_ALT: return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #if defined(MBEDTLS_USE_PSA_CRYPTO) case MBEDTLS_PK_OPAQUE: { psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_get_key_attributes(pk->priv_id, &old_attributes); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_key_type_t old_type = psa_get_key_type(&old_attributes); switch (usage) { case PSA_KEY_USAGE_SIGN_MESSAGE: case PSA_KEY_USAGE_SIGN_HASH: case PSA_KEY_USAGE_VERIFY_MESSAGE: case PSA_KEY_USAGE_VERIFY_HASH: if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type) || old_type == PSA_KEY_TYPE_RSA_KEY_PAIR)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } break; case PSA_KEY_USAGE_DECRYPT: case PSA_KEY_USAGE_ENCRYPT: if (old_type != PSA_KEY_TYPE_RSA_KEY_PAIR) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } break; case PSA_KEY_USAGE_DERIVE: if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type))) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } break; default: return MBEDTLS_ERR_PK_TYPE_MISMATCH; } psa_key_type_t new_type = old_type; /* Opaque keys are always key pairs, so we don't need a check * on the input if the required usage is private. We just need * to adjust the type correctly if the required usage is public. */ if (!want_private) { new_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(new_type); } more_usage = psa_get_key_usage_flags(&old_attributes); if ((usage & more_usage) == 0) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } psa_set_key_type(attributes, new_type); psa_set_key_bits(attributes, psa_get_key_bits(&old_attributes)); psa_set_key_algorithm(attributes, psa_get_key_algorithm(&old_attributes)); break; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ default: return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_usage_flags(attributes, more_usage); /* Key's enrollment is available only when an Mbed TLS implementation of PSA * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined. * Even though we don't officially support using other implementations of PSA * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations * separated. */ #if defined(MBEDTLS_PSA_CRYPTO_C) psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE); #endif return 0; } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO) static psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *new_key_id) { unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE]; size_t key_length = 0; psa_status_t status = psa_export_key(old_key_id, key_buffer, sizeof(key_buffer), &key_length); if (status != PSA_SUCCESS) { return status; } status = psa_import_key(attributes, key_buffer, key_length, new_key_id); mbedtls_platform_zeroize(key_buffer, key_length); return status; } static int copy_into_psa(mbedtls_svc_key_id_t old_key_id, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *new_key_id) { /* Normally, we prefer copying: it's more efficient and works even * for non-exportable keys. */ psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id); if (status == PSA_ERROR_NOT_PERMITTED /*missing COPY usage*/ || status == PSA_ERROR_INVALID_ARGUMENT /*incompatible policy*/) { /* There are edge cases where copying won't work, but export+import * might: * - If the old key does not allow PSA_KEY_USAGE_COPY. * - If the old key's usage does not allow what attributes wants. * Because the key was intended for use in the pk module, and may * have had a policy chosen solely for what pk needs rather than * based on a detailed understanding of PSA policies, we are a bit * more liberal than psa_copy_key() here. */ /* Here we need to check that the types match, otherwise we risk * importing nonsensical data. */ psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT; status = psa_get_key_attributes(old_key_id, &old_attributes); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_key_type_t old_type = psa_get_key_type(&old_attributes); psa_reset_key_attributes(&old_attributes); if (old_type != psa_get_key_type(attributes)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } status = export_import_into_psa(old_key_id, attributes, new_key_id); } return PSA_PK_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_USE_PSA_CRYPTO */ static int import_pair_into_psa(const mbedtls_pk_context *pk, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key_id) { switch (mbedtls_pk_get_type(pk)) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: { if (psa_get_key_type(attributes) != PSA_KEY_TYPE_RSA_KEY_PAIR) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } unsigned char key_buffer[ PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)]; unsigned char *const key_end = key_buffer + sizeof(key_buffer); unsigned char *key_data = key_end; int ret = mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), key_buffer, &key_data); if (ret < 0) { return ret; } size_t key_length = key_end - key_data; ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes, key_data, key_length, key_id)); mbedtls_platform_zeroize(key_data, key_length); return ret; } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: { /* We need to check the curve family, otherwise the import could * succeed with nonsensical data. * We don't check the bit-size: it's optional in attributes, * and if it's specified, psa_import_key() will know from the key * data length and will check that the bit-size matches. */ psa_key_type_t to_type = psa_get_key_type(attributes); #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) psa_ecc_family_t from_family = pk->ec_family; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk); size_t from_bits = 0; psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id, &from_bits); #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ if (to_type != PSA_KEY_TYPE_ECC_KEY_PAIR(from_family)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) if (mbedtls_svc_key_id_is_null(pk->priv_id)) { /* We have a public key and want a key pair. */ return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return copy_into_psa(pk->priv_id, attributes, key_id); #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ if (ec->d.n == 0) { /* Private key not set. Assume the input is a public key only. * (The other possibility is that it's an incomplete object * where the group is set but neither the public key nor * the private key. This is not possible through ecp.h * functions, so we don't bother reporting a more suitable * error in that case.) */ return MBEDTLS_ERR_PK_TYPE_MISMATCH; } unsigned char key_buffer[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; size_t key_length = 0; int ret = mbedtls_ecp_write_key_ext(ec, &key_length, key_buffer, sizeof(key_buffer)); if (ret < 0) { return ret; } ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes, key_buffer, key_length, key_id)); mbedtls_platform_zeroize(key_buffer, key_length); return ret; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_USE_PSA_CRYPTO) case MBEDTLS_PK_OPAQUE: return copy_into_psa(pk->priv_id, attributes, key_id); #endif /* MBEDTLS_USE_PSA_CRYPTO */ default: return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } } static int import_public_into_psa(const mbedtls_pk_context *pk, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key_id) { psa_key_type_t psa_type = psa_get_key_type(attributes); #if defined(MBEDTLS_RSA_C) || \ (defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)) || \ defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char key_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; #endif unsigned char *key_data = NULL; size_t key_length = 0; switch (mbedtls_pk_get_type(pk)) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: { if (psa_type != PSA_KEY_TYPE_RSA_PUBLIC_KEY) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } unsigned char *const key_end = key_buffer + sizeof(key_buffer); key_data = key_end; int ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*pk), key_buffer, &key_data); if (ret < 0) { return ret; } key_length = (size_t) ret; break; } #endif /*MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: { /* We need to check the curve family, otherwise the import could * succeed with nonsensical data. * We don't check the bit-size: it's optional in attributes, * and if it's specified, psa_import_key() will know from the key * data length and will check that the bit-size matches. */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } key_data = (unsigned char *) pk->pub_raw; key_length = pk->pub_raw_len; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk); size_t from_bits = 0; psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id, &from_bits); if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(from_family)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } int ret = mbedtls_ecp_write_public_key( ec, MBEDTLS_ECP_PF_UNCOMPRESSED, &key_length, key_buffer, sizeof(key_buffer)); if (ret < 0) { return ret; } key_data = key_buffer; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ break; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_USE_PSA_CRYPTO) case MBEDTLS_PK_OPAQUE: { psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = psa_get_key_attributes(pk->priv_id, &old_attributes); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_key_type_t old_type = psa_get_key_type(&old_attributes); psa_reset_key_attributes(&old_attributes); if (psa_type != PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(old_type)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } status = psa_export_public_key(pk->priv_id, key_buffer, sizeof(key_buffer), &key_length); if (status != PSA_SUCCESS) { return PSA_PK_TO_MBEDTLS_ERR(status); } key_data = key_buffer; break; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ default: return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes, key_data, key_length, key_id)); } int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key_id) { /* Set the output immediately so that it won't contain garbage even * if we error out before calling psa_import_key(). */ *key_id = MBEDTLS_SVC_KEY_ID_INIT; #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA_ALT) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ int want_public = PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes)); if (want_public) { return import_public_into_psa(pk, attributes, key_id); } else { return import_pair_into_psa(pk, attributes, key_id); } } static int copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk, int public_only) { psa_status_t status; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t key_type; size_t key_bits; /* Use a buffer size large enough to contain either a key pair or public key. */ unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE]; size_t exp_key_len; int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; if (pk == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } status = psa_get_key_attributes(key_id, &key_attr); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (public_only) { status = psa_export_public_key(key_id, exp_key, sizeof(exp_key), &exp_key_len); } else { status = psa_export_key(key_id, exp_key, sizeof(exp_key), &exp_key_len); } if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto exit; } key_type = psa_get_key_type(&key_attr); if (public_only) { key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); } key_bits = psa_get_key_bits(&key_attr); #if defined(MBEDTLS_RSA_C) if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) || (key_type == PSA_KEY_TYPE_RSA_PUBLIC_KEY)) { ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); if (ret != 0) { goto exit; } if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) { ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), exp_key, exp_key_len); } else { ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), exp_key, exp_key_len); } if (ret != 0) { goto exit; } psa_algorithm_t alg_type = psa_get_key_algorithm(&key_attr); mbedtls_md_type_t md_type = MBEDTLS_MD_NONE; if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) { md_type = mbedtls_md_type_from_psa_alg(alg_type); } if (PSA_ALG_IS_RSA_OAEP(alg_type) || PSA_ALG_IS_RSA_PSS(alg_type)) { ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V21, md_type); } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg_type) || alg_type == PSA_ALG_RSA_PKCS1V15_CRYPT) { ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V15, md_type); } if (ret != 0) { goto exit; } } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) || PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type)) { mbedtls_ecp_group_id grp_id; ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)); if (ret != 0) { goto exit; } grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type), key_bits); ret = mbedtls_pk_ecc_set_group(pk, grp_id); if (ret != 0) { goto exit; } if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) { ret = mbedtls_pk_ecc_set_key(pk, exp_key, exp_key_len); if (ret != 0) { goto exit; } ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, exp_key, exp_key_len, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); } else { ret = mbedtls_pk_ecc_set_pubkey(pk, exp_key, exp_key_len); } if (ret != 0) { goto exit; } } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ { (void) key_bits; return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } exit: psa_reset_key_attributes(&key_attr); mbedtls_platform_zeroize(exp_key, sizeof(exp_key)); return ret; } int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk) { return copy_from_psa(key_id, pk, 0); } int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk) { return copy_from_psa(key_id, pk, 1); } #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ /* * Helper for mbedtls_pk_sign and mbedtls_pk_verify */ static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len) { if (*hash_len != 0) { return 0; } *hash_len = mbedtls_md_get_size_from_type(md_alg); if (*hash_len == 0) { return -1; } return 0; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* * Helper to set up a restart context if needed */ static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx, const mbedtls_pk_info_t *info) { /* Don't do anything if already set up or invalid */ if (ctx == NULL || ctx->pk_info != NULL) { return 0; } /* Should never happen when we're called */ if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } ctx->pk_info = info; return 0; } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* * Verify a signature (restartable) */ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, mbedtls_pk_restart_ctx *rs_ctx) { if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* optimization: use non-restartable version if restart disabled */ if (rs_ctx != NULL && mbedtls_ecp_restart_is_enabled() && ctx->pk_info->verify_rs_func != NULL) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) { return ret; } ret = ctx->pk_info->verify_rs_func(ctx, md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx); if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { mbedtls_pk_restart_free(rs_ctx); } return ret; } #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ (void) rs_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ if (ctx->pk_info->verify_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return ctx->pk_info->verify_func(ctx, md_alg, hash, hash_len, sig, sig_len); } /* * Verify a signature */ int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { return mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len, sig, sig_len, NULL); } /* * Verify a signature with options */ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (!mbedtls_pk_can_do(ctx, type)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } if (type != MBEDTLS_PK_RSASSA_PSS) { /* General case: no options */ if (options != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len); } /* Ensure the PK context is of the right type otherwise mbedtls_pk_rsa() * below would return a NULL pointer. */ if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_RSA) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_pk_rsassa_pss_options *pss_opts; #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif if (options == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; #if defined(MBEDTLS_USE_PSA_CRYPTO) if (pss_opts->mgf1_hash_id == md_alg) { unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; unsigned char *p; int key_len; size_t signature_length; psa_status_t status = PSA_ERROR_DATA_CORRUPT; psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT; psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg); p = buf + sizeof(buf); key_len = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*ctx), buf, &p); if (key_len < 0) { return key_len; } psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_algorithm(&attributes, psa_sig_alg); status = psa_import_key(&attributes, buf + sizeof(buf) - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { psa_destroy_key(key_id); return PSA_PK_TO_MBEDTLS_ERR(status); } /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH * on a valid signature with trailing data in a buffer, but * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact, * so for this reason the passed sig_len is overwritten. Smaller * signature lengths should not be accepted for verification. */ signature_length = sig_len > mbedtls_pk_get_len(ctx) ? mbedtls_pk_get_len(ctx) : sig_len; status = psa_verify_hash(key_id, psa_sig_alg, hash, hash_len, sig, signature_length); destruction_status = psa_destroy_key(key_id); if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } if (status == PSA_SUCCESS) { status = destruction_status; } return PSA_PK_RSA_TO_MBEDTLS_ERR(status); } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ { if (sig_len < mbedtls_pk_get_len(ctx)) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx), md_alg, (unsigned int) hash_len, hash, pss_opts->mgf1_hash_id, pss_opts->expected_salt_len, sig); if (ret != 0) { return ret; } if (sig_len > mbedtls_pk_get_len(ctx)) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } return 0; } #else return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ } /* * Make a signature (restartable) */ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_pk_restart_ctx *rs_ctx) { if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* optimization: use non-restartable version if restart disabled */ if (rs_ctx != NULL && mbedtls_ecp_restart_is_enabled() && ctx->pk_info->sign_rs_func != NULL) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) { return ret; } ret = ctx->pk_info->sign_rs_func(ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, rs_ctx->rs_ctx); if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { mbedtls_pk_restart_free(rs_ctx); } return ret; } #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ (void) rs_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ if (ctx->pk_info->sign_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return ctx->pk_info->sign_func(ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng); } /* * Make a signature */ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, NULL); } /* * Make a signature given a signature type. */ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (!mbedtls_pk_can_do(ctx, pk_type)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } if (pk_type != MBEDTLS_PK_RSASSA_PSS) { return mbedtls_pk_sign(ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng); } #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) #if defined(MBEDTLS_USE_PSA_CRYPTO) const psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); if (psa_md_alg == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) { psa_status_t status; /* PSA_ALG_RSA_PSS() behaves the same as PSA_ALG_RSA_PSS_ANY_SALT() when * performing a signature, but they are encoded differently. Instead of * extracting the proper one from the wrapped key policy, just try both. */ status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg), hash, hash_len, sig, sig_size, sig_len); if (status == PSA_ERROR_NOT_PERMITTED) { status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg), hash, hash_len, sig, sig_size, sig_len); } return PSA_PK_RSA_TO_MBEDTLS_ERR(status); } return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg), ctx->pk_ctx, hash, hash_len, sig, sig_size, sig_len); #else /* MBEDTLS_USE_PSA_CRYPTO */ if (sig_size < mbedtls_pk_get_len(ctx)) { return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } if (pk_hashlen_helper(md_alg, &hash_len) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } mbedtls_rsa_context *const rsa_ctx = mbedtls_pk_rsa(*ctx); const int ret = mbedtls_rsa_rsassa_pss_sign_no_mode_check(rsa_ctx, f_rng, p_rng, md_alg, (unsigned int) hash_len, hash, sig); if (ret == 0) { *sig_len = rsa_ctx->len; } return ret; #endif /* MBEDTLS_USE_PSA_CRYPTO */ #else return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ } /* * Decrypt message */ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info->decrypt_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return ctx->pk_info->decrypt_func(ctx, input, ilen, output, olen, osize, f_rng, p_rng); } /* * Encrypt message */ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info->encrypt_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return ctx->pk_info->encrypt_func(ctx, input, ilen, output, olen, osize, f_rng, p_rng); } /* * Check public-private key pair */ int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (pub->pk_info == NULL || prv->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (f_rng == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (prv->pk_info->check_pair_func == NULL) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) { if (pub->pk_info->type != MBEDTLS_PK_RSA) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } } else { if ((prv->pk_info->type != MBEDTLS_PK_OPAQUE) && (pub->pk_info != prv->pk_info)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } } return prv->pk_info->check_pair_func((mbedtls_pk_context *) pub, (mbedtls_pk_context *) prv, f_rng, p_rng); } /* * Get key size in bits */ size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx) { /* For backward compatibility, accept NULL or a context that * isn't set up yet, and return a fake value that should be safe. */ if (ctx == NULL || ctx->pk_info == NULL) { return 0; } return ctx->pk_info->get_bitlen((mbedtls_pk_context *) ctx); } /* * Export debug information */ int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items) { if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info->debug_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } ctx->pk_info->debug_func((mbedtls_pk_context *) ctx, items); return 0; } /* * Access the PK type name */ const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx) { if (ctx == NULL || ctx->pk_info == NULL) { return "invalid PK"; } return ctx->pk_info->name; } /* * Access the PK type */ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) { if (ctx == NULL || ctx->pk_info == NULL) { return MBEDTLS_PK_NONE; } return ctx->pk_info->type; } #endif /* MBEDTLS_PK_C */ webfakes/src/mbedtls/library/bignum_mod.h0000644000176200001440000005060114740737024020231 0ustar liggesusers/** * Modular bignum functions * * This module implements operations on integers modulo some fixed modulus. * * The functions in this module obey the following conventions unless * explicitly indicated otherwise: * * - **Modulus parameters**: the modulus is passed as a pointer to a structure * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an * array of limbs storing the bignum value of the modulus. The modulus must * be odd and is assumed to have no leading zeroes. The modulus is usually * named \c N and is usually input-only. Functions which take a parameter * of type \c const #mbedtls_mpi_mod_modulus* must not modify its value. * - **Bignum parameters**: Bignums are passed as pointers to an array of * limbs or to a #mbedtls_mpi_mod_residue structure. A limb has the type * #mbedtls_mpi_uint. Residues must be initialized before use, and must be * associated with the modulus \c N. Unless otherwise specified: * - Bignum parameters called \c A, \c B, ... are inputs and are not * modified by the function. Functions which take a parameter of * type \c const #mbedtls_mpi_mod_residue* must not modify its value. * - Bignum parameters called \c X, \c Y, ... are outputs or input-output. * The initial bignum value of output-only parameters is ignored, but * they must be set up and associated with the modulus \c N. Some * functions (typically constant-flow) require that the limbs in an * output residue are initialized. * - Bignum parameters called \c p are inputs used to set up a modulus or * residue. These must be pointers to an array of limbs. * - \c T is a temporary storage area. The initial content of such a * parameter is ignored and the final content is unspecified. * - Some functions use different names, such as \c r for the residue. * - **Bignum sizes**: bignum sizes are always expressed in limbs. Both * #mbedtls_mpi_mod_modulus and #mbedtls_mpi_mod_residue have a \c limbs * member storing its size. All bignum parameters must have the same * number of limbs as the modulus. All bignum sizes must be at least 1 and * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is * undefined. * - **Bignum representation**: the representation of inputs and outputs is * specified by the \c int_rep field of the modulus. * - **Parameter ordering**: for bignum parameters, outputs come before inputs. * The modulus is passed after residues. Temporaries come last. * - **Aliasing**: in general, output bignums may be aliased to one or more * inputs. Modulus values may not be aliased to any other parameter. Outputs * may not be aliased to one another. Temporaries may not be aliased to any * other parameter. * - **Overlap**: apart from aliasing of residue pointers (where two residue * arguments are equal pointers), overlap is not supported and may result * in undefined behavior. * - **Error handling**: functions generally check compatibility of input * sizes. Most functions will not check that input values are in canonical * form (i.e. that \c A < \c N), this is only checked during setup of a * residue structure. * - **Modular representatives**: all functions expect inputs to be in the * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. * Residues are set up with an associated modulus, and operations are only * guaranteed to work if the modulus is associated with all residue * parameters. If a residue is passed with a modulus other than the one it * is associated with, then it may be out of range. If an input is out of * range, outputs are fully unspecified, though bignum values out of range * should not cause buffer overflows (beware that this is not extensively * tested). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_MOD_H #define MBEDTLS_BIGNUM_MOD_H #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif /** How residues associated with a modulus are represented. * * This also determines which fields of the modulus structure are valid and * what their contents are (see #mbedtls_mpi_mod_modulus). */ typedef enum { /** Representation not chosen (makes the modulus structure invalid). */ MBEDTLS_MPI_MOD_REP_INVALID = 0, /* Skip 1 as it is slightly easier to accidentally pass to functions. */ /** Montgomery representation. */ MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2, /* Optimised reduction available. This indicates a coordinate modulus (P) * and one or more of the following have been configured: * - A nist curve (MBEDTLS_ECP_DP_SECPXXXR1_ENABLED) & MBEDTLS_ECP_NIST_OPTIM. * - A Kobliz Curve. * - A Fast Reduction Curve CURVE25519 or CURVE448. */ MBEDTLS_MPI_MOD_REP_OPT_RED, } mbedtls_mpi_mod_rep_selector; /* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to * make it easier to catch when they are accidentally swapped. */ typedef enum { MBEDTLS_MPI_MOD_EXT_REP_INVALID = 0, MBEDTLS_MPI_MOD_EXT_REP_LE = 8, MBEDTLS_MPI_MOD_EXT_REP_BE } mbedtls_mpi_mod_ext_rep; typedef struct { mbedtls_mpi_uint *p; size_t limbs; } mbedtls_mpi_mod_residue; typedef struct { mbedtls_mpi_uint const *rr; /* The residue for 2^{2*n*biL} mod N */ mbedtls_mpi_uint mm; /* Montgomery const for -N^{-1} mod 2^{ciL} */ } mbedtls_mpi_mont_struct; typedef int (*mbedtls_mpi_modp_fn)(mbedtls_mpi_uint *X, size_t X_limbs); typedef struct { mbedtls_mpi_modp_fn modp; /* The optimised reduction function pointer */ } mbedtls_mpi_opt_red_struct; typedef struct { const mbedtls_mpi_uint *p; size_t limbs; // number of limbs size_t bits; // bitlen of p mbedtls_mpi_mod_rep_selector int_rep; // selector to signal the active member of the union union rep { /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */ mbedtls_mpi_mont_struct mont; /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */ mbedtls_mpi_opt_red_struct ored; } rep; } mbedtls_mpi_mod_modulus; /** Setup a residue structure. * * The residue will be set up with the buffer \p p and modulus \p N. * * The memory pointed to by \p p will be used by the resulting residue structure. * The value at the pointed-to memory will be the initial value of \p r and must * hold a value that is less than the modulus. This value will be used as-is * and interpreted according to the value of the `N->int_rep` field. * * The modulus \p N will be the modulus associated with \p r. The residue \p r * should only be used in operations where the modulus is \p N. * * \param[out] r The address of the residue to setup. * \param[in] N The address of the modulus related to \p r. * \param[in] p The address of the limb array containing the value of \p r. * The memory pointed to by \p p will be used by \p r and must * not be modified in any way until after * mbedtls_mpi_mod_residue_release() is called. The data * pointed to by \p p must be less than the modulus (the value * pointed to by `N->p`) and already in the representation * indicated by `N->int_rep`. * \param p_limbs The number of limbs of \p p. Must be the same as the number * of limbs in the modulus \p N. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p p_limbs is less than the * limbs in \p N or if \p p is not less than \p N. */ int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *p, size_t p_limbs); /** Unbind elements of a residue structure. * * This function removes the reference to the limb array that was passed to * mbedtls_mpi_mod_residue_setup() to make it safe to free or use again. * * This function invalidates \p r and it must not be used until after * mbedtls_mpi_mod_residue_setup() is called on it again. * * \param[out] r The address of residue to release. */ void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r); /** Initialize a modulus structure. * * \param[out] N The address of the modulus structure to initialize. */ void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N); /** Setup a modulus structure. * * \param[out] N The address of the modulus structure to populate. * \param[in] p The address of the limb array storing the value of \p N. * The memory pointed to by \p p will be used by \p N and must * not be modified in any way until after * mbedtls_mpi_mod_modulus_free() is called. * \param p_limbs The number of limbs of \p p. * * \return \c 0 if successful. */ int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs); /** Setup an optimised-reduction compatible modulus structure. * * \param[out] N The address of the modulus structure to populate. * \param[in] p The address of the limb array storing the value of \p N. * The memory pointed to by \p p will be used by \p N and must * not be modified in any way until after * mbedtls_mpi_mod_modulus_free() is called. * \param p_limbs The number of limbs of \p p. * \param modp A pointer to the optimised reduction function to use. \p p. * * \return \c 0 if successful. */ int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs, mbedtls_mpi_modp_fn modp); /** Free elements of a modulus structure. * * This function frees any memory allocated by mbedtls_mpi_mod_modulus_setup(). * * \warning This function does not free the limb array passed to * mbedtls_mpi_mod_modulus_setup() only removes the reference to it, * making it safe to free or to use it again. * * \param[in,out] N The address of the modulus structure to free. */ void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N); /** \brief Multiply two residues, returning the residue modulo the specified * modulus. * * \note Currently handles the case when `N->int_rep` is * MBEDTLS_MPI_MOD_REP_MONTGOMERY. * * The size of the operation is determined by \p N. \p A, \p B and \p X must * all be associated with the modulus \p N and must all have the same number * of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. They may not alias \p N (since they must be in canonical * form, they cannot == \p N). * * \param[out] X The address of the result MPI. Must have the same * number of limbs as \p N. * On successful completion, \p X contains the result of * the multiplication `A * B * R^-1` mod N where * `R = 2^(biL * N->limbs)`. * \param[in] A The address of the first MPI. * \param[in] B The address of the second MPI. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the multiplication. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not * have the same number of limbs or \p N is invalid. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N); /** * \brief Perform a fixed-size modular subtraction. * * Calculate `A - B modulo N`. * * \p A, \p B and \p X must all have the same number of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \note This function does not check that \p A or \p B are in canonical * form (that is, are < \p N) - that will have been done by * mbedtls_mpi_mod_residue_setup(). * * \param[out] X The address of the result MPI. Must be initialized. * Must have the same number of limbs as the modulus \p N. * \param[in] A The address of the first MPI. * \param[in] B The address of the second MPI. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the subtraction. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not * have the correct number of limbs. */ int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N); /** * \brief Perform modular inversion of an MPI with respect to a modulus \p N. * * \p A and \p X must be associated with the modulus \p N and will therefore * have the same number of limbs as \p N. * * \p X may be aliased to \p A. * * \warning Currently only supports prime moduli, but does not check for them. * * \param[out] X The modular inverse of \p A with respect to \p N. * \param[in] A The number to calculate the modular inverse of. * Must not be 0. * \param[in] N The modulus to use. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A and \p N do not * have the same number of limbs. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A is zero. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough * memory (needed for conversion to and from Mongtomery form * when not in Montgomery form already, and for temporary use * by the inversion calculation itself). */ int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_modulus *N); /** * \brief Perform a fixed-size modular addition. * * Calculate `A + B modulo N`. * * \p A, \p B and \p X must all be associated with the modulus \p N and must * all have the same number of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \note This function does not check that \p A or \p B are in canonical * form (that is, are < \p N) - that will have been done by * mbedtls_mpi_mod_residue_setup(). * * \param[out] X The address of the result residue. Must be initialized. * Must have the same number of limbs as the modulus \p N. * \param[in] A The address of the first input residue. * \param[in] B The address of the second input residue. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the addition. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not * have the correct number of limbs. */ int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N); /** Generate a random number uniformly in a range. * * This function generates a random number between \p min inclusive and * \p N exclusive. * * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) * when the RNG is a suitably parametrized instance of HMAC_DRBG * and \p min is \c 1. * * \note There are `N - min` possible outputs. The lower bound * \p min can be reached, but the upper bound \p N cannot. * * \param X The destination residue. * \param min The minimum value to return. It must be strictly smaller * than \b N. * \param N The modulus. * This is the upper bound of the output range, exclusive. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was * unable to find a suitable value within a limited number * of attempts. This has a negligible probability if \p N * is significantly larger than \p min, which is the case * for all usual cryptographic applications. */ int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X, mbedtls_mpi_uint min, const mbedtls_mpi_mod_modulus *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Read a residue from a byte buffer. * * The residue will be automatically converted to the internal representation * based on the value of the `N->int_rep` field. * * The modulus \p N will be the modulus associated with \p r. The residue \p r * should only be used in operations where the modulus is \p N or a modulus * equivalent to \p N (in the sense that all their fields or memory pointed by * their fields hold the same value). * * \param[out] r The address of the residue. It must have exactly the same * number of limbs as the modulus \p N. * \param[in] N The address of the modulus. * \param[in] buf The input buffer to import from. * \param buflen The length in bytes of \p buf. * \param ext_rep The endianness of the number in the input buffer. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p r isn't * large enough to hold the value in \p buf. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep * is invalid or the value in the buffer is not less than \p N. */ int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, const unsigned char *buf, size_t buflen, mbedtls_mpi_mod_ext_rep ext_rep); /** Write a residue into a byte buffer. * * The modulus \p N must be the modulus associated with \p r (see * mbedtls_mpi_mod_residue_setup() and mbedtls_mpi_mod_read()). * * The residue will be automatically converted from the internal representation * based on the value of `N->int_rep` field. * * \warning If the buffer is smaller than `N->bits`, the number of * leading zeroes is leaked through timing. If \p r is * secret, the caller must ensure that \p buflen is at least * (`N->bits`+7)/8. * * \param[in] r The address of the residue. It must have the same number of * limbs as the modulus \p N. (\p r is an input parameter, but * its value will be modified during execution and restored * before the function returns.) * \param[in] N The address of the modulus associated with \p r. * \param[out] buf The output buffer to export to. * \param buflen The length in bytes of \p buf. * \param ext_rep The endianness in which the number should be written into * the output buffer. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't * large enough to hold the value of \p r (without leading * zeroes). * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep is invalid. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough * memory for conversion. Can occur only for moduli with * MBEDTLS_MPI_MOD_REP_MONTGOMERY. */ int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, unsigned char *buf, size_t buflen, mbedtls_mpi_mod_ext_rep ext_rep); #endif /* MBEDTLS_BIGNUM_MOD_H */ webfakes/src/mbedtls/library/ssl_ciphersuites.c0000644000176200001440000024760314740737024021506 0ustar liggesusers/** * \file ssl_ciphersuites.c * * \brief SSL ciphersuites for Mbed TLS * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/platform.h" #include "mbedtls/ssl_ciphersuites.h" #include "mbedtls/ssl.h" #include "ssl_misc.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/psa_util.h" #endif #include /* * Ordered from most preferred to least preferred in terms of security. * * Current rule (except weak and null which come last): * 1. By key exchange: * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK * 2. By key length and cipher: * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 * 4. By hash function used when relevant * 5. By key exchange/auth again: EC > non-EC */ static const int ciphersuite_preference[] = { #if defined(MBEDTLS_SSL_CIPHERSUITES) MBEDTLS_SSL_CIPHERSUITES, #else #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* TLS 1.3 ciphersuites */ MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS1_3_AES_256_GCM_SHA384, MBEDTLS_TLS1_3_AES_128_GCM_SHA256, MBEDTLS_TLS1_3_AES_128_CCM_SHA256, MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /* Chacha-Poly ephemeral suites */ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* All AES-256 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, /* All CAMELLIA-256 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, /* All ARIA-256 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, /* All AES-128 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, /* All CAMELLIA-128 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, /* All ARIA-128 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, /* The PSK ephemeral suites */ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, /* The ECJPAKE suite */ MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, /* All AES-256 suites */ MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_RSA_WITH_AES_256_CCM, MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, /* All CAMELLIA-256 suites */ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, /* All ARIA-256 suites */ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, /* All AES-128 suites */ MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_RSA_WITH_AES_128_CCM, MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, /* All CAMELLIA-128 suites */ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, /* All ARIA-128 suites */ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, /* The RSA PSK suites */ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, /* The PSK suites */ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CCM, MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, /* NULL suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, MBEDTLS_TLS_RSA_WITH_NULL_SHA256, MBEDTLS_TLS_RSA_WITH_NULL_SHA, MBEDTLS_TLS_RSA_WITH_NULL_MD5, MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, MBEDTLS_TLS_PSK_WITH_NULL_SHA384, MBEDTLS_TLS_PSK_WITH_NULL_SHA256, MBEDTLS_TLS_PSK_WITH_NULL_SHA, #endif /* MBEDTLS_SSL_CIPHERSUITES */ 0 }; static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = { #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, "TLS1-3-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ 0, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS1_3_AES_128_GCM_SHA256, "TLS1-3-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ 0, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CCM) && defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS1_3_AES_128_CCM_SHA256, "TLS1-3-AES-128-CCM-SHA256", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ 0, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, { MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, "TLS1-3-AES-128-CCM-8-SHA256", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, #endif /* MBEDTLS_MD_CAN_SHA256 && MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, "TLS1-3-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ 0, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, #endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY && MBEDTLS_MD_CAN_SHA256 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && \ defined(MBEDTLS_MD_CAN_SHA256) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY && MBEDTLS_MD_CAN_SHA256 && MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA384) && \ defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA384) && \ defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) #if defined(MBEDTLS_MD_CAN_MD5) { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #if defined(MBEDTLS_SSL_HAVE_ARIA) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, "TLS-PSK-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, "TLS-PSK-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #endif /* MBEDTLS_SSL_HAVE_ARIA */ { 0, "", MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, 0, 0, 0 } }; #if defined(MBEDTLS_SSL_CIPHERSUITES) const int *mbedtls_ssl_list_ciphersuites(void) { return ciphersuite_preference; } #else #define MAX_CIPHERSUITES sizeof(ciphersuite_definitions) / \ sizeof(ciphersuite_definitions[0]) static int supported_ciphersuites[MAX_CIPHERSUITES]; static int supported_init = 0; MBEDTLS_CHECK_RETURN_CRITICAL static int ciphersuite_is_removed(const mbedtls_ssl_ciphersuite_t *cs_info) { (void) cs_info; return 0; } const int *mbedtls_ssl_list_ciphersuites(void) { /* * On initial call filter out all ciphersuites not supported by current * build based on presence in the ciphersuite_definitions. */ if (supported_init == 0) { const int *p; int *q; for (p = ciphersuite_preference, q = supported_ciphersuites; *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; p++) { const mbedtls_ssl_ciphersuite_t *cs_info; if ((cs_info = mbedtls_ssl_ciphersuite_from_id(*p)) != NULL && !ciphersuite_is_removed(cs_info)) { *(q++) = *p; } } *q = 0; supported_init = 1; } return supported_ciphersuites; } #endif /* MBEDTLS_SSL_CIPHERSUITES */ const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name) { const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; if (NULL == ciphersuite_name) { return NULL; } while (cur->id != 0) { if (0 == strcmp(cur->name, ciphersuite_name)) { return cur; } cur++; } return NULL; } const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite) { const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; while (cur->id != 0) { if (cur->id == ciphersuite) { return cur; } cur++; } return NULL; } const char *mbedtls_ssl_get_ciphersuite_name(const int ciphersuite_id) { const mbedtls_ssl_ciphersuite_t *cur; cur = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id); if (cur == NULL) { return "unknown"; } return cur->name; } int mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name) { const mbedtls_ssl_ciphersuite_t *cur; cur = mbedtls_ssl_ciphersuite_from_string(ciphersuite_name); if (cur == NULL) { return 0; } return cur->id; } size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t key_type; psa_algorithm_t alg; size_t key_bits; status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) info->cipher, info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16, &alg, &key_type, &key_bits); if (status != PSA_SUCCESS) { return 0; } return key_bits; #else const mbedtls_cipher_info_t * const cipher_info = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) info->cipher); return mbedtls_cipher_info_get_key_bitlen(cipher_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #if defined(MBEDTLS_PK_C) mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: return MBEDTLS_PK_RSA; case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return MBEDTLS_PK_ECDSA; case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: return MBEDTLS_PK_ECKEY; default: return MBEDTLS_PK_NONE; } } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: return PSA_ALG_RSA_PKCS1V15_CRYPT; case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: return PSA_ALG_RSA_PKCS1V15_SIGN( mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac)); case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac)); case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: return PSA_ALG_ECDH; default: return PSA_ALG_NONE; } } psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: return PSA_KEY_USAGE_DECRYPT; case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return PSA_KEY_USAGE_SIGN_HASH; case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: return PSA_KEY_USAGE_DERIVE; default: return 0; } } #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: return MBEDTLS_PK_RSA; case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return MBEDTLS_PK_ECDSA; default: return MBEDTLS_PK_NONE; } } #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECJPAKE: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || * MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || * MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_PSK: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #endif /* MBEDTLS_SSL_TLS_C */ webfakes/src/mbedtls/library/psa_crypto_pake.c0000644000176200001440000005015214740737024021270 0ustar liggesusers/* * PSA PAKE layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa_crypto_core.h" #include "psa_crypto_pake.h" #include "psa_crypto_slot_management.h" #include #include "psa_util_internal.h" #include #include #include /* * State sequence: * * psa_pake_setup() * | * |-- In any order: * | | psa_pake_set_password_key() * | | psa_pake_set_user() * | | psa_pake_set_peer() * | | psa_pake_set_role() * | * |--- In any order: (First round input before or after first round output) * | | * | |------ In Order * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) * | | * | |------ In Order: * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) * | * |--- In any order: (Second round input before or after second round output) * | | * | |------ In Order * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) * | | * | |------ In Order: * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) * | * psa_pake_get_implicit_key() * psa_pake_abort() */ /* * Possible sequence of calls to implementation: * * |--- In any order: * | | * | |------ In Order * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_KEY_SHARE) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PUBLIC) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PROOF) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_KEY_SHARE) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PUBLIC) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PROOF) * | | * | |------ In Order: * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_KEY_SHARE) * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PUBLIC) * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PROOF) * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_KEY_SHARE) * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PUBLIC) * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PROOF) * | * |--- In any order: * | | * | |------ In Order * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_KEY_SHARE) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PUBLIC) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PROOF) * | | * | |------ In Order: * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_KEY_SHARE) * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PUBLIC) * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PROOF) */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) static psa_status_t mbedtls_ecjpake_to_psa_error(int ret) { switch (ret) { case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: case MBEDTLS_ERR_ECP_INVALID_KEY: case MBEDTLS_ERR_ECP_VERIFY_FAILED: return PSA_ERROR_DATA_INVALID; case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: return PSA_ERROR_CORRUPTION_DETECTED; default: return PSA_ERROR_GENERIC_ERROR; } } #endif #if defined(MBEDTLS_PSA_BUILTIN_PAKE) #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) static psa_status_t psa_pake_ecjpake_setup(mbedtls_psa_pake_operation_t *operation) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecjpake_init(&operation->ctx.jpake); ret = mbedtls_ecjpake_setup(&operation->ctx.jpake, operation->role, MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, operation->password, operation->password_len); mbedtls_platform_zeroize(operation->password, operation->password_len); if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } return PSA_SUCCESS; } #endif /* The only two JPAKE user/peer identifiers supported in built-in implementation. */ static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' }; static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' }; psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation, const psa_crypto_driver_pake_inputs_t *inputs) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t user_len = 0, peer_len = 0, password_len = 0; uint8_t *peer = NULL, *user = NULL; size_t actual_user_len = 0, actual_peer_len = 0, actual_password_len = 0; psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); status = psa_crypto_driver_pake_get_password_len(inputs, &password_len); if (status != PSA_SUCCESS) { return status; } status = psa_crypto_driver_pake_get_user_len(inputs, &user_len); if (status != PSA_SUCCESS) { return status; } status = psa_crypto_driver_pake_get_peer_len(inputs, &peer_len); if (status != PSA_SUCCESS) { return status; } status = psa_crypto_driver_pake_get_cipher_suite(inputs, &cipher_suite); if (status != PSA_SUCCESS) { return status; } operation->password = mbedtls_calloc(1, password_len); if (operation->password == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto error; } user = mbedtls_calloc(1, user_len); if (user == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto error; } peer = mbedtls_calloc(1, peer_len); if (peer == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto error; } status = psa_crypto_driver_pake_get_password(inputs, operation->password, password_len, &actual_password_len); if (status != PSA_SUCCESS) { goto error; } status = psa_crypto_driver_pake_get_user(inputs, user, user_len, &actual_user_len); if (status != PSA_SUCCESS) { goto error; } status = psa_crypto_driver_pake_get_peer(inputs, peer, peer_len, &actual_peer_len); if (status != PSA_SUCCESS) { goto error; } operation->password_len = actual_password_len; operation->alg = cipher_suite.algorithm; #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) if (cipher_suite.algorithm == PSA_ALG_JPAKE) { if (cipher_suite.type != PSA_PAKE_PRIMITIVE_TYPE_ECC || cipher_suite.family != PSA_ECC_FAMILY_SECP_R1 || cipher_suite.bits != 256 || cipher_suite.hash != PSA_ALG_SHA_256) { status = PSA_ERROR_NOT_SUPPORTED; goto error; } const size_t user_peer_len = sizeof(jpake_client_id); // client and server have the same length if (actual_user_len != user_peer_len || actual_peer_len != user_peer_len) { status = PSA_ERROR_NOT_SUPPORTED; goto error; } if (memcmp(user, jpake_client_id, actual_user_len) == 0 && memcmp(peer, jpake_server_id, actual_peer_len) == 0) { operation->role = MBEDTLS_ECJPAKE_CLIENT; } else if (memcmp(user, jpake_server_id, actual_user_len) == 0 && memcmp(peer, jpake_client_id, actual_peer_len) == 0) { operation->role = MBEDTLS_ECJPAKE_SERVER; } else { status = PSA_ERROR_NOT_SUPPORTED; goto error; } operation->buffer_length = 0; operation->buffer_offset = 0; status = psa_pake_ecjpake_setup(operation); if (status != PSA_SUCCESS) { goto error; } /* Role has been set, release user/peer buffers. */ mbedtls_free(user); mbedtls_free(peer); return PSA_SUCCESS; } else #else (void) operation; (void) inputs; #endif { status = PSA_ERROR_NOT_SUPPORTED; } error: mbedtls_free(user); mbedtls_free(peer); /* In case of failure of the setup of a multipart operation, the PSA driver interface * specifies that the core does not call any other driver entry point thus does not * call mbedtls_psa_pake_abort(). Therefore call it here to do the needed clean * up like freeing the memory that may have been allocated to store the password. */ mbedtls_psa_pake_abort(operation); return status; } static psa_status_t mbedtls_psa_pake_output_internal( mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t length; (void) step; // Unused parameter #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) /* * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different * handling of output sequencing. * * The Mbed TLS JPAKE API outputs the whole X1+X2 and X2S steps data * at once, on the other side the PSA CRYPTO PAKE api requires * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X2S to be * retrieved in sequence. * * In order to achieve API compatibility, the whole X1+X2 or X2S steps * data is stored in an intermediate buffer at first step output call, * and data is sliced down by parsing the ECPoint records in order * to return the right parts on each step. */ if (operation->alg == PSA_ALG_JPAKE) { /* Initialize & write round on KEY_SHARE sequences */ if (step == PSA_JPAKE_X1_STEP_KEY_SHARE) { ret = mbedtls_ecjpake_write_round_one(&operation->ctx.jpake, operation->buffer, sizeof(operation->buffer), &operation->buffer_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } operation->buffer_offset = 0; } else if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE) { ret = mbedtls_ecjpake_write_round_two(&operation->ctx.jpake, operation->buffer, sizeof(operation->buffer), &operation->buffer_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } operation->buffer_offset = 0; } /* * mbedtls_ecjpake_write_round_xxx() outputs thing in the format * defined by draft-cragie-tls-ecjpake-01 section 7. The summary is * that the data for each step is prepended with a length byte, and * then they're concatenated. Additionally, the server's second round * output is prepended with a 3-bytes ECParameters structure. * * In PSA, we output each step separately, and don't prepend the * output with a length byte, even less a curve identifier, as that * information is already available. */ if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE && operation->role == MBEDTLS_ECJPAKE_SERVER) { /* Skip ECParameters, with is 3 bytes (RFC 8422) */ operation->buffer_offset += 3; } /* Read the length byte then move past it to the data */ length = operation->buffer[operation->buffer_offset]; operation->buffer_offset += 1; if (operation->buffer_offset + length > operation->buffer_length) { return PSA_ERROR_DATA_CORRUPT; } if (output_size < length) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(output, operation->buffer + operation->buffer_offset, length); *output_length = length; operation->buffer_offset += length; /* Reset buffer after ZK_PROOF sequence */ if ((step == PSA_JPAKE_X2_STEP_ZK_PROOF) || (step == PSA_JPAKE_X2S_STEP_ZK_PROOF)) { mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); operation->buffer_length = 0; operation->buffer_offset = 0; } return PSA_SUCCESS; } else #else (void) step; (void) output; (void) output_size; (void) output_length; #endif { return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = mbedtls_psa_pake_output_internal( operation, step, output, output_size, output_length); return status; } static psa_status_t mbedtls_psa_pake_input_internal( mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, const uint8_t *input, size_t input_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; (void) step; // Unused parameter #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) /* * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different * handling of input sequencing. * * The Mbed TLS JPAKE API takes the whole X1+X2 or X4S steps data * at once as input, on the other side the PSA CRYPTO PAKE api requires * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X4S to be * given in sequence. * * In order to achieve API compatibility, each X1+X2 or X4S step data * is stored sequentially in an intermediate buffer and given to the * Mbed TLS JPAKE API on the last step. * * This causes any input error to be only detected on the last step. */ if (operation->alg == PSA_ALG_JPAKE) { /* * Copy input to local buffer and format it as the Mbed TLS API * expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7. * The summary is that the data for each step is prepended with a * length byte, and then they're concatenated. Additionally, the * server's second round output is prepended with a 3-bytes * ECParameters structure - which means we have to prepend that when * we're a client. */ if (step == PSA_JPAKE_X4S_STEP_KEY_SHARE && operation->role == MBEDTLS_ECJPAKE_CLIENT) { /* We only support secp256r1. */ /* This is the ECParameters structure defined by RFC 8422. */ unsigned char ecparameters[3] = { 3, /* named_curve */ 0, 23 /* secp256r1 */ }; if (operation->buffer_length + sizeof(ecparameters) > sizeof(operation->buffer)) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(operation->buffer + operation->buffer_length, ecparameters, sizeof(ecparameters)); operation->buffer_length += sizeof(ecparameters); } /* * The core checks that input_length is smaller than * PSA_PAKE_INPUT_MAX_SIZE. * Thus no risk of integer overflow here. */ if (operation->buffer_length + input_length + 1 > sizeof(operation->buffer)) { return PSA_ERROR_BUFFER_TOO_SMALL; } /* Write the length byte */ operation->buffer[operation->buffer_length] = (uint8_t) input_length; operation->buffer_length += 1; /* Finally copy the data */ memcpy(operation->buffer + operation->buffer_length, input, input_length); operation->buffer_length += input_length; /* Load buffer at each last round ZK_PROOF */ if (step == PSA_JPAKE_X2_STEP_ZK_PROOF) { ret = mbedtls_ecjpake_read_round_one(&operation->ctx.jpake, operation->buffer, operation->buffer_length); mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); operation->buffer_length = 0; if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } } else if (step == PSA_JPAKE_X4S_STEP_ZK_PROOF) { ret = mbedtls_ecjpake_read_round_two(&operation->ctx.jpake, operation->buffer, operation->buffer_length); mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); operation->buffer_length = 0; if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } } return PSA_SUCCESS; } else #else (void) step; (void) input; (void) input_length; #endif { return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, const uint8_t *input, size_t input_length) { psa_status_t status = mbedtls_psa_pake_input_internal( operation, step, input, input_length); return status; } psa_status_t mbedtls_psa_pake_get_implicit_key( mbedtls_psa_pake_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.jpake, output, output_size, output_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } return PSA_SUCCESS; } else #else (void) output; #endif { return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation) { mbedtls_zeroize_and_free(operation->password, operation->password_len); operation->password = NULL; operation->password_len = 0; #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { operation->role = MBEDTLS_ECJPAKE_NONE; mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); operation->buffer_length = 0; operation->buffer_offset = 0; mbedtls_ecjpake_free(&operation->ctx.jpake); } #endif operation->alg = PSA_ALG_NONE; return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/pk_internal.h0000644000176200001440000001750314740737024020423 0ustar liggesusers/** * \file pk_internal.h * * \brief Public Key abstraction layer: internal (i.e. library only) functions * and definitions. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_INTERNAL_H #define MBEDTLS_PK_INTERNAL_H #include "mbedtls/pk.h" #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include "psa/crypto.h" #include "psa_util_internal.h" #define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status) #define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ psa_to_pk_rsa_errors, \ psa_pk_status_to_mbedtls) #define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ psa_to_pk_ecdsa_errors, \ psa_pk_status_to_mbedtls) #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ /* Headers/footers for PEM files */ #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----" #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----" #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----" #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----" #define PEM_BEGIN_PUBLIC_KEY_RSA "-----BEGIN RSA PUBLIC KEY-----" #define PEM_END_PUBLIC_KEY_RSA "-----END RSA PUBLIC KEY-----" #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----" #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----" #define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----" #define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----" #define PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8 "-----BEGIN ENCRYPTED PRIVATE KEY-----" #define PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8 "-----END ENCRYPTED PRIVATE KEY-----" #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA) /** * Public function mbedtls_pk_ec() can be used to get direct access to the * wrapped ecp_keypair structure pointed to the pk_ctx. However this is not * ideal because it bypasses the PK module on the control of its internal * structure (pk_context) fields. * For backward compatibility we keep mbedtls_pk_ec() when ECP_C is defined, but * we provide 2 very similar functions when only ECP_LIGHT is enabled and not * ECP_C. * These variants embed the "ro" or "rw" keywords in their name to make the * usage of the returned pointer explicit. Of course the returned value is * const or non-const accordingly. */ static inline const mbedtls_ecp_keypair *mbedtls_pk_ec_ro(const mbedtls_pk_context pk) { switch (mbedtls_pk_get_type(&pk)) { case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: return (const mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } } static inline mbedtls_ecp_keypair *mbedtls_pk_ec_rw(const mbedtls_pk_context pk) { switch (mbedtls_pk_get_type(&pk)) { case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_PK_USE_PSA_EC_DATA */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) static inline mbedtls_ecp_group_id mbedtls_pk_get_ec_group_id(const mbedtls_pk_context *pk) { mbedtls_ecp_group_id id; #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t opaque_key_type; psa_ecc_family_t curve; if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) { return MBEDTLS_ECP_DP_NONE; } opaque_key_type = psa_get_key_type(&opaque_attrs); curve = PSA_KEY_TYPE_ECC_GET_FAMILY(opaque_key_type); id = mbedtls_ecc_group_from_psa(curve, psa_get_key_bits(&opaque_attrs)); psa_reset_key_attributes(&opaque_attrs); } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits); #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ id = mbedtls_pk_ec_ro(*pk)->grp.id; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } return id; } /* Helper for Montgomery curves */ #if defined(MBEDTLS_ECP_HAVE_CURVE25519) || defined(MBEDTLS_ECP_HAVE_CURVE448) #define MBEDTLS_PK_HAVE_RFC8410_CURVES #endif /* MBEDTLS_ECP_HAVE_CURVE25519 || MBEDTLS_ECP_DP_CURVE448 */ #define MBEDTLS_PK_IS_RFC8410_GROUP_ID(id) \ ((id == MBEDTLS_ECP_DP_CURVE25519) || (id == MBEDTLS_ECP_DP_CURVE448)) static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk) { mbedtls_ecp_group_id id = mbedtls_pk_get_ec_group_id(pk); return MBEDTLS_PK_IS_RFC8410_GROUP_ID(id); } /* * Set the group used by this key. * * [in/out] pk: in: must have been pk_setup() to an ECC type * out: will have group (curve) information set * [in] grp_in: a supported group ID (not NONE) */ int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id); /* * Set the private key material * * [in/out] pk: in: must have the group set already, see mbedtls_pk_ecc_set_group(). * out: will have the private key set. * [in] key, key_len: the raw private key (no ASN.1 wrapping). */ int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len); /* * Set the public key. * * [in/out] pk: in: must have its group set, see mbedtls_pk_ecc_set_group(). * out: will have the public key set. * [in] pub, pub_len: the raw public key (an ECPoint). * * Return: * - 0 on success; * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid * but not supported; * - another error code otherwise. */ int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len); /* * Derive a public key from its private counterpart. * Computationally intensive, only use when public key is not available. * * [in/out] pk: in: must have the private key set, see mbedtls_pk_ecc_set_key(). * out: will have the public key set. * [in] prv, prv_len: the raw private key (see note below). * [in] f_rng, p_rng: RNG function and context. * * Note: the private key information is always available from pk, * however for convenience the serialized version is also passed, * as it's available at each calling site, and useful in some configs * (as otherwise we would have to re-serialize it from the pk context). * * There are three implementations of this function: * 1. MBEDTLS_PK_USE_PSA_EC_DATA, * 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA, * 3. not MBEDTLS_USE_PSA_CRYPTO. */ int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk, const unsigned char *prv, size_t prv_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Helper for (deterministic) ECDSA */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET PSA_ALG_DETERMINISTIC_ECDSA #else #define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET PSA_ALG_ECDSA #endif #if defined(MBEDTLS_TEST_HOOKS) MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der( mbedtls_pk_context *pk, unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif #if defined(MBEDTLS_FS_IO) int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); #endif #endif /* MBEDTLS_PK_INTERNAL_H */ webfakes/src/mbedtls/library/psa_crypto_aead.h0000644000176200001440000005652714740737024021263 0ustar liggesusers/* * PSA AEAD driver entry points */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_AEAD_H #define PSA_CRYPTO_AEAD_H #include /** * \brief Process an authenticated encryption operation. * * \note The signature of this function is that of a PSA driver * aead_encrypt entry point. This function behaves as an aead_encrypt * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The AEAD algorithm to compute. * \param[in] nonce Nonce or IV to use. * \param nonce_length Size of the nonce buffer in bytes. This must * be appropriate for the selected algorithm. * The default nonce size is * PSA_AEAD_NONCE_LENGTH(key_type, alg) where * key_type is the type of key. * \param[in] additional_data Additional data that will be authenticated * but not encrypted. * \param additional_data_length Size of additional_data in bytes. * \param[in] plaintext Data that will be authenticated and encrypted. * \param plaintext_length Size of plaintext in bytes. * \param[out] ciphertext Output buffer for the authenticated and * encrypted data. The additional data is not * part of this output. For algorithms where the * encrypted data and the authentication tag are * defined as separate outputs, the * authentication tag is appended to the * encrypted data. * \param ciphertext_size Size of the ciphertext buffer in bytes. This * must be appropriate for the selected algorithm * and key: * - A sufficient output size is * PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, * plaintext_length) where key_type is the type * of key. * - PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE( * plaintext_length) evaluates to the maximum * ciphertext size of any supported AEAD * encryption. * \param[out] ciphertext_length On success, the size of the output in the * ciphertext buffer. * * \retval #PSA_SUCCESS Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * ciphertext_size is too small. * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_aead_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length); /** * \brief Process an authenticated decryption operation. * * \note The signature of this function is that of a PSA driver * aead_decrypt entry point. This function behaves as an aead_decrypt * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The AEAD algorithm to compute. * \param[in] nonce Nonce or IV to use. * \param nonce_length Size of the nonce buffer in bytes. This must * be appropriate for the selected algorithm. * The default nonce size is * PSA_AEAD_NONCE_LENGTH(key_type, alg) where * key_type is the type of key. * \param[in] additional_data Additional data that has been authenticated * but not encrypted. * \param additional_data_length Size of additional_data in bytes. * \param[in] ciphertext Data that has been authenticated and * encrypted. For algorithms where the encrypted * data and the authentication tag are defined * as separate inputs, the buffer contains * encrypted data followed by the authentication * tag. * \param ciphertext_length Size of ciphertext in bytes. * \param[out] plaintext Output buffer for the decrypted data. * \param plaintext_size Size of the plaintext buffer in bytes. This * must be appropriate for the selected algorithm * and key: * - A sufficient output size is * PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, * ciphertext_length) where key_type is the * type of key. * - PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE( * ciphertext_length) evaluates to the maximum * plaintext size of any supported AEAD * decryption. * \param[out] plaintext_length On success, the size of the output in the * plaintext buffer. * * \retval #PSA_SUCCESS Success. * \retval #PSA_ERROR_INVALID_SIGNATURE * The cipher is not authentic. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * plaintext_size is too small. * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_aead_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length); /** Set the key for a multipart authenticated encryption operation. * * \note The signature of this function is that of a PSA driver * aead_encrypt_setup entry point. This function behaves as an * aead_encrypt_setup entry point as defined in the PSA driver interface * specification for transparent drivers. * * If an error occurs at any step after a call to * mbedtls_psa_aead_encrypt_setup(), the operation is reset by the PSA core by a * call to mbedtls_psa_aead_abort(). The PSA core may call * mbedtls_psa_aead_abort() at any time after the operation has been * initialized, and is required to when the operation is no longer needed. * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #mbedtls_psa_aead_operation_t and not yet in * use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. It must be consistent with the size in bits recorded in \p attributes. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * An invalid block length was supplied. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * Failed to allocate memory for key material */ psa_status_t mbedtls_psa_aead_encrypt_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Set the key for a multipart authenticated decryption operation. * * \note The signature of this function is that of a PSA driver * aead_decrypt_setup entry point. This function behaves as an * aead_decrypt_setup entry point as defined in the PSA driver interface * specification for transparent drivers. * * If an error occurs at any step after a call to * mbedtls_psa_aead_decrypt_setup(), the PSA core resets the operation by a * call to mbedtls_psa_aead_abort(). The PSA core may call * mbedtls_psa_aead_abort() at any time after the operation has been * initialized, and is required to when the operation is no longer needed. * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #mbedtls_psa_aead_operation_t and not yet in * use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. It must be consistent with the size in bits recorded in \p attributes. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * An invalid block length was supplied. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * Failed to allocate memory for key material */ psa_status_t mbedtls_psa_aead_decrypt_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Set the nonce for an authenticated encryption or decryption operation. * * \note The signature of this function is that of a PSA driver aead_set_nonce * entry point. This function behaves as an aead_set_nonce entry point as * defined in the PSA driver interface specification for transparent * drivers. * * This function sets the nonce for the authenticated * encryption or decryption operation. * * The PSA core calls mbedtls_psa_aead_encrypt_setup() or * mbedtls_psa_aead_decrypt_setup() before calling this function. * * If this function returns an error status, the PSA core will call * mbedtls_psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param[in] nonce Buffer containing the nonce to use. * \param nonce_length Size of the nonce in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p nonce is not acceptable for the chosen algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * Algorithm previously set is not supported in this configuration of * the library. */ psa_status_t mbedtls_psa_aead_set_nonce( mbedtls_psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length); /** Declare the lengths of the message and additional data for AEAD. * * \note The signature of this function is that of a PSA driver aead_set_lengths * entry point. This function behaves as an aead_set_lengths entry point * as defined in the PSA driver interface specification for transparent * drivers. * * The PSA core calls this function before calling mbedtls_psa_aead_update_ad() * or mbedtls_psa_aead_update() if the algorithm for the operation requires it. * If the algorithm does not require it, calling this function is optional, but * if this function is called then the implementation must enforce the lengths. * * The PSA core may call this function before or after setting the nonce with * mbedtls_psa_aead_set_nonce(). * * - For #PSA_ALG_CCM, calling this function is required. * - For the other AEAD algorithms defined in this specification, calling * this function is not required. * * If this function returns an error status, the PSA core calls * mbedtls_psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param ad_length Size of the non-encrypted additional * authenticated data in bytes. * \param plaintext_length Size of the plaintext to encrypt in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * At least one of the lengths is not acceptable for the chosen * algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * Algorithm previously set is not supported in this configuration of * the library. */ psa_status_t mbedtls_psa_aead_set_lengths( mbedtls_psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length); /** Pass additional data to an active AEAD operation. * * \note The signature of this function is that of a PSA driver * aead_update_ad entry point. This function behaves as an aead_update_ad * entry point as defined in the PSA driver interface specification for * transparent drivers. * * Additional data is authenticated, but not encrypted. * * The PSA core can call this function multiple times to pass successive * fragments of the additional data. It will not call this function after * passing data to encrypt or decrypt with mbedtls_psa_aead_update(). * * Before calling this function, the PSA core will: * 1. Call either mbedtls_psa_aead_encrypt_setup() or * mbedtls_psa_aead_decrypt_setup(). * 2. Set the nonce with mbedtls_psa_aead_set_nonce(). * * If this function returns an error status, the PSA core will call * mbedtls_psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param[in] input Buffer containing the fragment of * additional data. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * Algorithm previously set is not supported in this configuration of * the library. */ psa_status_t mbedtls_psa_aead_update_ad( mbedtls_psa_aead_operation_t *operation, const uint8_t *input, size_t input_length); /** Encrypt or decrypt a message fragment in an active AEAD operation. * * \note The signature of this function is that of a PSA driver * aead_update entry point. This function behaves as an aead_update entry * point as defined in the PSA driver interface specification for * transparent drivers. * * Before calling this function, the PSA core will: * 1. Call either mbedtls_psa_aead_encrypt_setup() or * mbedtls_psa_aead_decrypt_setup(). The choice of setup function * determines whether this function encrypts or decrypts its input. * 2. Set the nonce with mbedtls_psa_aead_set_nonce(). * 3. Call mbedtls_psa_aead_update_ad() to pass all the additional data. * * If this function returns an error status, the PSA core will call * mbedtls_psa_aead_abort(). * * This function does not require the input to be aligned to any * particular block boundary. If the implementation can only process * a whole block at a time, it must consume all the input provided, but * it may delay the end of the corresponding output until a subsequent * call to mbedtls_psa_aead_update(), mbedtls_psa_aead_finish() provides * sufficient input. The amount of data that can be delayed in this way is * bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. * * \param[in,out] operation Active AEAD operation. * \param[in] input Buffer containing the message fragment to * encrypt or decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param output_size Size of the \p output buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, * \c alg, \p input_length) where * \c key_type is the type of key and \c alg is * the algorithm that were used to set up the * operation. * - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p * input_length) evaluates to the maximum * output size of any supported AEAD * algorithm. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or * #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to * determine the required buffer size. */ psa_status_t mbedtls_psa_aead_update( mbedtls_psa_aead_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Finish encrypting a message in an AEAD operation. * * \note The signature of this function is that of a PSA driver * aead_finish entry point. This function behaves as an aead_finish entry * point as defined in the PSA driver interface specification for * transparent drivers. * * The operation must have been set up by the PSA core with * mbedtls_psa_aead_encrypt_setup(). * * This function finishes the authentication of the additional data * formed by concatenating the inputs passed to preceding calls to * mbedtls_psa_aead_update_ad() with the plaintext formed by concatenating the * inputs passed to preceding calls to mbedtls_psa_aead_update(). * * This function has two output buffers: * - \p ciphertext contains trailing ciphertext that was buffered from * preceding calls to mbedtls_psa_aead_update(). * - \p tag contains the authentication tag. * * Whether or not this function returns successfully, the PSA core subsequently * calls mbedtls_psa_aead_abort() to deactivate the operation. * * \param[in,out] operation Active AEAD operation. * \param[out] ciphertext Buffer where the last part of the ciphertext * is to be written. * \param ciphertext_size Size of the \p ciphertext buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, * \c alg) where \c key_type is the type of key * and \c alg is the algorithm that were used to * set up the operation. * - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to * the maximum output size of any supported AEAD * algorithm. * \param[out] ciphertext_length On success, the number of bytes of * returned ciphertext. * \param[out] tag Buffer where the authentication tag is * to be written. * \param tag_size Size of the \p tag buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c * key_type, \c key_bits, \c alg) where * \c key_type and \c key_bits are the type and * bit-size of the key, and \c alg are the * algorithm that were used in the call to * mbedtls_psa_aead_encrypt_setup(). * - #PSA_AEAD_TAG_MAX_SIZE evaluates to the * maximum tag size of any supported AEAD * algorithm. * \param[out] tag_length On success, the number of bytes * that make up the returned tag. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p tag buffer is too small. * #PSA_AEAD_TAG_LENGTH(\c key_type, key_bits, \c alg) or * #PSA_AEAD_TAG_MAX_SIZE can be used to determine the required \p tag * buffer size. */ psa_status_t mbedtls_psa_aead_finish( mbedtls_psa_aead_operation_t *operation, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag, size_t tag_size, size_t *tag_length); /** Abort an AEAD operation. * * \note The signature of this function is that of a PSA driver * aead_abort entry point. This function behaves as an aead_abort entry * point as defined in the PSA driver interface specification for * transparent drivers. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by the PSA core by it calling * mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again. * * The PSA core may call this function any time after the operation object has * been initialized as described in #mbedtls_psa_aead_operation_t. * * In particular, calling mbedtls_psa_aead_abort() after the operation has been * terminated by a call to mbedtls_psa_aead_abort() or * mbedtls_psa_aead_finish() is safe and has no effect. * * \param[in,out] operation Initialized AEAD operation. * * \retval #PSA_SUCCESS * Success. */ psa_status_t mbedtls_psa_aead_abort( mbedtls_psa_aead_operation_t *operation); #endif /* PSA_CRYPTO_AEAD_H */ webfakes/src/mbedtls/library/x509_crl.c0000644000176200001440000005076014740737024017457 0ustar liggesusers/* * X.509 Certificate Revocation List (CRL) parsing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. * * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ #include "common.h" #if defined(MBEDTLS_X509_CRL_PARSE_C) #include "mbedtls/x509_crl.h" #include "x509_internal.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #include "mbedtls/platform.h" #if defined(MBEDTLS_HAVE_TIME) #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #else #include #endif #endif #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) #include #endif /* * Version ::= INTEGER { v1(0), v2(1) } */ static int x509_crl_get_version(unsigned char **p, const unsigned char *end, int *ver) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { *ver = 0; return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret); } return 0; } /* * X.509 CRL v2 extensions * * We currently don't parse any extension's content, but we do check that the * list of extensions is well-formed and abort on critical extensions (that * are unsupported as we don't support any extension so far) */ static int x509_get_crl_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (*p == end) { return 0; } /* * crlExtensions [0] EXPLICIT Extensions OPTIONAL * -- if present, version MUST be v2 */ if ((ret = mbedtls_x509_get_ext(p, end, ext, 0)) != 0) { return ret; } end = ext->p + ext->len; while (*p < end) { /* * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING } */ int is_critical = 0; const unsigned char *end_ext_data; size_t len; /* Get enclosing sequence tag */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_ext_data = *p + len; /* Get OID (currently ignored) */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } *p += len; /* Get optional critical */ if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Data should be octet string type */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Ignore data so far and just check its length */ *p += len; if (*p != end_ext_data) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* Abort on (unsupported) critical extensions */ if (is_critical) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * X.509 CRL v2 entry extensions (no extensions parsed yet.) */ static int x509_get_crl_entry_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; /* OPTIONAL */ if (end <= *p) { return 0; } ext->tag = **p; ext->p = *p; /* * Get CRL-entry extension sequence header * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 */ if ((ret = mbedtls_asn1_get_tag(p, end, &ext->len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { ext->p = NULL; return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end = *p + ext->len; if (end != *p + ext->len) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } while (*p < end) { if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } *p += len; } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * X.509 CRL Entries */ static int x509_get_entries(unsigned char **p, const unsigned char *end, mbedtls_x509_crl_entry *entry) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t entry_len; mbedtls_x509_crl_entry *cur_entry = entry; if (*p == end) { return 0; } if ((ret = mbedtls_asn1_get_tag(p, end, &entry_len, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return 0; } return ret; } end = *p + entry_len; while (*p < end) { size_t len2; const unsigned char *end2; cur_entry->raw.tag = **p; if ((ret = mbedtls_asn1_get_tag(p, end, &len2, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { return ret; } cur_entry->raw.p = *p; cur_entry->raw.len = len2; end2 = *p + len2; if ((ret = mbedtls_x509_get_serial(p, end2, &cur_entry->serial)) != 0) { return ret; } if ((ret = mbedtls_x509_get_time(p, end2, &cur_entry->revocation_date)) != 0) { return ret; } if ((ret = x509_get_crl_entry_ext(p, end2, &cur_entry->entry_ext)) != 0) { return ret; } if (*p < end) { cur_entry->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl_entry)); if (cur_entry->next == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } cur_entry = cur_entry->next; } } return 0; } /* * Parse one CRLs in DER format and append it to the chained list */ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *p = NULL, *end = NULL; mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; mbedtls_x509_crl *crl = chain; /* * Check for valid input */ if (crl == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } memset(&sig_params1, 0, sizeof(mbedtls_x509_buf)); memset(&sig_params2, 0, sizeof(mbedtls_x509_buf)); memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf)); /* * Add new CRL on the end of the chain if needed. */ while (crl->version != 0 && crl->next != NULL) { crl = crl->next; } if (crl->version != 0 && crl->next == NULL) { crl->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl)); if (crl->next == NULL) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_ALLOC_FAILED; } mbedtls_x509_crl_init(crl->next); crl = crl->next; } /* * Copy raw DER-encoded CRL */ if (buflen == 0) { return MBEDTLS_ERR_X509_INVALID_FORMAT; } p = mbedtls_calloc(1, buflen); if (p == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } memcpy(p, buf, buflen); crl->raw.p = p; crl->raw.len = buflen; end = p + buflen; /* * CertificateList ::= SEQUENCE { * tbsCertList TBSCertList, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_INVALID_FORMAT; } if (len != (size_t) (end - p)) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * TBSCertList ::= SEQUENCE { */ crl->tbs.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } end = p + len; crl->tbs.len = (size_t) (end - crl->tbs.p); /* * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } * -- if present, MUST be v2 * * signature AlgorithmIdentifier */ if ((ret = x509_crl_get_version(&p, end, &crl->version)) != 0 || (ret = mbedtls_x509_get_alg(&p, end, &crl->sig_oid, &sig_params1)) != 0) { mbedtls_x509_crl_free(crl); return ret; } if (crl->version < 0 || crl->version > 1) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_UNKNOWN_VERSION; } crl->version++; if ((ret = mbedtls_x509_get_sig_alg(&crl->sig_oid, &sig_params1, &crl->sig_md, &crl->sig_pk, &crl->sig_opts)) != 0) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG; } /* * issuer Name */ crl->issuer_raw.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if ((ret = mbedtls_x509_get_name(&p, p + len, &crl->issuer)) != 0) { mbedtls_x509_crl_free(crl); return ret; } crl->issuer_raw.len = (size_t) (p - crl->issuer_raw.p); /* * thisUpdate Time * nextUpdate Time OPTIONAL */ if ((ret = mbedtls_x509_get_time(&p, end, &crl->this_update)) != 0) { mbedtls_x509_crl_free(crl); return ret; } if ((ret = mbedtls_x509_get_time(&p, end, &crl->next_update)) != 0) { if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) && ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_OUT_OF_DATA))) { mbedtls_x509_crl_free(crl); return ret; } } /* * revokedCertificates SEQUENCE OF SEQUENCE { * userCertificate CertificateSerialNumber, * revocationDate Time, * crlEntryExtensions Extensions OPTIONAL * -- if present, MUST be v2 * } OPTIONAL */ if ((ret = x509_get_entries(&p, end, &crl->entry)) != 0) { mbedtls_x509_crl_free(crl); return ret; } /* * crlExtensions EXPLICIT Extensions OPTIONAL * -- if present, MUST be v2 */ if (crl->version == 2) { ret = x509_get_crl_ext(&p, end, &crl->crl_ext); if (ret != 0) { mbedtls_x509_crl_free(crl); return ret; } } if (p != end) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } end = crl->raw.p + crl->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) { mbedtls_x509_crl_free(crl); return ret; } if (crl->sig_oid.len != sig_oid2.len || memcmp(crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len) != 0 || sig_params1.len != sig_params2.len || (sig_params1.len != 0 && memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_SIG_MISMATCH; } if ((ret = mbedtls_x509_get_sig(&p, end, &crl->sig)) != 0) { mbedtls_x509_crl_free(crl); return ret; } if (p != end) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse one or more CRLs and add them to the chained list */ int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen) { #if defined(MBEDTLS_PEM_PARSE_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t use_len = 0; mbedtls_pem_context pem; int is_pem = 0; if (chain == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } do { mbedtls_pem_init(&pem); // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated // string if (buflen == 0 || buf[buflen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN X509 CRL-----", "-----END X509 CRL-----", buf, NULL, 0, &use_len); } if (ret == 0) { /* * Was PEM encoded */ is_pem = 1; buflen -= use_len; buf += use_len; if ((ret = mbedtls_x509_crl_parse_der(chain, pem.buf, pem.buflen)) != 0) { mbedtls_pem_free(&pem); return ret; } } else if (is_pem) { mbedtls_pem_free(&pem); return ret; } mbedtls_pem_free(&pem); } /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. * And a valid CRL cannot be less than 1 byte anyway. */ while (is_pem && buflen > 1); if (is_pem) { return 0; } else #endif /* MBEDTLS_PEM_PARSE_C */ return mbedtls_x509_crl_parse_der(chain, buf, buflen); } #if defined(MBEDTLS_FS_IO) /* * Load one or more CRLs and add them to the chained list */ int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_x509_crl_parse(chain, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Return an informational string about the certificate. */ #define BEFORE_COLON 14 #define BC "14" /* * Return an informational string about the CRL. */ int mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crl *crl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; char *p; const mbedtls_x509_crl_entry *entry; p = buf; n = size; ret = mbedtls_snprintf(p, n, "%sCRL version : %d", prefix, crl->version); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sissuer name : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &crl->issuer); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sthis update : " \ "%04d-%02d-%02d %02d:%02d:%02d", prefix, crl->this_update.year, crl->this_update.mon, crl->this_update.day, crl->this_update.hour, crl->this_update.min, crl->this_update.sec); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%snext update : " \ "%04d-%02d-%02d %02d:%02d:%02d", prefix, crl->next_update.year, crl->next_update.mon, crl->next_update.day, crl->next_update.hour, crl->next_update.min, crl->next_update.sec); MBEDTLS_X509_SAFE_SNPRINTF; entry = &crl->entry; ret = mbedtls_snprintf(p, n, "\n%sRevoked certificates:", prefix); MBEDTLS_X509_SAFE_SNPRINTF; while (entry != NULL && entry->raw.len != 0) { ret = mbedtls_snprintf(p, n, "\n%sserial number: ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_serial_gets(p, n, &entry->serial); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, " revocation date: " \ "%04d-%02d-%02d %02d:%02d:%02d", entry->revocation_date.year, entry->revocation_date.mon, entry->revocation_date.day, entry->revocation_date.hour, entry->revocation_date.min, entry->revocation_date.sec); MBEDTLS_X509_SAFE_SNPRINTF; entry = entry->next; } ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_sig_alg_gets(p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, crl->sig_opts); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n"); MBEDTLS_X509_SAFE_SNPRINTF; return (int) (size - n); } #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Initialize a CRL chain */ void mbedtls_x509_crl_init(mbedtls_x509_crl *crl) { memset(crl, 0, sizeof(mbedtls_x509_crl)); } /* * Unallocate all CRL data */ void mbedtls_x509_crl_free(mbedtls_x509_crl *crl) { mbedtls_x509_crl *crl_cur = crl; mbedtls_x509_crl *crl_prv; mbedtls_x509_crl_entry *entry_cur; mbedtls_x509_crl_entry *entry_prv; while (crl_cur != NULL) { #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_free(crl_cur->sig_opts); #endif mbedtls_asn1_free_named_data_list_shallow(crl_cur->issuer.next); entry_cur = crl_cur->entry.next; while (entry_cur != NULL) { entry_prv = entry_cur; entry_cur = entry_cur->next; mbedtls_zeroize_and_free(entry_prv, sizeof(mbedtls_x509_crl_entry)); } if (crl_cur->raw.p != NULL) { mbedtls_zeroize_and_free(crl_cur->raw.p, crl_cur->raw.len); } crl_prv = crl_cur; crl_cur = crl_cur->next; mbedtls_platform_zeroize(crl_prv, sizeof(mbedtls_x509_crl)); if (crl_prv != crl) { mbedtls_free(crl_prv); } } } #endif /* MBEDTLS_X509_CRL_PARSE_C */ webfakes/src/mbedtls/library/cipher_wrap.c0000644000176200001440000020407214740737024020412 0ustar liggesusers/** * \file cipher_wrap.c * * \brief Generic cipher wrapper for Mbed TLS * * \author Adriaan de Jong * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_CIPHER_C) #include "cipher_wrap.h" #include "mbedtls/error.h" #if defined(MBEDTLS_CHACHAPOLY_C) #include "mbedtls/chachapoly.h" #endif #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #endif #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #endif #if defined(MBEDTLS_ARIA_C) #include "mbedtls/aria.h" #endif #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #endif #if defined(MBEDTLS_CHACHA20_C) #include "mbedtls/chacha20.h" #endif #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" #endif #if defined(MBEDTLS_NIST_KW_C) #include "mbedtls/nist_kw.h" #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #include #endif #include "mbedtls/platform.h" enum mbedtls_cipher_base_index { #if defined(MBEDTLS_AES_C) MBEDTLS_CIPHER_BASE_INDEX_AES, #endif #if defined(MBEDTLS_ARIA_C) MBEDTLS_CIPHER_BASE_INDEX_ARIA, #endif #if defined(MBEDTLS_CAMELLIA_C) MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA, #endif #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) MBEDTLS_CIPHER_BASE_INDEX_CCM_AES, #endif #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C) MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA, #endif #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C) MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA, #endif #if defined(MBEDTLS_CHACHA20_C) MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE, #endif #if defined(MBEDTLS_CHACHAPOLY_C) MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE, #endif #if defined(MBEDTLS_DES_C) MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3, #endif #if defined(MBEDTLS_DES_C) MBEDTLS_CIPHER_BASE_INDEX_DES_EDE, #endif #if defined(MBEDTLS_DES_C) MBEDTLS_CIPHER_BASE_INDEX_DES, #endif #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) MBEDTLS_CIPHER_BASE_INDEX_GCM_AES, #endif #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C) MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA, #endif #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C) MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA, #endif #if defined(MBEDTLS_NIST_KW_C) MBEDTLS_CIPHER_BASE_INDEX_KW_AES, #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C) MBEDTLS_CIPHER_BASE_INDEX_XTS_AES, #endif /* Prevent compile failure due to empty enum */ MBEDTLS_CIPHER_BASE_PREVENT_EMPTY_ENUM }; #if defined(MBEDTLS_GCM_C) && \ (defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) /* shared by all GCM ciphers */ static void *gcm_ctx_alloc(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_gcm_context)); if (ctx != NULL) { mbedtls_gcm_init((mbedtls_gcm_context *) ctx); } return ctx; } static void gcm_ctx_free(void *ctx) { mbedtls_gcm_free(ctx); mbedtls_free(ctx); } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) && \ (defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) /* shared by all CCM ciphers */ static void *ccm_ctx_alloc(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ccm_context)); if (ctx != NULL) { mbedtls_ccm_init((mbedtls_ccm_context *) ctx); } return ctx; } static void ccm_ctx_free(void *ctx) { mbedtls_ccm_free(ctx); mbedtls_free(ctx); } #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_AES_C) static int aes_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_ecb((mbedtls_aes_context *) ctx, operation, input, output); } #if defined(MBEDTLS_CIPHER_MODE_CBC) static int aes_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_cbc((mbedtls_aes_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static int aes_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_cfb128((mbedtls_aes_context *) ctx, operation, length, iv_off, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) static int aes_crypt_ofb_wrap(void *ctx, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_ofb((mbedtls_aes_context *) ctx, length, iv_off, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static int aes_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_ctr((mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, stream_block, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) static int aes_crypt_xts_wrap(void *ctx, mbedtls_operation_t operation, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output) { mbedtls_aes_xts_context *xts_ctx = ctx; int mode; switch (operation) { case MBEDTLS_ENCRYPT: mode = MBEDTLS_AES_ENCRYPT; break; case MBEDTLS_DECRYPT: mode = MBEDTLS_AES_DECRYPT; break; default: return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return mbedtls_aes_crypt_xts(xts_ctx, mode, length, data_unit, input, output); } #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static int aes_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aes_setkey_dec((mbedtls_aes_context *) ctx, key, key_bitlen); } #endif static int aes_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aes_setkey_enc((mbedtls_aes_context *) ctx, key, key_bitlen); } static void *aes_ctx_alloc(void) { mbedtls_aes_context *aes = mbedtls_calloc(1, sizeof(mbedtls_aes_context)); if (aes == NULL) { return NULL; } mbedtls_aes_init(aes); return aes; } static void aes_ctx_free(void *ctx) { mbedtls_aes_free((mbedtls_aes_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t aes_info = { MBEDTLS_CIPHER_ID_AES, aes_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) aes_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) aes_crypt_cfb128_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) aes_crypt_ofb_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) aes_crypt_ctr_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif aes_setkey_enc_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) aes_setkey_dec_wrap, #endif aes_ctx_alloc, aes_ctx_free }; static const mbedtls_cipher_info_t aes_128_ecb_info = { "AES-128-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_AES_128_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ecb_info = { "AES-192-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_AES_192_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_ecb_info = { "AES-256-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_AES_256_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t aes_128_cbc_info = { "AES-128-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_AES_128_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_cbc_info = { "AES-192-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_AES_192_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_cbc_info = { "AES-256-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_AES_256_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const mbedtls_cipher_info_t aes_128_cfb128_info = { "AES-128-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_AES_128_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_cfb128_info = { "AES-192-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_AES_192_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_cfb128_info = { "AES-256-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_AES_256_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) static const mbedtls_cipher_info_t aes_128_ofb_info = { "AES-128-OFB", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_OFB, MBEDTLS_CIPHER_AES_128_OFB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ofb_info = { "AES-192-OFB", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_OFB, MBEDTLS_CIPHER_AES_192_OFB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_ofb_info = { "AES-256-OFB", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_OFB, MBEDTLS_CIPHER_AES_256_OFB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t aes_128_ctr_info = { "AES-128-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_AES_128_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ctr_info = { "AES-192-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_AES_192_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_ctr_info = { "AES-256-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_AES_256_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) static int xts_aes_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { mbedtls_aes_xts_context *xts_ctx = ctx; return mbedtls_aes_xts_setkey_enc(xts_ctx, key, key_bitlen); } static int xts_aes_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { mbedtls_aes_xts_context *xts_ctx = ctx; return mbedtls_aes_xts_setkey_dec(xts_ctx, key, key_bitlen); } static void *xts_aes_ctx_alloc(void) { mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc(1, sizeof(*xts_ctx)); if (xts_ctx != NULL) { mbedtls_aes_xts_init(xts_ctx); } return xts_ctx; } static void xts_aes_ctx_free(void *ctx) { mbedtls_aes_xts_context *xts_ctx = ctx; if (xts_ctx == NULL) { return; } mbedtls_aes_xts_free(xts_ctx); mbedtls_free(xts_ctx); } static const mbedtls_cipher_base_t xts_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) aes_crypt_xts_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif xts_aes_setkey_enc_wrap, xts_aes_setkey_dec_wrap, xts_aes_ctx_alloc, xts_aes_ctx_free }; static const mbedtls_cipher_info_t aes_128_xts_info = { "AES-128-XTS", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_XTS, MBEDTLS_CIPHER_AES_128_XTS, 0, MBEDTLS_CIPHER_BASE_INDEX_XTS_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_256_xts_info = { "AES-256-XTS", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 512 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_XTS, MBEDTLS_CIPHER_AES_256_XTS, 0, MBEDTLS_CIPHER_BASE_INDEX_XTS_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_XTS */ #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES) static int gcm_aes_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen); } #endif /* MBEDTLS_GCM_C && MBEDTLS_CCM_GCM_CAN_AES */ #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_base_t gcm_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif #if defined(MBEDTLS_GCM_C) gcm_aes_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) gcm_aes_setkey_wrap, #endif gcm_ctx_alloc, gcm_ctx_free, #else NULL, NULL, NULL, NULL, #endif /* MBEDTLS_GCM_C */ }; #endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_info_t aes_128_gcm_info = { "AES-128-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_gcm_info = { "AES-192-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_AES_192_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_AES }; static const mbedtls_cipher_info_t aes_256_gcm_info = { "AES-256-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_AES }; #endif #endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES) static int ccm_aes_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen); } #endif /* MBEDTLS_CCM_C && MBEDTLS_CCM_GCM_CAN_AES */ #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_base_t ccm_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif #if defined(MBEDTLS_CCM_C) ccm_aes_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) ccm_aes_setkey_wrap, #endif ccm_ctx_alloc, ccm_ctx_free, #else NULL, NULL, NULL, NULL, #endif }; #endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_info_t aes_128_ccm_info = { "AES-128-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ccm_info = { "AES-192-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_AES_192_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; static const mbedtls_cipher_info_t aes_256_ccm_info = { "AES-256-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; #endif #endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_info_t aes_128_ccm_star_no_tag_info = { "AES-128-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ccm_star_no_tag_info = { "AES-192-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; static const mbedtls_cipher_info_t aes_256_ccm_star_no_tag_info = { "AES-256-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; #endif #endif /* MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CAMELLIA_C) static int camellia_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { return mbedtls_camellia_crypt_ecb((mbedtls_camellia_context *) ctx, operation, input, output); } #if defined(MBEDTLS_CIPHER_MODE_CBC) static int camellia_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_camellia_crypt_cbc((mbedtls_camellia_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static int camellia_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_camellia_crypt_cfb128((mbedtls_camellia_context *) ctx, operation, length, iv_off, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static int camellia_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output) { return mbedtls_camellia_crypt_ctr((mbedtls_camellia_context *) ctx, length, nc_off, nonce_counter, stream_block, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static int camellia_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_camellia_setkey_dec((mbedtls_camellia_context *) ctx, key, key_bitlen); } #endif static int camellia_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_camellia_setkey_enc((mbedtls_camellia_context *) ctx, key, key_bitlen); } static void *camellia_ctx_alloc(void) { mbedtls_camellia_context *ctx; ctx = mbedtls_calloc(1, sizeof(mbedtls_camellia_context)); if (ctx == NULL) { return NULL; } mbedtls_camellia_init(ctx); return ctx; } static void camellia_ctx_free(void *ctx) { mbedtls_camellia_free((mbedtls_camellia_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t camellia_info = { MBEDTLS_CIPHER_ID_CAMELLIA, camellia_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) camellia_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) camellia_crypt_cfb128_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) camellia_crypt_ctr_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif camellia_setkey_enc_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) camellia_setkey_dec_wrap, #endif camellia_ctx_alloc, camellia_ctx_free }; static const mbedtls_cipher_info_t camellia_128_ecb_info = { "CAMELLIA-128-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_CAMELLIA_128_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ecb_info = { "CAMELLIA-192-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_CAMELLIA_192_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ecb_info = { "CAMELLIA-256-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_CAMELLIA_256_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t camellia_128_cbc_info = { "CAMELLIA-128-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_CAMELLIA_128_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_cbc_info = { "CAMELLIA-192-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_CAMELLIA_192_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_cbc_info = { "CAMELLIA-256-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_CAMELLIA_256_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const mbedtls_cipher_info_t camellia_128_cfb128_info = { "CAMELLIA-128-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_CAMELLIA_128_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_cfb128_info = { "CAMELLIA-192-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_CAMELLIA_192_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_cfb128_info = { "CAMELLIA-256-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_CAMELLIA_256_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t camellia_128_ctr_info = { "CAMELLIA-128-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_CAMELLIA_128_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ctr_info = { "CAMELLIA-192-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_CAMELLIA_192_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ctr_info = { "CAMELLIA-256-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_CAMELLIA_256_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_GCM_C) static int gcm_camellia_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, key, key_bitlen); } static const mbedtls_cipher_base_t gcm_camellia_info = { MBEDTLS_CIPHER_ID_CAMELLIA, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif gcm_camellia_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) gcm_camellia_setkey_wrap, #endif gcm_ctx_alloc, gcm_ctx_free, }; static const mbedtls_cipher_info_t camellia_128_gcm_info = { "CAMELLIA-128-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_gcm_info = { "CAMELLIA-192-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_CAMELLIA_192_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_gcm_info = { "CAMELLIA-256-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA }; #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) static int ccm_camellia_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, key, key_bitlen); } static const mbedtls_cipher_base_t ccm_camellia_info = { MBEDTLS_CIPHER_ID_CAMELLIA, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif ccm_camellia_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) ccm_camellia_setkey_wrap, #endif ccm_ctx_alloc, ccm_ctx_free, }; static const mbedtls_cipher_info_t camellia_128_ccm_info = { "CAMELLIA-128-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_CAMELLIA_128_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ccm_info = { "CAMELLIA-192-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_CAMELLIA_192_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ccm_info = { "CAMELLIA-256-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_CAMELLIA_256_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_128_ccm_star_no_tag_info = { "CAMELLIA-128-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ccm_star_no_tag_info = { "CAMELLIA-192-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ccm_star_no_tag_info = { "CAMELLIA-256-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; #endif /* MBEDTLS_CCM_C */ #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_ARIA_C) static int aria_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { (void) operation; return mbedtls_aria_crypt_ecb((mbedtls_aria_context *) ctx, input, output); } #if defined(MBEDTLS_CIPHER_MODE_CBC) static int aria_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aria_crypt_cbc((mbedtls_aria_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static int aria_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aria_crypt_cfb128((mbedtls_aria_context *) ctx, operation, length, iv_off, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static int aria_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output) { return mbedtls_aria_crypt_ctr((mbedtls_aria_context *) ctx, length, nc_off, nonce_counter, stream_block, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static int aria_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aria_setkey_dec((mbedtls_aria_context *) ctx, key, key_bitlen); } #endif static int aria_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aria_setkey_enc((mbedtls_aria_context *) ctx, key, key_bitlen); } static void *aria_ctx_alloc(void) { mbedtls_aria_context *ctx; ctx = mbedtls_calloc(1, sizeof(mbedtls_aria_context)); if (ctx == NULL) { return NULL; } mbedtls_aria_init(ctx); return ctx; } static void aria_ctx_free(void *ctx) { mbedtls_aria_free((mbedtls_aria_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t aria_info = { MBEDTLS_CIPHER_ID_ARIA, aria_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) aria_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) aria_crypt_cfb128_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) aria_crypt_ctr_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif aria_setkey_enc_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) aria_setkey_dec_wrap, #endif aria_ctx_alloc, aria_ctx_free }; static const mbedtls_cipher_info_t aria_128_ecb_info = { "ARIA-128-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_ARIA_128_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_ecb_info = { "ARIA-192-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_ARIA_192_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_ecb_info = { "ARIA-256-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_ARIA_256_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t aria_128_cbc_info = { "ARIA-128-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_ARIA_128_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_cbc_info = { "ARIA-192-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_ARIA_192_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_cbc_info = { "ARIA-256-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_ARIA_256_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const mbedtls_cipher_info_t aria_128_cfb128_info = { "ARIA-128-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_ARIA_128_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_cfb128_info = { "ARIA-192-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_ARIA_192_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_cfb128_info = { "ARIA-256-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_ARIA_256_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t aria_128_ctr_info = { "ARIA-128-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_ARIA_128_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_ctr_info = { "ARIA-192-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_ARIA_192_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_ctr_info = { "ARIA-256-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_ARIA_256_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_GCM_C) static int gcm_aria_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, key, key_bitlen); } static const mbedtls_cipher_base_t gcm_aria_info = { MBEDTLS_CIPHER_ID_ARIA, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif gcm_aria_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) gcm_aria_setkey_wrap, #endif gcm_ctx_alloc, gcm_ctx_free, }; static const mbedtls_cipher_info_t aria_128_gcm_info = { "ARIA-128-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA }; static const mbedtls_cipher_info_t aria_192_gcm_info = { "ARIA-192-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_ARIA_192_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA }; static const mbedtls_cipher_info_t aria_256_gcm_info = { "ARIA-256-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA }; #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) static int ccm_aria_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, key, key_bitlen); } static const mbedtls_cipher_base_t ccm_aria_info = { MBEDTLS_CIPHER_ID_ARIA, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif ccm_aria_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) ccm_aria_setkey_wrap, #endif ccm_ctx_alloc, ccm_ctx_free, }; static const mbedtls_cipher_info_t aria_128_ccm_info = { "ARIA-128-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_ARIA_128_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_192_ccm_info = { "ARIA-192-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_ARIA_192_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_256_ccm_info = { "ARIA-256-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_ARIA_256_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_128_ccm_star_no_tag_info = { "ARIA-128-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_192_ccm_star_no_tag_info = { "ARIA-192-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_256_ccm_star_no_tag_info = { "ARIA-256-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; #endif /* MBEDTLS_CCM_C */ #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_DES_C) static int des_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { ((void) operation); return mbedtls_des_crypt_ecb((mbedtls_des_context *) ctx, input, output); } static int des3_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { ((void) operation); return mbedtls_des3_crypt_ecb((mbedtls_des3_context *) ctx, input, output); } #if defined(MBEDTLS_CIPHER_MODE_CBC) static int des_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_des_crypt_cbc((mbedtls_des_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CBC) static int des3_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_des3_crypt_cbc((mbedtls_des3_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ static int des_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des_setkey_dec((mbedtls_des_context *) ctx, key); } static int des_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des_setkey_enc((mbedtls_des_context *) ctx, key); } static int des3_set2key_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des3_set2key_dec((mbedtls_des3_context *) ctx, key); } static int des3_set2key_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des3_set2key_enc((mbedtls_des3_context *) ctx, key); } static int des3_set3key_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des3_set3key_dec((mbedtls_des3_context *) ctx, key); } static int des3_set3key_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des3_set3key_enc((mbedtls_des3_context *) ctx, key); } static void *des_ctx_alloc(void) { mbedtls_des_context *des = mbedtls_calloc(1, sizeof(mbedtls_des_context)); if (des == NULL) { return NULL; } mbedtls_des_init(des); return des; } static void des_ctx_free(void *ctx) { mbedtls_des_free((mbedtls_des_context *) ctx); mbedtls_free(ctx); } static void *des3_ctx_alloc(void) { mbedtls_des3_context *des3; des3 = mbedtls_calloc(1, sizeof(mbedtls_des3_context)); if (des3 == NULL) { return NULL; } mbedtls_des3_init(des3); return des3; } static void des3_ctx_free(void *ctx) { mbedtls_des3_free((mbedtls_des3_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t des_info = { MBEDTLS_CIPHER_ID_DES, des_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) des_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif des_setkey_enc_wrap, des_setkey_dec_wrap, des_ctx_alloc, des_ctx_free }; static const mbedtls_cipher_info_t des_ecb_info = { "DES-ECB", 8, 0 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_DES_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_DES }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t des_cbc_info = { "DES-CBC", 8, 8 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_DES_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_DES }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ static const mbedtls_cipher_base_t des_ede_info = { MBEDTLS_CIPHER_ID_DES, des3_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) des3_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif des3_set2key_enc_wrap, des3_set2key_dec_wrap, des3_ctx_alloc, des3_ctx_free }; static const mbedtls_cipher_info_t des_ede_ecb_info = { "DES-EDE-ECB", 8, 0 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_DES_EDE_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_DES_EDE }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t des_ede_cbc_info = { "DES-EDE-CBC", 8, 8 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_DES_EDE_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_DES_EDE }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ static const mbedtls_cipher_base_t des_ede3_info = { MBEDTLS_CIPHER_ID_3DES, des3_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) des3_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif des3_set3key_enc_wrap, des3_set3key_dec_wrap, des3_ctx_alloc, des3_ctx_free }; static const mbedtls_cipher_info_t des_ede3_ecb_info = { "DES-EDE3-ECB", 8, 0 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_DES_EDE3_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3 }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t des_ede3_cbc_info = { "DES-EDE3-CBC", 8, 8 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_DES_EDE3_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3 }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_CHACHA20_C) static int chacha20_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { if (key_bitlen != 256U) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (0 != mbedtls_chacha20_setkey((mbedtls_chacha20_context *) ctx, key)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return 0; } static int chacha20_stream_wrap(void *ctx, size_t length, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_chacha20_update(ctx, length, input, output); if (ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return ret; } static void *chacha20_ctx_alloc(void) { mbedtls_chacha20_context *ctx; ctx = mbedtls_calloc(1, sizeof(mbedtls_chacha20_context)); if (ctx == NULL) { return NULL; } mbedtls_chacha20_init(ctx); return ctx; } static void chacha20_ctx_free(void *ctx) { mbedtls_chacha20_free((mbedtls_chacha20_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t chacha20_base_info = { MBEDTLS_CIPHER_ID_CHACHA20, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) chacha20_stream_wrap, #endif chacha20_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) chacha20_setkey_wrap, #endif chacha20_ctx_alloc, chacha20_ctx_free }; static const mbedtls_cipher_info_t chacha20_info = { "CHACHA20", 1, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_STREAM, MBEDTLS_CIPHER_CHACHA20, 0, MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE }; #endif /* MBEDTLS_CHACHA20_C */ #if defined(MBEDTLS_CHACHAPOLY_C) static int chachapoly_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { if (key_bitlen != 256U) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (0 != mbedtls_chachapoly_setkey((mbedtls_chachapoly_context *) ctx, key)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return 0; } static void *chachapoly_ctx_alloc(void) { mbedtls_chachapoly_context *ctx; ctx = mbedtls_calloc(1, sizeof(mbedtls_chachapoly_context)); if (ctx == NULL) { return NULL; } mbedtls_chachapoly_init(ctx); return ctx; } static void chachapoly_ctx_free(void *ctx) { mbedtls_chachapoly_free((mbedtls_chachapoly_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t chachapoly_base_info = { MBEDTLS_CIPHER_ID_CHACHA20, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif chachapoly_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) chachapoly_setkey_wrap, #endif chachapoly_ctx_alloc, chachapoly_ctx_free }; static const mbedtls_cipher_info_t chachapoly_info = { "CHACHA20-POLY1305", 1, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CHACHAPOLY, MBEDTLS_CIPHER_CHACHA20_POLY1305, 0, MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE }; #endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) static int null_crypt_stream(void *ctx, size_t length, const unsigned char *input, unsigned char *output) { ((void) ctx); memmove(output, input, length); return 0; } static int null_setkey(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) ctx); ((void) key); ((void) key_bitlen); return 0; } static void *null_ctx_alloc(void) { return (void *) 1; } static void null_ctx_free(void *ctx) { ((void) ctx); } static const mbedtls_cipher_base_t null_base_info = { MBEDTLS_CIPHER_ID_NULL, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) null_crypt_stream, #endif null_setkey, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) null_setkey, #endif null_ctx_alloc, null_ctx_free }; static const mbedtls_cipher_info_t null_cipher_info = { "NULL", 1, 0 >> MBEDTLS_IV_SIZE_SHIFT, 0 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_STREAM, MBEDTLS_CIPHER_NULL, 0, MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE }; #endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ #if defined(MBEDTLS_NIST_KW_C) static void *kw_ctx_alloc(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_nist_kw_context)); if (ctx != NULL) { mbedtls_nist_kw_init((mbedtls_nist_kw_context *) ctx); } return ctx; } static void kw_ctx_free(void *ctx) { mbedtls_nist_kw_free(ctx); mbedtls_free(ctx); } static int kw_aes_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1); } static int kw_aes_setkey_unwrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0); } static const mbedtls_cipher_base_t kw_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif kw_aes_setkey_wrap, kw_aes_setkey_unwrap, kw_ctx_alloc, kw_ctx_free, }; static const mbedtls_cipher_info_t aes_128_nist_kw_info = { "AES-128-KW", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KW, MBEDTLS_CIPHER_AES_128_KW, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_nist_kw_info = { "AES-192-KW", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KW, MBEDTLS_CIPHER_AES_192_KW, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; static const mbedtls_cipher_info_t aes_256_nist_kw_info = { "AES-256-KW", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KW, MBEDTLS_CIPHER_AES_256_KW, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; #endif static const mbedtls_cipher_info_t aes_128_nist_kwp_info = { "AES-128-KWP", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KWP, MBEDTLS_CIPHER_AES_128_KWP, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_nist_kwp_info = { "AES-192-KWP", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KWP, MBEDTLS_CIPHER_AES_192_KWP, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; static const mbedtls_cipher_info_t aes_256_nist_kwp_info = { "AES-256-KWP", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KWP, MBEDTLS_CIPHER_AES_256_KWP, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; #endif #endif /* MBEDTLS_NIST_KW_C */ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = { #if defined(MBEDTLS_AES_C) { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, #endif #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, #endif #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, #endif #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, #endif #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, #endif #endif #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, #endif #endif #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, #endif #endif #if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA) { MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, &aes_128_ccm_star_no_tag_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, &aes_192_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, &aes_256_ccm_star_no_tag_info }, #endif #endif #if defined(MBEDTLS_CAMELLIA_C) { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, #if defined(MBEDTLS_CIPHER_MODE_CBC) { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, #endif #if defined(MBEDTLS_GCM_C) { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, #endif #if defined(MBEDTLS_CCM_C) { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, { MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, &camellia_128_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, &camellia_192_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, &camellia_256_ccm_star_no_tag_info }, #endif #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_ARIA_C) { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, #if defined(MBEDTLS_CIPHER_MODE_CBC) { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, #endif #if defined(MBEDTLS_GCM_C) { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, #endif #if defined(MBEDTLS_CCM_C) { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, { MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, &aria_128_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, &aria_192_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, &aria_256_ccm_star_no_tag_info }, #endif #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_DES_C) { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, #if defined(MBEDTLS_CIPHER_MODE_CBC) { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, #endif #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_CHACHA20_C) { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, #endif #if defined(MBEDTLS_CHACHAPOLY_C) { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, #endif #if defined(MBEDTLS_NIST_KW_C) { MBEDTLS_CIPHER_AES_128_KW, &aes_128_nist_kw_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_KW, &aes_192_nist_kw_info }, { MBEDTLS_CIPHER_AES_256_KW, &aes_256_nist_kw_info }, #endif { MBEDTLS_CIPHER_AES_128_KWP, &aes_128_nist_kwp_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_KWP, &aes_192_nist_kwp_info }, { MBEDTLS_CIPHER_AES_256_KWP, &aes_256_nist_kwp_info }, #endif #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) { MBEDTLS_CIPHER_NULL, &null_cipher_info }, #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ { MBEDTLS_CIPHER_NONE, NULL } }; #define NUM_CIPHERS (sizeof(mbedtls_cipher_definitions) / \ sizeof(mbedtls_cipher_definitions[0])) int mbedtls_cipher_supported[NUM_CIPHERS]; const mbedtls_cipher_base_t *mbedtls_cipher_base_lookup_table[] = { #if defined(MBEDTLS_AES_C) [MBEDTLS_CIPHER_BASE_INDEX_AES] = &aes_info, #endif #if defined(MBEDTLS_ARIA_C) [MBEDTLS_CIPHER_BASE_INDEX_ARIA] = &aria_info, #endif #if defined(MBEDTLS_CAMELLIA_C) [MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA] = &camellia_info, #endif #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) [MBEDTLS_CIPHER_BASE_INDEX_CCM_AES] = &ccm_aes_info, #endif #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C) [MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA] = &ccm_aria_info, #endif #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C) [MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA] = &ccm_camellia_info, #endif #if defined(MBEDTLS_CHACHA20_C) [MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE] = &chacha20_base_info, #endif #if defined(MBEDTLS_CHACHAPOLY_C) [MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE] = &chachapoly_base_info, #endif #if defined(MBEDTLS_DES_C) [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3] = &des_ede3_info, #endif #if defined(MBEDTLS_DES_C) [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE] = &des_ede_info, #endif #if defined(MBEDTLS_DES_C) [MBEDTLS_CIPHER_BASE_INDEX_DES] = &des_info, #endif #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) [MBEDTLS_CIPHER_BASE_INDEX_GCM_AES] = &gcm_aes_info, #endif #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C) [MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA] = &gcm_aria_info, #endif #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C) [MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA] = &gcm_camellia_info, #endif #if defined(MBEDTLS_NIST_KW_C) [MBEDTLS_CIPHER_BASE_INDEX_KW_AES] = &kw_aes_info, #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) [MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE] = &null_base_info, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C) [MBEDTLS_CIPHER_BASE_INDEX_XTS_AES] = &xts_aes_info #endif }; #endif /* MBEDTLS_CIPHER_C */ webfakes/src/mbedtls/library/check_crypto_config.h0000644000176200001440000001302014740737024022105 0ustar liggesusers/** * \file check_crypto_config.h * * \brief Consistency checks for PSA configuration options */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * It is recommended to include this file from your crypto_config.h * in order to catch dependency issues early. */ #ifndef MBEDTLS_CHECK_CRYPTO_CONFIG_H #define MBEDTLS_CHECK_CRYPTO_CONFIG_H #if defined(PSA_WANT_ALG_CCM) && \ !(defined(PSA_WANT_KEY_TYPE_AES) || \ defined(PSA_WANT_KEY_TYPE_CAMELLIA)) #error "PSA_WANT_ALG_CCM defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_CMAC) && \ !(defined(PSA_WANT_KEY_TYPE_AES) || \ defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \ defined(PSA_WANT_KEY_TYPE_DES)) #error "PSA_WANT_ALG_CMAC defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \ !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)) #error "PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_ECDSA) && \ !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)) #error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_GCM) && \ !(defined(PSA_WANT_KEY_TYPE_AES) || \ defined(PSA_WANT_KEY_TYPE_CAMELLIA)) #error "PSA_WANT_ALG_GCM defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \ !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \ !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_OAEP) && \ !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_PSS) && \ !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites" #endif #if (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)) && \ !defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx defined, but not all prerequisites" #endif #if (defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)) && \ !defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) #error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx defined, but not all prerequisites" #endif #if (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)) && \ !defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) #error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_xxx defined, but not all prerequisites" #endif #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) #if defined(MBEDTLS_DEPRECATED_REMOVED) #error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \ future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \ symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" #elif defined(MBEDTLS_DEPRECATED_WARNING) #warning "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \ future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \ symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" #endif /* MBEDTLS_DEPRECATED_WARNING */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) #if defined(MBEDTLS_DEPRECATED_REMOVED) #error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \ future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \ symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" #elif defined(MBEDTLS_DEPRECATED_WARNING) #warning "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \ future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \ symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" #endif /* MBEDTLS_DEPRECATED_WARNING */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE) #error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE defined, but feature is not supported" #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE) #error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE defined, but feature is not supported" #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_USE_PSA_CRYPTO) && \ !(defined(PSA_WANT_ALG_SHA_1) || defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_512)) #error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) && \ !defined(PSA_WANT_ALG_SHA_256) #error "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS defined, but not all prerequisites" #endif #endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */ webfakes/src/mbedtls/library/pk_ecc.c0000644000176200001440000002133214740737024017327 0ustar liggesusers/* * ECC setters for PK. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "mbedtls/pk.h" #include "mbedtls/error.h" #include "mbedtls/ecp.h" #include "pk_internal.h" #if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS) int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) size_t ec_bits; psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits); /* group may already be initialized; if so, make sure IDs match */ if ((pk->ec_family != 0 && pk->ec_family != ec_family) || (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* set group */ pk->ec_family = ec_family; pk->ec_bits = ec_bits; return 0; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk); /* grp may already be initialized; if so, make sure IDs match */ if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE && mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* set group */ return mbedtls_ecp_group_load(&(ecp->grp), grp_id); #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_usage_t flags; psa_status_t status; psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family)); if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) { /* Do not set algorithm here because Montgomery keys cannot do ECDSA and * the PK module cannot do ECDH. When the key will be used in TLS for * ECDH, it will be exported and then re-imported with proper flags * and algorithm. */ flags = PSA_KEY_USAGE_EXPORT; } else { psa_set_key_algorithm(&attributes, MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH)); flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT; } psa_set_key_usage_flags(&attributes, flags); status = psa_import_key(&attributes, key, key_len, &pk->priv_id); return psa_pk_status_to_mbedtls(status); #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk); int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } return 0; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk, const unsigned char *prv, size_t prv_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) (void) f_rng; (void) p_rng; (void) prv; (void) prv_len; psa_status_t status; status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw), &pk->pub_raw_len); return psa_pk_status_to_mbedtls(status); #elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */ (void) f_rng; (void) p_rng; psa_status_t status; mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; size_t curve_bits; psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits); /* Import private key into PSA, from serialized input */ mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); status = psa_import_key(&key_attr, prv, prv_len, &key_id); if (status != PSA_SUCCESS) { return psa_pk_status_to_mbedtls(status); } /* Export public key from PSA */ unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t pub_len; status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len); psa_status_t destruction_status = psa_destroy_key(key_id); if (status != PSA_SUCCESS) { return psa_pk_status_to_mbedtls(status); } else if (destruction_status != PSA_SUCCESS) { return psa_pk_status_to_mbedtls(destruction_status); } /* Load serialized public key into ecp_keypair structure */ return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len); #else /* MBEDTLS_USE_PSA_CRYPTO */ (void) prv; (void) prv_len; mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* * Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case. * * Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA * functions to handle keys. However, currently psa_import_key() does not * support compressed points. In case that support was explicitly requested, * this fallback uses ECP functions to get the job done. This is the reason * why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT. * * [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group(). * out: will have the public key set. * [in] pub, pub_len: the public key as an ECPoint, * in any format supported by ECP. * * Return: * - 0 on success; * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid * but not supported; * - another error code otherwise. */ static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len) { #if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) (void) pk; (void) pub; (void) pub_len; return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ mbedtls_ecp_keypair ecp_key; mbedtls_ecp_group_id ecp_group_id; int ret; ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits); mbedtls_ecp_keypair_init(&ecp_key); ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id); if (ret != 0) { goto exit; } ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q, pub, pub_len); if (ret != 0) { goto exit; } ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &pk->pub_raw_len, pk->pub_raw, sizeof(pk->pub_raw)); exit: mbedtls_ecp_keypair_free(&ecp_key); return ret; #endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* Load the key */ if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) { /* Format directly supported by PSA: * - non-Weierstrass curves that only have one format; * - uncompressed format for Weierstrass curves. */ if (pub_len > sizeof(pk->pub_raw)) { return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } memcpy(pk->pub_raw, pub, pub_len); pk->pub_raw_len = pub_len; } else { /* Other format, try the fallback */ int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len); if (ret != 0) { return ret; } } /* Validate the key by trying to import it */ mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_usage_flags(&key_attrs, 0); psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)); psa_set_key_bits(&key_attrs, pk->ec_bits); if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len, &key_id) != PSA_SUCCESS) || (psa_destroy_key(key_id) != PSA_SUCCESS)) { return MBEDTLS_ERR_PK_INVALID_PUBKEY; } return 0; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ int ret; mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx; ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len); if (ret != 0) { return ret; } return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q); #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } #endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */ webfakes/src/mbedtls/library/padlock.c0000644000176200001440000001033114740737024017515 0ustar liggesusers/* * VIA PadLock support functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * This implementation is based on the VIA PadLock Programming Guide: * * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ * programming_guide.pdf */ #include "common.h" #if defined(MBEDTLS_PADLOCK_C) #include "padlock.h" #include #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) /* * PadLock detection routine */ int mbedtls_padlock_has_support(int feature) { static int flags = -1; int ebx = 0, edx = 0; if (flags == -1) { asm ("movl %%ebx, %0 \n\t" "movl $0xC0000000, %%eax \n\t" "cpuid \n\t" "cmpl $0xC0000001, %%eax \n\t" "movl $0, %%edx \n\t" "jb 1f \n\t" "movl $0xC0000001, %%eax \n\t" "cpuid \n\t" "1: \n\t" "movl %%edx, %1 \n\t" "movl %2, %%ebx \n\t" : "=m" (ebx), "=m" (edx) : "m" (ebx) : "eax", "ecx", "edx"); flags = edx; } return flags & feature; } /* * PadLock AES-ECB block en(de)cryption */ int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { int ebx = 0; uint32_t *rk; uint32_t *blk; uint32_t *ctrl; unsigned char buf[256]; rk = ctx->buf + ctx->rk_offset; if (((long) rk & 15) != 0) { return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED; } blk = MBEDTLS_PADLOCK_ALIGN16(buf); memcpy(blk, input, 16); ctrl = blk + 4; *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode^1) - 10) << 9); asm ("pushfl \n\t" "popfl \n\t" "movl %%ebx, %0 \n\t" "movl $1, %%ecx \n\t" "movl %2, %%edx \n\t" "movl %3, %%ebx \n\t" "movl %4, %%esi \n\t" "movl %4, %%edi \n\t" ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" "movl %1, %%ebx \n\t" : "=m" (ebx) : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) : "memory", "ecx", "edx", "esi", "edi"); memcpy(output, blk, 16); return 0; } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * PadLock AES-CBC buffer en(de)cryption */ int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int ebx = 0; size_t count; uint32_t *rk; uint32_t *iw; uint32_t *ctrl; unsigned char buf[256]; rk = ctx->buf + ctx->rk_offset; if (((long) input & 15) != 0 || ((long) output & 15) != 0 || ((long) rk & 15) != 0) { return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED; } iw = MBEDTLS_PADLOCK_ALIGN16(buf); memcpy(iw, iv, 16); ctrl = iw + 4; *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode ^ 1) - 10) << 9); count = (length + 15) >> 4; asm ("pushfl \n\t" "popfl \n\t" "movl %%ebx, %0 \n\t" "movl %2, %%ecx \n\t" "movl %3, %%edx \n\t" "movl %4, %%ebx \n\t" "movl %5, %%esi \n\t" "movl %6, %%edi \n\t" "movl %7, %%eax \n\t" ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" "movl %1, %%ebx \n\t" : "=m" (ebx) : "m" (ebx), "m" (count), "m" (ctrl), "m" (rk), "m" (input), "m" (output), "m" (iw) : "memory", "eax", "ecx", "edx", "esi", "edi"); memcpy(iv, iw, 16); return 0; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_VIA_PADLOCK_HAVE_CODE */ #endif /* MBEDTLS_PADLOCK_C */ webfakes/src/mbedtls/library/timing.c0000644000176200001440000000760414740737024017400 0ustar liggesusers/* * Portable interface to the CPU cycle counter * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_TIMING_C) #include "mbedtls/timing.h" #if !defined(MBEDTLS_TIMING_ALT) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ !defined(__HAIKU__) && !defined(__midipix__) #error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in mbedtls_config.h" #endif #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #include struct _hr_time { LARGE_INTEGER start; }; #else #include #include #include /* time.h should be included independently of MBEDTLS_HAVE_TIME. If the * platform matches the ifdefs above, it will be used. */ #include #include struct _hr_time { struct timeval start; }; #endif /* _WIN32 && !EFIX64 && !EFI32 */ /** * \brief Return the elapsed time in milliseconds * * \warning May change without notice * * \param val points to a timer structure * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. * * \return Elapsed time since the previous reset in ms. When * restarting, this is always 0. * * \note To initialize a timer, call this function with reset=1. * * Determining the elapsed time and resetting the timer is not * atomic on all platforms, so after the sequence * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = * get_timer(0) }` the value time1+time2 is only approximately * the delay since the first reset. */ #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) { struct _hr_time *t = (struct _hr_time *) val; if (reset) { QueryPerformanceCounter(&t->start); return 0; } else { unsigned long delta; LARGE_INTEGER now, hfreq; QueryPerformanceCounter(&now); QueryPerformanceFrequency(&hfreq); delta = (unsigned long) ((now.QuadPart - t->start.QuadPart) * 1000ul / hfreq.QuadPart); return delta; } } #else /* _WIN32 && !EFIX64 && !EFI32 */ unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) { struct _hr_time *t = (struct _hr_time *) val; if (reset) { gettimeofday(&t->start, NULL); return 0; } else { unsigned long delta; struct timeval now; gettimeofday(&now, NULL); delta = (now.tv_sec - t->start.tv_sec) * 1000ul + (now.tv_usec - t->start.tv_usec) / 1000; return delta; } } #endif /* _WIN32 && !EFIX64 && !EFI32 */ /* * Set delays to watch */ void mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms) { mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; ctx->int_ms = int_ms; ctx->fin_ms = fin_ms; if (fin_ms != 0) { (void) mbedtls_timing_get_timer(&ctx->timer, 1); } } /* * Get number of delays expired */ int mbedtls_timing_get_delay(void *data) { mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; unsigned long elapsed_ms; if (ctx->fin_ms == 0) { return -1; } elapsed_ms = mbedtls_timing_get_timer(&ctx->timer, 0); if (elapsed_ms >= ctx->fin_ms) { return 2; } if (elapsed_ms >= ctx->int_ms) { return 1; } return 0; } /* * Get the final delay. */ uint32_t mbedtls_timing_get_final_delay( const mbedtls_timing_delay_context *data) { return data->fin_ms; } #endif /* !MBEDTLS_TIMING_ALT */ #endif /* MBEDTLS_TIMING_C */ webfakes/src/mbedtls/library/mps_reader.c0000644000176200001440000004573214740737024020236 0ustar liggesusers/* * Message Processing Stack, Reader implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "mps_reader.h" #include "mps_common.h" #include "mps_trace.h" #include #if defined(MBEDTLS_MPS_ENABLE_TRACE) static int mbedtls_mps_trace_id = MBEDTLS_MPS_TRACE_BIT_READER; #endif /* MBEDTLS_MPS_ENABLE_TRACE */ /* * GENERAL NOTE ON CODING STYLE * * The following code intentionally separates memory loads * and stores from other operations (arithmetic or branches). * This leads to the introduction of many local variables * and significantly increases the C-code line count, but * should not increase the size of generated assembly. * * The reason for this is twofold: * (1) It will ease verification efforts using the VST * (Verified Software Toolchain) * whose program logic cannot directly reason * about instructions containing a load or store in * addition to other operations (e.g. *p = *q or * tmp = *p + 42). * (2) Operating on local variables and writing the results * back to the target contexts on success only * allows to maintain structure invariants even * on failure - this in turn has two benefits: * (2.a) If for some reason an error code is not caught * and operation continues, functions are nonetheless * called with sane contexts, reducing the risk * of dangerous behavior. * (2.b) Randomized testing is easier if structures * remain intact even in the face of failing * and/or non-sensical calls. * Moreover, it might even reduce code-size because * the compiler need not write back temporary results * to memory in case of failure. * */ static inline int mps_reader_is_accumulating( mbedtls_mps_reader const *rd) { mbedtls_mps_size_t acc_remaining; if (rd->acc == NULL) { return 0; } acc_remaining = rd->acc_share.acc_remaining; return acc_remaining > 0; } static inline int mps_reader_is_producing( mbedtls_mps_reader const *rd) { unsigned char *frag = rd->frag; return frag == NULL; } static inline int mps_reader_is_consuming( mbedtls_mps_reader const *rd) { return !mps_reader_is_producing(rd); } static inline mbedtls_mps_size_t mps_reader_get_fragment_offset( mbedtls_mps_reader const *rd) { unsigned char *acc = rd->acc; mbedtls_mps_size_t frag_offset; if (acc == NULL) { return 0; } frag_offset = rd->acc_share.frag_offset; return frag_offset; } static inline mbedtls_mps_size_t mps_reader_serving_from_accumulator( mbedtls_mps_reader const *rd) { mbedtls_mps_size_t frag_offset, end; frag_offset = mps_reader_get_fragment_offset(rd); end = rd->end; return end < frag_offset; } static inline void mps_reader_zero(mbedtls_mps_reader *rd) { /* A plain memset() would likely be more efficient, * but the current way of zeroing makes it harder * to overlook fields which should not be zero-initialized. * It's also more suitable for FV efforts since it * doesn't require reasoning about structs being * interpreted as unstructured binary blobs. */ static mbedtls_mps_reader const zero = { .frag = NULL, .frag_len = 0, .commit = 0, .end = 0, .pending = 0, .acc = NULL, .acc_len = 0, .acc_available = 0, .acc_share = { .acc_remaining = 0 } }; *rd = zero; } int mbedtls_mps_reader_init(mbedtls_mps_reader *rd, unsigned char *acc, mbedtls_mps_size_t acc_len) { MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_init"); MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "* Accumulator size: %u bytes", (unsigned) acc_len); mps_reader_zero(rd); rd->acc = acc; rd->acc_len = acc_len; MBEDTLS_MPS_TRACE_RETURN(0); } int mbedtls_mps_reader_free(mbedtls_mps_reader *rd) { MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_free"); mps_reader_zero(rd); MBEDTLS_MPS_TRACE_RETURN(0); } int mbedtls_mps_reader_feed(mbedtls_mps_reader *rd, unsigned char *new_frag, mbedtls_mps_size_t new_frag_len) { mbedtls_mps_size_t copy_to_acc; MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_feed"); MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "* Fragment length: %u bytes", (unsigned) new_frag_len); if (new_frag == NULL) { MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_INVALID_ARG); } MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_producing( rd), "mbedtls_mps_reader_feed() requires reader to be in producing mode"); if (mps_reader_is_accumulating(rd)) { unsigned char *acc = rd->acc; mbedtls_mps_size_t acc_remaining = rd->acc_share.acc_remaining; mbedtls_mps_size_t acc_available = rd->acc_available; /* Skip over parts of the accumulator that have already been filled. */ acc += acc_available; copy_to_acc = acc_remaining; if (copy_to_acc > new_frag_len) { copy_to_acc = new_frag_len; } /* Copy new contents to accumulator. */ memcpy(acc, new_frag, copy_to_acc); MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "Copy new data of size %u of %u into accumulator at offset %u", (unsigned) copy_to_acc, (unsigned) new_frag_len, (unsigned) acc_available); /* Check if, with the new fragment, we have enough data. */ acc_remaining -= copy_to_acc; if (acc_remaining > 0) { /* We need to accumulate more data. Stay in producing mode. */ acc_available += copy_to_acc; rd->acc_share.acc_remaining = acc_remaining; rd->acc_available = acc_available; MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_NEED_MORE); } /* We have filled the accumulator: Move to consuming mode. */ MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "Enough data available to serve user request"); /* Remember overlap of accumulator and fragment. */ rd->acc_share.frag_offset = acc_available; acc_available += copy_to_acc; rd->acc_available = acc_available; } else { /* Not accumulating */ rd->acc_share.frag_offset = 0; } rd->frag = new_frag; rd->frag_len = new_frag_len; rd->commit = 0; rd->end = 0; MBEDTLS_MPS_TRACE_RETURN(0); } int mbedtls_mps_reader_get(mbedtls_mps_reader *rd, mbedtls_mps_size_t desired, unsigned char **buffer, mbedtls_mps_size_t *buflen) { unsigned char *frag; mbedtls_mps_size_t frag_len, frag_offset, end, frag_fetched, frag_remaining; MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_get"); MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "* Bytes requested: %u", (unsigned) desired); MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_consuming( rd), "mbedtls_mps_reader_get() requires reader to be in consuming mode"); end = rd->end; frag_offset = mps_reader_get_fragment_offset(rd); /* Check if we're still serving from the accumulator. */ if (mps_reader_serving_from_accumulator(rd)) { /* Illustration of supported and unsupported cases: * * - Allowed #1 * * +-----------------------------------+ * | frag | * +-----------------------------------+ * * end end+desired * | | * +-----v-------v-------------+ * | acc | * +---------------------------+ * | | * frag_offset acc_available * * - Allowed #2 * * +-----------------------------------+ * | frag | * +-----------------------------------+ * * end end+desired * | | * +----------v----------------v * | acc | * +---------------------------+ * | | * frag_offset acc_available * * - Not allowed #1 (could be served, but we don't actually use it): * * +-----------------------------------+ * | frag | * +-----------------------------------+ * * end end+desired * | | * +------v-------------v------+ * | acc | * +---------------------------+ * | | * frag_offset acc_available * * * - Not allowed #2 (can't be served with a contiguous buffer): * * +-----------------------------------+ * | frag | * +-----------------------------------+ * * end end + desired * | | * +------v--------------------+ v * | acc | * +---------------------------+ * | | * frag_offset acc_available * * In case of Allowed #2 we're switching to serve from * `frag` starting from the next call to mbedtls_mps_reader_get(). */ unsigned char *acc; MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "Serve the request from the accumulator"); if (frag_offset - end < desired) { mbedtls_mps_size_t acc_available; acc_available = rd->acc_available; if (acc_available - end != desired) { /* It might be possible to serve some of these situations by * making additional space in the accumulator, removing those * parts that have already been committed. * On the other hand, this brings additional complexity and * enlarges the code size, while there doesn't seem to be a use * case where we don't attempt exactly the same `get` calls when * resuming on a reader than what we tried before pausing it. * If we believe we adhere to this restricted usage throughout * the library, this check is a good opportunity to * validate this. */ MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS); } } acc = rd->acc; acc += end; *buffer = acc; if (buflen != NULL) { *buflen = desired; } end += desired; rd->end = end; rd->pending = 0; MBEDTLS_MPS_TRACE_RETURN(0); } /* Attempt to serve the request from the current fragment */ MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "Serve the request from the current fragment."); frag_len = rd->frag_len; frag_fetched = end - frag_offset; /* The amount of data from the current * fragment that has already been passed * to the user. */ frag_remaining = frag_len - frag_fetched; /* Remaining data in fragment */ /* Check if we can serve the read request from the fragment. */ if (frag_remaining < desired) { MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "There's not enough data in the current fragment " "to serve the request."); /* There's not enough data in the current fragment, * so either just RETURN what we have or fail. */ if (buflen == NULL) { if (frag_remaining > 0) { rd->pending = desired - frag_remaining; MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "Remember to collect %u bytes before re-opening", (unsigned) rd->pending); } MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_OUT_OF_DATA); } desired = frag_remaining; } /* There's enough data in the current fragment to serve the * (potentially modified) read request. */ frag = rd->frag; frag += frag_fetched; *buffer = frag; if (buflen != NULL) { *buflen = desired; } end += desired; rd->end = end; rd->pending = 0; MBEDTLS_MPS_TRACE_RETURN(0); } int mbedtls_mps_reader_commit(mbedtls_mps_reader *rd) { mbedtls_mps_size_t end; MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_commit"); MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_consuming( rd), "mbedtls_mps_reader_commit() requires reader to be in consuming mode"); end = rd->end; rd->commit = end; MBEDTLS_MPS_TRACE_RETURN(0); } int mbedtls_mps_reader_reclaim(mbedtls_mps_reader *rd, int *paused) { unsigned char *frag, *acc; mbedtls_mps_size_t pending, commit; mbedtls_mps_size_t acc_len, frag_offset, frag_len; MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_reclaim"); if (paused != NULL) { *paused = 0; } MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_consuming( rd), "mbedtls_mps_reader_reclaim() requires reader to be in consuming mode"); frag = rd->frag; acc = rd->acc; pending = rd->pending; commit = rd->commit; frag_len = rd->frag_len; frag_offset = mps_reader_get_fragment_offset(rd); if (pending == 0) { MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "No unsatisfied read-request has been logged."); /* Check if there's data left to be consumed. */ if (commit < frag_offset || commit - frag_offset < frag_len) { MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "There is data left to be consumed."); rd->end = commit; MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_DATA_LEFT); } rd->acc_available = 0; rd->acc_share.acc_remaining = 0; MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "Fragment has been fully processed and committed."); } else { int overflow; mbedtls_mps_size_t acc_backup_offset; mbedtls_mps_size_t acc_backup_len; mbedtls_mps_size_t frag_backup_offset; mbedtls_mps_size_t frag_backup_len; mbedtls_mps_size_t backup_len; mbedtls_mps_size_t acc_len_needed; MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "There has been an unsatisfied read with %u bytes overhead.", (unsigned) pending); if (acc == NULL) { MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "No accumulator present"); MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR); } acc_len = rd->acc_len; /* Check if the upper layer has already fetched * and committed the contents of the accumulator. */ if (commit < frag_offset) { /* No, accumulator is still being processed. */ frag_backup_offset = 0; frag_backup_len = frag_len; acc_backup_offset = commit; acc_backup_len = frag_offset - commit; } else { /* Yes, the accumulator is already processed. */ frag_backup_offset = commit - frag_offset; frag_backup_len = frag_len - frag_backup_offset; acc_backup_offset = 0; acc_backup_len = 0; } backup_len = acc_backup_len + frag_backup_len; acc_len_needed = backup_len + pending; overflow = 0; overflow |= (backup_len < acc_backup_len); overflow |= (acc_len_needed < backup_len); if (overflow || acc_len < acc_len_needed) { /* Except for the different return code, we behave as if * there hadn't been a call to mbedtls_mps_reader_get() * since the last commit. */ rd->end = commit; rd->pending = 0; MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR, "The accumulator is too small to handle the backup."); MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR, "* Size: %u", (unsigned) acc_len); MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR, "* Needed: %u (%u + %u)", (unsigned) acc_len_needed, (unsigned) backup_len, (unsigned) pending); MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL); } MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "Fragment backup: %u", (unsigned) frag_backup_len); MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "Accumulator backup: %u", (unsigned) acc_backup_len); /* Move uncommitted parts from the accumulator to the front * of the accumulator. */ memmove(acc, acc + acc_backup_offset, acc_backup_len); /* Copy uncommitted parts of the current fragment to the * accumulator. */ memcpy(acc + acc_backup_len, frag + frag_backup_offset, frag_backup_len); rd->acc_available = backup_len; rd->acc_share.acc_remaining = pending; if (paused != NULL) { *paused = 1; } } rd->frag = NULL; rd->frag_len = 0; rd->commit = 0; rd->end = 0; rd->pending = 0; MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT, "Final state: aa %u, al %u, ar %u", (unsigned) rd->acc_available, (unsigned) rd->acc_len, (unsigned) rd->acc_share.acc_remaining); MBEDTLS_MPS_TRACE_RETURN(0); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ webfakes/src/mbedtls/library/pk_wrap.h0000644000176200001440000001123714740737024017556 0ustar liggesusers/** * \file pk_wrap.h * * \brief Public Key abstraction layer: wrapper functions */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_WRAP_H #define MBEDTLS_PK_WRAP_H #include "mbedtls/build_info.h" #include "mbedtls/pk.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif struct mbedtls_pk_info_t { /** Public key type */ mbedtls_pk_type_t type; /** Type name */ const char *name; /** Get key size in bits */ size_t (*get_bitlen)(mbedtls_pk_context *pk); /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ int (*can_do)(mbedtls_pk_type_t type); /** Verify signature */ int (*verify_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len); /** Make signature */ int (*sign_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** Verify signature (restartable) */ int (*verify_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx); /** Make signature (restartable) */ int (*sign_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** Decrypt message */ int (*decrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Encrypt message */ int (*encrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Check public-private key pair */ int (*check_pair_func)(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Allocate a new context */ void * (*ctx_alloc_func)(void); /** Free the given context */ void (*ctx_free_func)(void *ctx); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** Allocate the restart context */ void *(*rs_alloc_func)(void); /** Free the restart context */ void (*rs_free_func)(void *rs_ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** Interface with the debug module */ void (*debug_func)(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items); }; #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* Container for RSA-alt */ typedef struct { void *key; mbedtls_pk_rsa_alt_decrypt_func decrypt_func; mbedtls_pk_rsa_alt_sign_func sign_func; mbedtls_pk_rsa_alt_key_len_func key_len_func; } mbedtls_rsa_alt_context; #endif #if defined(MBEDTLS_RSA_C) extern const mbedtls_pk_info_t mbedtls_rsa_info; #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) extern const mbedtls_pk_info_t mbedtls_eckey_info; extern const mbedtls_pk_info_t mbedtls_eckeydh_info; #endif #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) extern const mbedtls_pk_info_t mbedtls_ecdsa_info; #endif #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) extern const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info; extern const mbedtls_pk_info_t mbedtls_rsa_opaque_info; #if defined(MBEDTLS_RSA_C) int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md, mbedtls_rsa_context *rsa_ctx, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len); #endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_WRAP_H */ webfakes/src/mbedtls/library/chachapoly.c0000644000176200001440000003425014740737024020221 0ustar liggesusers/** * \file chachapoly.c * * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_CHACHAPOLY_C) #include "mbedtls/chachapoly.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_CHACHAPOLY_ALT) #define CHACHAPOLY_STATE_INIT (0) #define CHACHAPOLY_STATE_AAD (1) #define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */ #define CHACHAPOLY_STATE_FINISHED (3) /** * \brief Adds nul bytes to pad the AAD for Poly1305. * * \param ctx The ChaCha20-Poly1305 context. */ static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx) { uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U); unsigned char zeroes[15]; if (partial_block_len == 0U) { return 0; } memset(zeroes, 0, sizeof(zeroes)); return mbedtls_poly1305_update(&ctx->poly1305_ctx, zeroes, 16U - partial_block_len); } /** * \brief Adds nul bytes to pad the ciphertext for Poly1305. * * \param ctx The ChaCha20-Poly1305 context. */ static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx) { uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U); unsigned char zeroes[15]; if (partial_block_len == 0U) { return 0; } memset(zeroes, 0, sizeof(zeroes)); return mbedtls_poly1305_update(&ctx->poly1305_ctx, zeroes, 16U - partial_block_len); } void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx) { mbedtls_chacha20_init(&ctx->chacha20_ctx); mbedtls_poly1305_init(&ctx->poly1305_ctx); ctx->aad_len = 0U; ctx->ciphertext_len = 0U; ctx->state = CHACHAPOLY_STATE_INIT; ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; } void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx) { if (ctx == NULL) { return; } mbedtls_chacha20_free(&ctx->chacha20_ctx); mbedtls_poly1305_free(&ctx->poly1305_ctx); ctx->aad_len = 0U; ctx->ciphertext_len = 0U; ctx->state = CHACHAPOLY_STATE_INIT; ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; } int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx, const unsigned char key[32]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key); return ret; } int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx, const unsigned char nonce[12], mbedtls_chachapoly_mode_t mode) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char poly1305_key[64]; /* Set counter = 0, will be update to 1 when generating Poly1305 key */ ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U); if (ret != 0) { goto cleanup; } /* Generate the Poly1305 key by getting the ChaCha20 keystream output with * counter = 0. This is the same as encrypting a buffer of zeroes. * Only the first 256-bits (32 bytes) of the key is used for Poly1305. * The other 256 bits are discarded. */ memset(poly1305_key, 0, sizeof(poly1305_key)); ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key), poly1305_key, poly1305_key); if (ret != 0) { goto cleanup; } ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key); if (ret == 0) { ctx->aad_len = 0U; ctx->ciphertext_len = 0U; ctx->state = CHACHAPOLY_STATE_AAD; ctx->mode = mode; } cleanup: mbedtls_platform_zeroize(poly1305_key, 64U); return ret; } int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx, const unsigned char *aad, size_t aad_len) { if (ctx->state != CHACHAPOLY_STATE_AAD) { return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE; } ctx->aad_len += aad_len; return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len); } int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx, size_t len, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ctx->state != CHACHAPOLY_STATE_AAD) && (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) { return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE; } if (ctx->state == CHACHAPOLY_STATE_AAD) { ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; ret = chachapoly_pad_aad(ctx); if (ret != 0) { return ret; } } ctx->ciphertext_len += len; if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) { ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output); if (ret != 0) { return ret; } ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len); if (ret != 0) { return ret; } } else { /* DECRYPT */ ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len); if (ret != 0) { return ret; } ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output); if (ret != 0) { return ret; } } return 0; } int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx, unsigned char mac[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char len_block[16]; if (ctx->state == CHACHAPOLY_STATE_INIT) { return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE; } if (ctx->state == CHACHAPOLY_STATE_AAD) { ret = chachapoly_pad_aad(ctx); if (ret != 0) { return ret; } } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) { ret = chachapoly_pad_ciphertext(ctx); if (ret != 0) { return ret; } } ctx->state = CHACHAPOLY_STATE_FINISHED; /* The lengths of the AAD and ciphertext are processed by * Poly1305 as the final 128-bit block, encoded as little-endian integers. */ MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0); MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8); ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U); if (ret != 0) { return ret; } ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac); return ret; } static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx, mbedtls_chachapoly_mode_t mode, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char *input, unsigned char *output, unsigned char tag[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_chachapoly_starts(ctx, nonce, mode); if (ret != 0) { goto cleanup; } ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len); if (ret != 0) { goto cleanup; } ret = mbedtls_chachapoly_update(ctx, length, input, output); if (ret != 0) { goto cleanup; } ret = mbedtls_chachapoly_finish(ctx, tag); cleanup: return ret; } int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char *input, unsigned char *output, unsigned char tag[16]) { return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, length, nonce, aad, aad_len, input, output, tag); } int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char tag[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char check_tag[16]; int diff; if ((ret = chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, aad, aad_len, input, output, check_tag)) != 0) { return ret; } /* Check tag in "constant-time" */ diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag)); if (diff != 0) { mbedtls_platform_zeroize(output, length); return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED; } return 0; } #endif /* MBEDTLS_CHACHAPOLY_ALT */ #if defined(MBEDTLS_SELF_TEST) static const unsigned char test_key[1][32] = { { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f } }; static const unsigned char test_nonce[1][12] = { { 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ } }; static const unsigned char test_aad[1][12] = { { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 } }; static const size_t test_aad_len[1] = { 12U }; static const unsigned char test_input[1][114] = { { 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x74, 0x2e } }; static const unsigned char test_output[1][114] = { { 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, 0x61, 0x16 } }; static const size_t test_input_len[1] = { 114U }; static const unsigned char test_mac[1][16] = { { 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 } }; /* Make sure no other definition is already present. */ #undef ASSERT #define ASSERT(cond, args) \ do \ { \ if (!(cond)) \ { \ if (verbose != 0) \ mbedtls_printf args; \ \ return -1; \ } \ } \ while (0) int mbedtls_chachapoly_self_test(int verbose) { mbedtls_chachapoly_context ctx; unsigned i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char output[200]; unsigned char mac[16]; for (i = 0U; i < 1U; i++) { if (verbose != 0) { mbedtls_printf(" ChaCha20-Poly1305 test %u ", i); } mbedtls_chachapoly_init(&ctx); ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]); ASSERT(0 == ret, ("setkey() error code: %i\n", ret)); ret = mbedtls_chachapoly_encrypt_and_tag(&ctx, test_input_len[i], test_nonce[i], test_aad[i], test_aad_len[i], test_input[i], output, mac); ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret)); ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]), ("failure (wrong output)\n")); ASSERT(0 == memcmp(mac, test_mac[i], 16U), ("failure (wrong MAC)\n")); mbedtls_chachapoly_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_CHACHAPOLY_C */ webfakes/src/mbedtls/library/psa_crypto_pake.h0000644000176200001440000001613314740737024021276 0ustar liggesusers/* * PSA PAKE layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_PAKE_H #define PSA_CRYPTO_PAKE_H #include /** Set the session information for a password-authenticated key exchange. * * \note The signature of this function is that of a PSA driver * pake_setup entry point. This function behaves as a pake_setup * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in,out] operation The operation object to set up. It must have * been initialized but not set up yet. * \param[in] inputs Inputs required for PAKE operation (role, password, * key lifetime, cipher suite) * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * The algorithm in \p cipher_suite is not a supported PAKE algorithm, * or the PAKE primitive in \p cipher_suite is not supported or not * compatible with the PAKE algorithm, or the hash algorithm in * \p cipher_suite is not supported or not compatible with the PAKE * algorithm and primitive. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation, const psa_crypto_driver_pake_inputs_t *inputs); /** Get output for a step of a password-authenticated key exchange. * * \note The signature of this function is that of a PSA driver * pake_output entry point. This function behaves as a pake_output * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in,out] operation Active PAKE operation. * \param step The step of the algorithm for which the output is * requested. * \param[out] output Buffer where the output is to be written in the * format appropriate for this driver \p step. Refer to * the documentation of psa_crypto_driver_pake_step_t for * more information. * \param output_size Size of the \p output buffer in bytes. This must * be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \p * primitive, \p step) where \p alg and * \p primitive are the PAKE algorithm and primitive * in the operation's cipher suite, and \p step is * the output step. * * \param[out] output_length On success, the number of bytes of the returned * output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length); /** Provide input for a step of a password-authenticated key exchange. * * \note The signature of this function is that of a PSA driver * pake_input entry point. This function behaves as a pake_input * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \note The core checks that input_length is smaller than PSA_PAKE_INPUT_MAX_SIZE. * * \param[in,out] operation Active PAKE operation. * \param step The driver step for which the input is provided. * \param[in] input Buffer containing the input in the format * appropriate for this \p step. Refer to the * documentation of psa_crypto_driver_pake_step_t * for more information. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_SIGNATURE * The verification fails for a zero-knowledge input step. * \retval #PSA_ERROR_INVALID_ARGUMENT * the \p input is not valid for the \p operation's algorithm, cipher suite * or \p step. * \retval #PSA_ERROR_NOT_SUPPORTED * the \p input is not supported for the \p operation's algorithm, cipher * suite or \p step. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, const uint8_t *input, size_t input_length); /** Get implicitly confirmed shared secret from a PAKE. * * \note The signature of this function is that of a PSA driver * pake_get_implicit_key entry point. This function behaves as a * pake_get_implicit_key entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Active PAKE operation. * \param[out] output Output buffer for implicit key. * \param output_size Size of the output buffer in bytes. * \param[out] output_length On success, the number of bytes of the implicit key. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * Input from a PAKE is not supported by the algorithm in the \p output * key derivation operation. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t mbedtls_psa_pake_get_implicit_key( mbedtls_psa_pake_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length); /** Abort a PAKE operation. * * \note The signature of this function is that of a PSA driver * pake_abort entry point. This function behaves as a pake_abort * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in,out] operation The operation to abort. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation); #endif /* PSA_CRYPTO_PAKE_H */ webfakes/src/mbedtls/library/block_cipher.c0000644000176200001440000001474514740737024020541 0ustar liggesusers/** * \file block_cipher.c * * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks, * for use by the GCM and CCM modules. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) #include "psa/crypto.h" #include "psa_crypto_core.h" #include "psa_util_internal.h" #endif #include "block_cipher_internal.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) static psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id) { switch (cipher_id) { #if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) case MBEDTLS_BLOCK_CIPHER_ID_AES: return PSA_KEY_TYPE_AES; #endif #if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: return PSA_KEY_TYPE_ARIA; #endif #if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: return PSA_KEY_TYPE_CAMELLIA; #endif default: return PSA_KEY_TYPE_NONE; } } static int mbedtls_cipher_error_from_psa(psa_status_t status) { return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors, psa_generic_status_to_mbedtls); } #endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { psa_destroy_key(ctx->psa_key_id); return; } #endif switch (ctx->id) { #if defined(MBEDTLS_AES_C) case MBEDTLS_BLOCK_CIPHER_ID_AES: mbedtls_aes_free(&ctx->ctx.aes); break; #endif #if defined(MBEDTLS_ARIA_C) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: mbedtls_aria_free(&ctx->ctx.aria); break; #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: mbedtls_camellia_free(&ctx->ctx.camellia); break; #endif default: break; } ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; } int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx, mbedtls_cipher_id_t cipher_id) { ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES : (cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA : (cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA : MBEDTLS_BLOCK_CIPHER_ID_NONE; #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id); if (psa_key_type != PSA_KEY_TYPE_NONE && psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) { ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA; return 0; } ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY; #endif switch (ctx->id) { #if defined(MBEDTLS_AES_C) case MBEDTLS_BLOCK_CIPHER_ID_AES: mbedtls_aes_init(&ctx->ctx.aes); return 0; #endif #if defined(MBEDTLS_ARIA_C) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: mbedtls_aria_init(&ctx->ctx.aria); return 0; #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: mbedtls_camellia_init(&ctx->ctx.camellia); return 0; #endif default: ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } } int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx, const unsigned char *key, unsigned key_bitlen) { #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status; psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id)); psa_set_key_bits(&key_attr, key_bitlen); psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id); if (status != PSA_SUCCESS) { return mbedtls_cipher_error_from_psa(status); } psa_reset_key_attributes(&key_attr); return 0; } #endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ switch (ctx->id) { #if defined(MBEDTLS_AES_C) case MBEDTLS_BLOCK_CIPHER_ID_AES: return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen); #endif #if defined(MBEDTLS_ARIA_C) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen); #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen); #endif default: return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; } } int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx, const unsigned char input[16], unsigned char output[16]) { #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { psa_status_t status; size_t olen; status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING, input, 16, output, 16, &olen); if (status != PSA_SUCCESS) { return mbedtls_cipher_error_from_psa(status); } return 0; } #endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ switch (ctx->id) { #if defined(MBEDTLS_AES_C) case MBEDTLS_BLOCK_CIPHER_ID_AES: return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT, input, output); #endif #if defined(MBEDTLS_ARIA_C) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output); #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia, MBEDTLS_CAMELLIA_ENCRYPT, input, output); #endif default: return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; } } #endif /* MBEDTLS_BLOCK_CIPHER_C */ webfakes/src/mbedtls/library/psa_crypto_mac.h0000644000176200001440000002676514740737024021132 0ustar liggesusers/* * PSA MAC layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_MAC_H #define PSA_CRYPTO_MAC_H #include /** Calculate the MAC (message authentication code) of a message using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_compute * entry point. This function behaves as a mac_compute entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key to use for * computing the MAC. This buffer contains the key * in export representation as defined by * psa_export_key() (i.e. the raw key bytes). * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The MAC algorithm to use (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * \param[in] input Buffer containing the input message. * \param input_length Size of the \p input buffer in bytes. * \param[out] mac Buffer where the MAC value is to be written. * \param mac_size Size of the \p mac buffer in bytes. * \param[out] mac_length On success, the number of bytes * that make up the MAC value. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p mac_size is too small * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_compute( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length); /** Set up a multipart MAC calculation operation using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_sign_setup * entry point. This function behaves as a mac_sign_setup entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param[in,out] operation The operation object to set up. It must have * been initialized and not yet in use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key to use for * computing the MAC. This buffer contains the key * in export representation as defined by * psa_export_key() (i.e. the raw key bytes). * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The MAC algorithm to use (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive). */ psa_status_t mbedtls_psa_mac_sign_setup( mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Set up a multipart MAC verification operation using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_verify_setup * entry point. This function behaves as a mac_verify_setup entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param[in,out] operation The operation object to set up. It must have * been initialized and not yet in use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key to use for * computing the MAC. This buffer contains the key * in export representation as defined by * psa_export_key() (i.e. the raw key bytes). * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The MAC algorithm to use (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive). */ psa_status_t mbedtls_psa_mac_verify_setup( mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Add a message fragment to a multipart MAC operation using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_update * entry point. This function behaves as a mac_update entry point as * defined in the PSA driver interface specification for transparent * drivers. * * The PSA core calls mbedtls_psa_mac_sign_setup() or * mbedtls_psa_mac_verify_setup() before calling this function. * * If this function returns an error status, the PSA core aborts the * operation by calling mbedtls_psa_mac_abort(). * * \param[in,out] operation Active MAC operation. * \param[in] input Buffer containing the message fragment to add to * the MAC calculation. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_update( mbedtls_psa_mac_operation_t *operation, const uint8_t *input, size_t input_length); /** Finish the calculation of the MAC of a message using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_sign_finish * entry point. This function behaves as a mac_sign_finish entry point as * defined in the PSA driver interface specification for transparent * drivers. * * The PSA core calls mbedtls_psa_mac_sign_setup() before calling this function. * This function calculates the MAC of the message formed by concatenating * the inputs passed to preceding calls to mbedtls_psa_mac_update(). * * Whether this function returns successfully or not, the PSA core subsequently * aborts the operation by calling mbedtls_psa_mac_abort(). * * \param[in,out] operation Active MAC operation. * \param[out] mac Buffer where the MAC value is to be written. * \param mac_size Output size requested for the MAC algorithm. The PSA * core guarantees this is a valid MAC length for the * algorithm and key combination passed to * mbedtls_psa_mac_sign_setup(). It also guarantees the * \p mac buffer is large enough to contain the * requested output size. * \param[out] mac_length On success, the number of bytes output to buffer * \p mac, which will be equal to the requested length * \p mac_size. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active mac sign * operation). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p mac buffer is too small. A sufficient buffer size * can be determined by calling PSA_MAC_LENGTH(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_sign_finish( mbedtls_psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length); /** Finish the calculation of the MAC of a message and compare it with * an expected value using Mbed TLS. * * \note The signature of this function is that of a PSA driver * mac_verify_finish entry point. This function behaves as a * mac_verify_finish entry point as defined in the PSA driver interface * specification for transparent drivers. * * The PSA core calls mbedtls_psa_mac_verify_setup() before calling this * function. This function calculates the MAC of the message formed by * concatenating the inputs passed to preceding calls to * mbedtls_psa_mac_update(). It then compares the calculated MAC with the * expected MAC passed as a parameter to this function. * * Whether this function returns successfully or not, the PSA core subsequently * aborts the operation by calling mbedtls_psa_mac_abort(). * * \param[in,out] operation Active MAC operation. * \param[in] mac Buffer containing the expected MAC value. * \param mac_length Length in bytes of the expected MAC value. The PSA * core guarantees that this length is a valid MAC * length for the algorithm and key combination passed * to mbedtls_psa_mac_verify_setup(). * * \retval #PSA_SUCCESS * The expected MAC is identical to the actual MAC of the message. * \retval #PSA_ERROR_INVALID_SIGNATURE * The MAC of the message was calculated successfully, but it * differs from the expected MAC. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active mac verify * operation). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_verify_finish( mbedtls_psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length); /** Abort a MAC operation using Mbed TLS. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * mbedtls_psa_mac_sign_setup() or mbedtls_psa_mac_verify_setup() again. * * The PSA core may call this function any time after the operation object has * been initialized by one of the methods described in * #mbedtls_psa_mac_operation_t. * * In particular, calling mbedtls_psa_mac_abort() after the operation has been * terminated by a call to mbedtls_psa_mac_abort(), * mbedtls_psa_mac_sign_finish() or mbedtls_psa_mac_verify_finish() is safe and * has no effect. * * \param[in,out] operation Initialized MAC operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_abort( mbedtls_psa_mac_operation_t *operation); #endif /* PSA_CRYPTO_MAC_H */ webfakes/src/mbedtls/library/md_psa.h0000644000176200001440000000122114740737024017346 0ustar liggesusers/** * Translation between MD and PSA identifiers (algorithms, errors). * * Note: this internal module will go away when everything becomes based on * PSA Crypto; it is a helper for the transition period. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD_PSA_H #define MBEDTLS_MD_PSA_H #include "common.h" #include "mbedtls/md.h" #include "psa/crypto.h" /** Convert PSA status to MD error code. * * \param status PSA status. * * \return The corresponding MD error code, */ int mbedtls_md_error_from_psa(psa_status_t status); #endif /* MBEDTLS_MD_PSA_H */ webfakes/src/mbedtls/library/mps_common.h0000644000176200001440000001615114740737024020262 0ustar liggesusers/* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** * \file mps_common.h * * \brief Common functions and macros used by MPS */ #ifndef MBEDTLS_MPS_COMMON_H #define MBEDTLS_MPS_COMMON_H #include "mps_error.h" #include /** * \name SECTION: MPS Configuration * * \{ */ /*! This flag controls whether the MPS-internal components * (reader, writer, Layer 1-3) perform validation of the * expected abstract state at the entry of API calls. * * Context: All MPS API functions impose assumptions/preconditions on the * context on which they operate. For example, every structure has a notion of * state integrity which is established by `xxx_init()` and preserved by any * calls to the MPS API which satisfy their preconditions and either succeed, * or fail with an error code which is explicitly documented to not corrupt * structure integrity (such as WANT_READ and WANT_WRITE); * apart from `xxx_init()` any function assumes state integrity as a * precondition (but usually more). If any of the preconditions is violated, * the function's behavior is entirely undefined. * In addition to state integrity, all MPS structures have a more refined * notion of abstract state that the API operates on. For example, all layers * have a notion of 'abstract read state' which indicates if incoming data has * been passed to the user, e.g. through mps_l2_read_start() for Layer 2 * or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to * call these reading functions again until the incoming data has been * explicitly 'consumed', e.g. through mps_l2_read_consume() for Layer 2 or * mps_l3_read_consume() on Layer 3. However, even if it doesn't make sense, * it's a design choice whether the API should fail gracefully on such * non-sensical calls or not, and that's what this option is about: * * This option determines whether the expected abstract state * is part of the API preconditions or not: If the option is set, * then the abstract state is not part of the precondition and is * thus required to be validated by the implementation. If an unexpected * abstract state is encountered, the implementation must fail gracefully * with error #MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED. * Conversely, if this option is not set, then the expected abstract state * is included in the preconditions of the respective API calls, and * an implementation's behaviour is undefined if the abstract state is * not as expected. * * For example: Enabling this makes mps_l2_read_done() fail if * no incoming record is currently open; disabling this would * lead to undefined behavior in this case. * * Comment this to remove state validation. */ #define MBEDTLS_MPS_STATE_VALIDATION /*! This flag enables/disables assertions on the internal state of MPS. * * Assertions are sanity checks that should never trigger when MPS * is used within the bounds of its API and preconditions. * * Enabling this increases security by limiting the scope of * potential bugs, but comes at the cost of increased code size. * * Note: So far, there is no guiding principle as to what * expected conditions merit an assertion, and which don't. * * Comment this to disable assertions. */ #define MBEDTLS_MPS_ENABLE_ASSERTIONS /*! This flag controls whether tracing for MPS should be enabled. */ //#define MBEDTLS_MPS_ENABLE_TRACE #if defined(MBEDTLS_MPS_STATE_VALIDATION) #define MBEDTLS_MPS_STATE_VALIDATE_RAW(cond, string) \ do \ { \ if (!(cond)) \ { \ MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR, string); \ MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED); \ } \ } while (0) #else /* MBEDTLS_MPS_STATE_VALIDATION */ #define MBEDTLS_MPS_STATE_VALIDATE_RAW(cond, string) \ do \ { \ (cond); \ } while (0) #endif /* MBEDTLS_MPS_STATE_VALIDATION */ #if defined(MBEDTLS_MPS_ENABLE_ASSERTIONS) #define MBEDTLS_MPS_ASSERT_RAW(cond, string) \ do \ { \ if (!(cond)) \ { \ MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR, string); \ MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_INTERNAL_ERROR); \ } \ } while (0) #else /* MBEDTLS_MPS_ENABLE_ASSERTIONS */ #define MBEDTLS_MPS_ASSERT_RAW(cond, string) do {} while (0) #endif /* MBEDTLS_MPS_ENABLE_ASSERTIONS */ /* \} name SECTION: MPS Configuration */ /** * \name SECTION: Common types * * Various common types used throughout MPS. * \{ */ /** \brief The type of buffer sizes and offsets used in MPS structures. * * This is an unsigned integer type that should be large enough to * hold the length of any buffer or message processed by MPS. * * The reason to pick a value as small as possible here is * to reduce the size of MPS structures. * * \warning Care has to be taken when using a narrower type * than ::mbedtls_mps_size_t here because of * potential truncation during conversion. * * \warning Handshake messages in TLS may be up to 2^24 ~ 16Mb in size. * If mbedtls_mps_[opt_]stored_size_t is smaller than that, the * maximum handshake message is restricted accordingly. * * For now, we use the default type of size_t throughout, and the use of * smaller types or different types for ::mbedtls_mps_size_t and * ::mbedtls_mps_stored_size_t is not yet supported. * */ typedef size_t mbedtls_mps_stored_size_t; #define MBEDTLS_MPS_STORED_SIZE_MAX (SIZE_MAX) /** \brief The type of buffer sizes and offsets used in the MPS API * and implementation. * * This must be at least as wide as ::mbedtls_stored_size_t but * may be chosen to be strictly larger if more suitable for the * target architecture. * * For example, in a test build for ARM Thumb, using uint_fast16_t * instead of uint16_t reduced the code size from 1060 Byte to 962 Byte, * so almost 10%. */ typedef size_t mbedtls_mps_size_t; #define MBEDTLS_MPS_SIZE_MAX (SIZE_MAX) #if MBEDTLS_MPS_STORED_SIZE_MAX > MBEDTLS_MPS_SIZE_MAX #error "Misconfiguration of mbedtls_mps_size_t and mbedtls_mps_stored_size_t." #endif /* \} SECTION: Common types */ #endif /* MBEDTLS_MPS_COMMON_H */ webfakes/src/mbedtls/library/psa_crypto_se.h0000644000176200001440000001513314740737024020764 0ustar liggesusers/* * PSA crypto support for secure element drivers */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SE_H #define PSA_CRYPTO_SE_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" #include "psa/crypto.h" #include "psa/crypto_se_driver.h" /** The maximum location value that this implementation supports * for a secure element. * * This is not a characteristic that each PSA implementation has, but a * limitation of the current implementation due to the constraints imposed * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. * * The minimum location value for a secure element is 1, like on any * PSA implementation (0 means a transparent key). */ #define PSA_MAX_SE_LOCATION 255 /** The base of the range of ITS file identifiers for secure element * driver persistent data. * * We use a slice of the implementation reserved range 0xffff0000..0xffffffff, * specifically the range 0xfffffe00..0xfffffeff. The length of this range * drives the value of #PSA_MAX_SE_LOCATION. The identifier 0xfffffe00 is * actually not used since it corresponds to #PSA_KEY_LOCATION_LOCAL_STORAGE * which doesn't have a driver. */ #define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ((psa_key_id_t) 0xfffffe00) /** The maximum number of registered secure element driver locations. */ #define PSA_MAX_SE_DRIVERS 4 /** Unregister all secure element drivers. * * \warning Do not call this function while the library is in the initialized * state. This function is only intended to be called at the end * of mbedtls_psa_crypto_free(). */ void psa_unregister_all_se_drivers(void); /** Initialize all secure element drivers. * * Called from psa_crypto_init(). */ psa_status_t psa_init_all_se_drivers(void); /** A structure that describes a registered secure element driver. * * A secure element driver table entry contains a pointer to the * driver's method table as well as the driver context structure. */ typedef struct psa_se_drv_table_entry_s psa_se_drv_table_entry_t; /** Return the secure element driver information for a lifetime value. * * \param lifetime The lifetime value to query. * \param[out] p_methods On output, if there is a driver, * \c *methods points to its method table. * Otherwise \c *methods is \c NULL. * \param[out] p_drv_context On output, if there is a driver, * \c *drv_context points to its context * structure. * Otherwise \c *drv_context is \c NULL. * * \retval 1 * \p lifetime corresponds to a registered driver. * \retval 0 * \p lifetime does not correspond to a registered driver. */ int psa_get_se_driver(psa_key_lifetime_t lifetime, const psa_drv_se_t **p_methods, psa_drv_se_context_t **p_drv_context); /** Return the secure element driver table entry for a lifetime value. * * \param lifetime The lifetime value to query. * * \return The driver table entry for \p lifetime, or * \p NULL if \p lifetime does not correspond to a registered driver. */ psa_se_drv_table_entry_t *psa_get_se_driver_entry( psa_key_lifetime_t lifetime); /** Return the method table for a secure element driver. * * \param[in] driver The driver table entry to access, or \c NULL. * * \return The driver's method table. * \c NULL if \p driver is \c NULL. */ const psa_drv_se_t *psa_get_se_driver_methods( const psa_se_drv_table_entry_t *driver); /** Return the context of a secure element driver. * * \param[in] driver The driver table entry to access, or \c NULL. * * \return A pointer to the driver context. * \c NULL if \p driver is \c NULL. */ psa_drv_se_context_t *psa_get_se_driver_context( psa_se_drv_table_entry_t *driver); /** Find a free slot for a key that is to be created. * * This function calls the relevant method in the driver to find a suitable * slot for a key with the given attributes. * * \param[in] attributes Metadata about the key that is about to be created. * \param[in] driver The driver table entry to query. * \param[out] slot_number On success, a slot number that is free in this * secure element. */ psa_status_t psa_find_se_slot_for_key( const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_se_drv_table_entry_t *driver, psa_key_slot_number_t *slot_number); /** Destroy a key in a secure element. * * This function calls the relevant driver method to destroy a key * and updates the driver's persistent data. */ psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver, psa_key_slot_number_t slot_number); /** Load the persistent data of a secure element driver. * * \param driver The driver table entry containing the persistent * data to load from storage. * * \return #PSA_SUCCESS * \return #PSA_ERROR_NOT_SUPPORTED * \return #PSA_ERROR_DOES_NOT_EXIST * \return #PSA_ERROR_STORAGE_FAILURE * \return #PSA_ERROR_DATA_CORRUPT * \return #PSA_ERROR_INVALID_ARGUMENT */ psa_status_t psa_load_se_persistent_data( const psa_se_drv_table_entry_t *driver); /** Save the persistent data of a secure element driver. * * \param[in] driver The driver table entry containing the persistent * data to save to storage. * * \return #PSA_SUCCESS * \return #PSA_ERROR_NOT_SUPPORTED * \return #PSA_ERROR_NOT_PERMITTED * \return #PSA_ERROR_NOT_SUPPORTED * \return #PSA_ERROR_INSUFFICIENT_STORAGE * \return #PSA_ERROR_STORAGE_FAILURE * \return #PSA_ERROR_INVALID_ARGUMENT */ psa_status_t psa_save_se_persistent_data( const psa_se_drv_table_entry_t *driver); /** Destroy the persistent data of a secure element driver. * * This is currently only used for testing. * * \param[in] location The location identifier for the driver whose * persistent data is to be erased. */ psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location); /** The storage representation of a key whose data is in a secure element. */ typedef struct { uint8_t slot_number[sizeof(psa_key_slot_number_t)]; } psa_se_key_data_storage_t; #endif /* PSA_CRYPTO_SE_H */ webfakes/src/mbedtls/library/aesce.c0000644000176200001440000004765214740737024017200 0ustar liggesusers/* * Armv8-A Cryptographic Extension support functions for Aarch64 * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #if defined(__clang__) && (__clang_major__ >= 4) /* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if, * but that is defined by build_info.h, and we need this block to happen first. */ #if defined(__ARM_ARCH) #if __ARM_ARCH >= 8 #define MBEDTLS_AESCE_ARCH_IS_ARMV8_A #endif #endif #if defined(MBEDTLS_AESCE_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO) /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. * * The intrinsic declaration are guarded by predefined ACLE macros in clang: * these are normally only enabled by the -march option on the command line. * By defining the macros ourselves we gain access to those declarations without * requiring -march on the command line. * * `arm_neon.h` is included by common.h, so we put these defines * at the top of this file, before any includes. */ #define __ARM_FEATURE_CRYPTO 1 /* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions * * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it * for older compilers. */ #define __ARM_FEATURE_AES 1 #define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG #endif #endif /* defined(__clang__) && (__clang_major__ >= 4) */ #include #include "common.h" #if defined(MBEDTLS_AESCE_C) #include "aesce.h" #if defined(MBEDTLS_AESCE_HAVE_CODE) /* Compiler version checks. */ #if defined(__clang__) # if defined(MBEDTLS_ARCH_IS_ARM32) && (__clang_major__ < 11) # error "Minimum version of Clang for MBEDTLS_AESCE_C on 32-bit Arm or Thumb is 11.0." # elif defined(MBEDTLS_ARCH_IS_ARM64) && (__clang_major__ < 4) # error "Minimum version of Clang for MBEDTLS_AESCE_C on aarch64 is 4.0." # endif #elif defined(__GNUC__) # if __GNUC__ < 6 # error "Minimum version of GCC for MBEDTLS_AESCE_C is 6.0." # endif #elif defined(_MSC_VER) /* TODO: We haven't verified MSVC from 1920 to 1928. If someone verified that, * please update this and document of `MBEDTLS_AESCE_C` in * `mbedtls_config.h`. */ # if _MSC_VER < 1929 # error "Minimum version of MSVC for MBEDTLS_AESCE_C is 2019 version 16.11.2." # endif #elif defined(__ARMCC_VERSION) # if defined(MBEDTLS_ARCH_IS_ARM32) && (__ARMCC_VERSION < 6200002) /* TODO: We haven't verified armclang for 32-bit Arm/Thumb prior to 6.20. * If someone verified that, please update this and document of * `MBEDTLS_AESCE_C` in `mbedtls_config.h`. */ # error "Minimum version of armclang for MBEDTLS_AESCE_C on 32-bit Arm is 6.20." # elif defined(MBEDTLS_ARCH_IS_ARM64) && (__ARMCC_VERSION < 6060000) # error "Minimum version of armclang for MBEDTLS_AESCE_C on aarch64 is 6.6." # endif #endif #if !(defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_AES)) || \ defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) # if defined(__ARMCOMPILER_VERSION) # if __ARMCOMPILER_VERSION <= 6090000 # error "Must use minimum -march=armv8-a+crypto for MBEDTLS_AESCE_C" # else # pragma clang attribute push (__attribute__((target("aes"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # endif # elif defined(__clang__) # pragma clang attribute push (__attribute__((target("aes"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # elif defined(__GNUC__) # pragma GCC push_options # pragma GCC target ("+crypto") # define MBEDTLS_POP_TARGET_PRAGMA # elif defined(_MSC_VER) # error "Required feature(__ARM_FEATURE_AES) is not enabled." # endif #endif /* !(__ARM_FEATURE_CRYPTO || __ARM_FEATURE_AES) || MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */ #if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) #include #if !defined(HWCAP_NEON) #define HWCAP_NEON (1 << 12) #endif #if !defined(HWCAP2_AES) #define HWCAP2_AES (1 << 0) #endif #if !defined(HWCAP_AES) #define HWCAP_AES (1 << 3) #endif #if !defined(HWCAP_ASIMD) #define HWCAP_ASIMD (1 << 1) #endif signed char mbedtls_aesce_has_support_result = -1; #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) /* * AES instruction support detection routine */ int mbedtls_aesce_has_support_impl(void) { /* To avoid many calls to getauxval, cache the result. This is * thread-safe, because we store the result in a char so cannot * be vulnerable to non-atomic updates. * It is possible that we could end up setting result more than * once, but that is harmless. */ if (mbedtls_aesce_has_support_result == -1) { #if defined(MBEDTLS_ARCH_IS_ARM32) unsigned long auxval = getauxval(AT_HWCAP); unsigned long auxval2 = getauxval(AT_HWCAP2); if (((auxval & HWCAP_NEON) == HWCAP_NEON) && ((auxval2 & HWCAP2_AES) == HWCAP2_AES)) { mbedtls_aesce_has_support_result = 1; } else { mbedtls_aesce_has_support_result = 0; } #else unsigned long auxval = getauxval(AT_HWCAP); if ((auxval & (HWCAP_ASIMD | HWCAP_AES)) == (HWCAP_ASIMD | HWCAP_AES)) { mbedtls_aesce_has_support_result = 1; } else { mbedtls_aesce_has_support_result = 0; } #endif } return mbedtls_aesce_has_support_result; } #endif #endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */ /* Single round of AESCE encryption */ #define AESCE_ENCRYPT_ROUND \ block = vaeseq_u8(block, vld1q_u8(keys)); \ block = vaesmcq_u8(block); \ keys += 16 /* Two rounds of AESCE encryption */ #define AESCE_ENCRYPT_ROUND_X2 AESCE_ENCRYPT_ROUND; AESCE_ENCRYPT_ROUND MBEDTLS_OPTIMIZE_FOR_PERFORMANCE static uint8x16_t aesce_encrypt_block(uint8x16_t block, unsigned char *keys, int rounds) { /* 10, 12 or 14 rounds. Unroll loop. */ if (rounds == 10) { goto rounds_10; } if (rounds == 12) { goto rounds_12; } AESCE_ENCRYPT_ROUND_X2; rounds_12: AESCE_ENCRYPT_ROUND_X2; rounds_10: AESCE_ENCRYPT_ROUND_X2; AESCE_ENCRYPT_ROUND_X2; AESCE_ENCRYPT_ROUND_X2; AESCE_ENCRYPT_ROUND_X2; AESCE_ENCRYPT_ROUND; /* AES AddRoundKey for the previous round. * SubBytes, ShiftRows for the final round. */ block = vaeseq_u8(block, vld1q_u8(keys)); keys += 16; /* Final round: no MixColumns */ /* Final AddRoundKey */ block = veorq_u8(block, vld1q_u8(keys)); return block; } /* Single round of AESCE decryption * * AES AddRoundKey, SubBytes, ShiftRows * * block = vaesdq_u8(block, vld1q_u8(keys)); * * AES inverse MixColumns for the next round. * * This means that we switch the order of the inverse AddRoundKey and * inverse MixColumns operations. We have to do this as AddRoundKey is * done in an atomic instruction together with the inverses of SubBytes * and ShiftRows. * * It works because MixColumns is a linear operation over GF(2^8) and * AddRoundKey is an exclusive or, which is equivalent to addition over * GF(2^8). (The inverse of MixColumns needs to be applied to the * affected round keys separately which has been done when the * decryption round keys were calculated.) * * block = vaesimcq_u8(block); */ #define AESCE_DECRYPT_ROUND \ block = vaesdq_u8(block, vld1q_u8(keys)); \ block = vaesimcq_u8(block); \ keys += 16 /* Two rounds of AESCE decryption */ #define AESCE_DECRYPT_ROUND_X2 AESCE_DECRYPT_ROUND; AESCE_DECRYPT_ROUND #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static uint8x16_t aesce_decrypt_block(uint8x16_t block, unsigned char *keys, int rounds) { /* 10, 12 or 14 rounds. Unroll loop. */ if (rounds == 10) { goto rounds_10; } if (rounds == 12) { goto rounds_12; } AESCE_DECRYPT_ROUND_X2; rounds_12: AESCE_DECRYPT_ROUND_X2; rounds_10: AESCE_DECRYPT_ROUND_X2; AESCE_DECRYPT_ROUND_X2; AESCE_DECRYPT_ROUND_X2; AESCE_DECRYPT_ROUND_X2; AESCE_DECRYPT_ROUND; /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the * last full round. */ block = vaesdq_u8(block, vld1q_u8(keys)); keys += 16; /* Inverse AddRoundKey for inverting the initial round key addition. */ block = veorq_u8(block, vld1q_u8(keys)); return block; } #endif /* * AES-ECB block en(de)cryption */ int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { uint8x16_t block = vld1q_u8(&input[0]); unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { block = aesce_decrypt_block(block, keys, ctx->nr); } else #else (void) mode; #endif { block = aesce_encrypt_block(block, keys, ctx->nr); } vst1q_u8(&output[0], block); return 0; } /* * Compute decryption round keys from encryption round keys */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) void mbedtls_aesce_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr) { int i, j; j = nr; vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16)); for (i = 1, j--; j > 0; i++, j--) { vst1q_u8(invkey + i * 16, vaesimcq_u8(vld1q_u8(fwdkey + j * 16))); } vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16)); } #endif static inline uint32_t aes_rot_word(uint32_t word) { return (word << (32 - 8)) | (word >> 8); } static inline uint32_t aes_sub_word(uint32_t in) { uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in)); uint8x16_t zero = vdupq_n_u8(0); /* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields * the correct result as ShiftRows doesn't change the first row. */ v = vaeseq_u8(zero, v); return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0); } /* * Key expansion function */ static void aesce_setkey_enc(unsigned char *rk, const unsigned char *key, const size_t key_bit_length) { static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; /* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf * - Section 5, Nr = Nk + 6 * - Section 5.2, the length of round keys is Nb*(Nr+1) */ const size_t key_len_in_words = key_bit_length / 32; /* Nk */ const size_t round_key_len_in_words = 4; /* Nb */ const size_t rounds_needed = key_len_in_words + 6; /* Nr */ const size_t round_keys_len_in_words = round_key_len_in_words * (rounds_needed + 1); /* Nb*(Nr+1) */ const uint32_t *rko_end = (uint32_t *) rk + round_keys_len_in_words; memcpy(rk, key, key_len_in_words * 4); for (uint32_t *rki = (uint32_t *) rk; rki + key_len_in_words < rko_end; rki += key_len_in_words) { size_t iteration = (size_t) (rki - (uint32_t *) rk) / key_len_in_words; uint32_t *rko; rko = rki + key_len_in_words; rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1])); rko[0] ^= rcon[iteration] ^ rki[0]; rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; if (rko + key_len_in_words > rko_end) { /* Do not write overflow words.*/ continue; } #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) switch (key_bit_length) { case 128: break; case 192: rko[4] = rko[3] ^ rki[4]; rko[5] = rko[4] ^ rki[5]; break; case 256: rko[4] = aes_sub_word(rko[3]) ^ rki[4]; rko[5] = rko[4] ^ rki[5]; rko[6] = rko[5] ^ rki[6]; rko[7] = rko[6] ^ rki[7]; break; } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ } } /* * Key expansion, wrapper */ int mbedtls_aesce_setkey_enc(unsigned char *rk, const unsigned char *key, size_t bits) { switch (bits) { case 128: case 192: case 256: aesce_setkey_enc(rk, key, bits); break; default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } return 0; } #if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_ARCH_IS_ARM32) #if defined(__clang__) /* On clang for A32/T32, work around some missing intrinsics and types which are listed in * [ACLE](https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#polynomial-1) * These are only required for GCM. */ #define vreinterpretq_u64_p64(a) ((uint64x2_t) a) typedef uint8x16_t poly128_t; static inline poly128_t vmull_p64(poly64_t a, poly64_t b) { poly128_t r; asm ("vmull.p64 %[r], %[a], %[b]" : [r] "=w" (r) : [a] "w" (a), [b] "w" (b) :); return r; } /* This is set to cause some more missing intrinsics to be defined below */ #define COMMON_MISSING_INTRINSICS static inline poly128_t vmull_high_p64(poly64x2_t a, poly64x2_t b) { return vmull_p64((poly64_t) (vget_high_u64((uint64x2_t) a)), (poly64_t) (vget_high_u64((uint64x2_t) b))); } #endif /* defined(__clang__) */ static inline uint8x16_t vrbitq_u8(uint8x16_t x) { /* There is no vrbitq_u8 instruction in A32/T32, so provide * an equivalent non-Neon implementation. Reverse bit order in each * byte with 4x rbit, rev. */ asm ("ldm %[p], { r2-r5 } \n\t" "rbit r2, r2 \n\t" "rev r2, r2 \n\t" "rbit r3, r3 \n\t" "rev r3, r3 \n\t" "rbit r4, r4 \n\t" "rev r4, r4 \n\t" "rbit r5, r5 \n\t" "rev r5, r5 \n\t" "stm %[p], { r2-r5 } \n\t" : /* Output: 16 bytes of memory pointed to by &x */ "+m" (*(uint8_t(*)[16]) &x) : [p] "r" (&x) : "r2", "r3", "r4", "r5" ); return x; } #endif /* defined(MBEDTLS_ARCH_IS_ARM32) */ #if defined(MBEDTLS_COMPILER_IS_GCC) && __GNUC__ == 5 /* Some intrinsics are not available for GCC 5.X. */ #define COMMON_MISSING_INTRINSICS #endif /* MBEDTLS_COMPILER_IS_GCC && __GNUC__ == 5 */ #if defined(COMMON_MISSING_INTRINSICS) /* Missing intrinsics common to both GCC 5, and Clang on 32-bit */ #define vreinterpretq_p64_u8(a) ((poly64x2_t) a) #define vreinterpretq_u8_p128(a) ((uint8x16_t) a) static inline poly64x1_t vget_low_p64(poly64x2_t a) { uint64x1_t r = vget_low_u64(vreinterpretq_u64_p64(a)); return (poly64x1_t) r; } #endif /* COMMON_MISSING_INTRINSICS */ /* vmull_p64/vmull_high_p64 wrappers. * * Older compilers miss some intrinsic functions for `poly*_t`. We use * uint8x16_t and uint8x16x3_t as input/output parameters. */ #if defined(MBEDTLS_COMPILER_IS_GCC) /* GCC reports incompatible type error without cast. GCC think poly64_t and * poly64x1_t are different, that is different with MSVC and Clang. */ #define MBEDTLS_VMULL_P64(a, b) vmull_p64((poly64_t) a, (poly64_t) b) #else /* MSVC reports `error C2440: 'type cast'` with cast. Clang does not report * error with/without cast. And I think poly64_t and poly64x1_t are same, no * cast for clang also. */ #define MBEDTLS_VMULL_P64(a, b) vmull_p64(a, b) #endif /* MBEDTLS_COMPILER_IS_GCC */ static inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b) { return vreinterpretq_u8_p128( MBEDTLS_VMULL_P64( (poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)), (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b)) )); } static inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b) { return vreinterpretq_u8_p128( vmull_high_p64(vreinterpretq_p64_u8(a), vreinterpretq_p64_u8(b))); } /* GHASH does 128b polynomial multiplication on block in GF(2^128) defined by * `x^128 + x^7 + x^2 + x + 1`. * * Arm64 only has 64b->128b polynomial multipliers, we need to do 4 64b * multiplies to generate a 128b. * * `poly_mult_128` executes polynomial multiplication and outputs 256b that * represented by 3 128b due to code size optimization. * * Output layout: * | | | | * |------------|-------------|-------------| * | ret.val[0] | h3:h2:00:00 | high 128b | * | ret.val[1] | :m2:m1:00 | middle 128b | * | ret.val[2] | : :l1:l0 | low 128b | */ static inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b) { uint8x16x3_t ret; uint8x16_t h, m, l; /* retval high/middle/low */ uint8x16_t c, d, e; h = pmull_high(a, b); /* h3:h2:00:00 = a1*b1 */ l = pmull_low(a, b); /* : :l1:l0 = a0*b0 */ c = vextq_u8(b, b, 8); /* :c1:c0 = b0:b1 */ d = pmull_high(a, c); /* :d2:d1:00 = a1*b0 */ e = pmull_low(a, c); /* :e2:e1:00 = a0*b1 */ m = veorq_u8(d, e); /* :m2:m1:00 = d + e */ ret.val[0] = h; ret.val[1] = m; ret.val[2] = l; return ret; } /* * Modulo reduction. * * See: https://www.researchgate.net/publication/285612706_Implementing_GCM_on_ARMv8 * * Section 4.3 * * Modular reduction is slightly more complex. Write the GCM modulus as f(z) = * z^128 +r(z), where r(z) = z^7+z^2+z+ 1. The well known approach is to * consider that z^128 ≡r(z) (mod z^128 +r(z)), allowing us to write the 256-bit * operand to be reduced as a(z) = h(z)z^128 +l(z)≡h(z)r(z) + l(z). That is, we * simply multiply the higher part of the operand by r(z) and add it to l(z). If * the result is still larger than 128 bits, we reduce again. */ static inline uint8x16_t poly_mult_reduce(uint8x16x3_t input) { uint8x16_t const ZERO = vdupq_n_u8(0); uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87)); #if defined(__GNUC__) /* use 'asm' as an optimisation barrier to prevent loading MODULO from * memory. It is for GNUC compatible compilers. */ asm volatile ("" : "+w" (r)); #endif uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8)); uint8x16_t h, m, l; /* input high/middle/low 128b */ uint8x16_t c, d, e, f, g, n, o; h = input.val[0]; /* h3:h2:00:00 */ m = input.val[1]; /* :m2:m1:00 */ l = input.val[2]; /* : :l1:l0 */ c = pmull_high(h, MODULO); /* :c2:c1:00 = reduction of h3 */ d = pmull_low(h, MODULO); /* : :d1:d0 = reduction of h2 */ e = veorq_u8(c, m); /* :e2:e1:00 = m2:m1:00 + c2:c1:00 */ f = pmull_high(e, MODULO); /* : :f1:f0 = reduction of e2 */ g = vextq_u8(ZERO, e, 8); /* : :g1:00 = e1:00 */ n = veorq_u8(d, l); /* : :n1:n0 = d1:d0 + l1:l0 */ o = veorq_u8(n, f); /* o1:o0 = f1:f0 + n1:n0 */ return veorq_u8(o, g); /* = o1:o0 + g1:00 */ } /* * GCM multiplication: c = a times b in GF(2^128) */ void mbedtls_aesce_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]) { uint8x16_t va, vb, vc; va = vrbitq_u8(vld1q_u8(&a[0])); vb = vrbitq_u8(vld1q_u8(&b[0])); vc = vrbitq_u8(poly_mult_reduce(poly_mult_128(va, vb))); vst1q_u8(&c[0], vc); } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_POP_TARGET_PRAGMA) #if defined(__clang__) #pragma clang attribute pop #elif defined(__GNUC__) #pragma GCC pop_options #endif #undef MBEDTLS_POP_TARGET_PRAGMA #endif #endif /* MBEDTLS_AESCE_HAVE_CODE */ #endif /* MBEDTLS_AESCE_C */ webfakes/src/mbedtls/library/md.c0000644000176200001440000007266014740737024016515 0ustar liggesusers/** * \file md.c * * \brief Generic message digest wrapper for Mbed TLS * * \author Adriaan de Jong * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" /* * Availability of functions in this module is controlled by two * feature macros: * - MBEDTLS_MD_C enables the whole module; * - MBEDTLS_MD_LIGHT enables only functions for hashing and accessing * most hash metadata (everything except string names); is it * automatically set whenever MBEDTLS_MD_C is defined. * * In this file, functions from MD_LIGHT are at the top, MD_C at the end. * * In the future we may want to change the contract of some functions * (behaviour with NULL arguments) depending on whether MD_C is defined or * only MD_LIGHT. Also, the exact scope of MD_LIGHT might vary. * * For these reasons, we're keeping MD_LIGHT internal for now. */ #if defined(MBEDTLS_MD_LIGHT) #include "mbedtls/md.h" #include "md_wrap.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/md5.h" #include "mbedtls/ripemd160.h" #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" #include "mbedtls/sha3.h" #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include #include "md_psa.h" #include "psa_util_internal.h" #endif #if defined(MBEDTLS_MD_SOME_PSA) #include "psa_crypto_core.h" #endif #include "mbedtls/platform.h" #include #if defined(MBEDTLS_FS_IO) #include #endif /* See comment above MBEDTLS_MD_MAX_SIZE in md.h */ #if defined(MBEDTLS_PSA_CRYPTO_C) && MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE #error "Internal error: MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE" #endif #if defined(MBEDTLS_MD_C) #define MD_INFO(type, out_size, block_size) type, out_size, block_size, #else #define MD_INFO(type, out_size, block_size) type, out_size, #endif #if defined(MBEDTLS_MD_CAN_MD5) static const mbedtls_md_info_t mbedtls_md5_info = { MD_INFO(MBEDTLS_MD_MD5, 16, 64) }; #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) static const mbedtls_md_info_t mbedtls_ripemd160_info = { MD_INFO(MBEDTLS_MD_RIPEMD160, 20, 64) }; #endif #if defined(MBEDTLS_MD_CAN_SHA1) static const mbedtls_md_info_t mbedtls_sha1_info = { MD_INFO(MBEDTLS_MD_SHA1, 20, 64) }; #endif #if defined(MBEDTLS_MD_CAN_SHA224) static const mbedtls_md_info_t mbedtls_sha224_info = { MD_INFO(MBEDTLS_MD_SHA224, 28, 64) }; #endif #if defined(MBEDTLS_MD_CAN_SHA256) static const mbedtls_md_info_t mbedtls_sha256_info = { MD_INFO(MBEDTLS_MD_SHA256, 32, 64) }; #endif #if defined(MBEDTLS_MD_CAN_SHA384) static const mbedtls_md_info_t mbedtls_sha384_info = { MD_INFO(MBEDTLS_MD_SHA384, 48, 128) }; #endif #if defined(MBEDTLS_MD_CAN_SHA512) static const mbedtls_md_info_t mbedtls_sha512_info = { MD_INFO(MBEDTLS_MD_SHA512, 64, 128) }; #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) static const mbedtls_md_info_t mbedtls_sha3_224_info = { MD_INFO(MBEDTLS_MD_SHA3_224, 28, 144) }; #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) static const mbedtls_md_info_t mbedtls_sha3_256_info = { MD_INFO(MBEDTLS_MD_SHA3_256, 32, 136) }; #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) static const mbedtls_md_info_t mbedtls_sha3_384_info = { MD_INFO(MBEDTLS_MD_SHA3_384, 48, 104) }; #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) static const mbedtls_md_info_t mbedtls_sha3_512_info = { MD_INFO(MBEDTLS_MD_SHA3_512, 64, 72) }; #endif const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type) { switch (md_type) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_MD_MD5: return &mbedtls_md5_info; #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) case MBEDTLS_MD_RIPEMD160: return &mbedtls_ripemd160_info; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_MD_SHA1: return &mbedtls_sha1_info; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_MD_SHA224: return &mbedtls_sha224_info; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: return &mbedtls_sha256_info; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: return &mbedtls_sha384_info; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_MD_SHA512: return &mbedtls_sha512_info; #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) case MBEDTLS_MD_SHA3_224: return &mbedtls_sha3_224_info; #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) case MBEDTLS_MD_SHA3_256: return &mbedtls_sha3_256_info; #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) case MBEDTLS_MD_SHA3_384: return &mbedtls_sha3_384_info; #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) case MBEDTLS_MD_SHA3_512: return &mbedtls_sha3_512_info; #endif default: return NULL; } } #if defined(MBEDTLS_MD_SOME_PSA) static psa_algorithm_t psa_alg_of_md(const mbedtls_md_info_t *info) { switch (info->type) { #if defined(MBEDTLS_MD_MD5_VIA_PSA) case MBEDTLS_MD_MD5: return PSA_ALG_MD5; #endif #if defined(MBEDTLS_MD_RIPEMD160_VIA_PSA) case MBEDTLS_MD_RIPEMD160: return PSA_ALG_RIPEMD160; #endif #if defined(MBEDTLS_MD_SHA1_VIA_PSA) case MBEDTLS_MD_SHA1: return PSA_ALG_SHA_1; #endif #if defined(MBEDTLS_MD_SHA224_VIA_PSA) case MBEDTLS_MD_SHA224: return PSA_ALG_SHA_224; #endif #if defined(MBEDTLS_MD_SHA256_VIA_PSA) case MBEDTLS_MD_SHA256: return PSA_ALG_SHA_256; #endif #if defined(MBEDTLS_MD_SHA384_VIA_PSA) case MBEDTLS_MD_SHA384: return PSA_ALG_SHA_384; #endif #if defined(MBEDTLS_MD_SHA512_VIA_PSA) case MBEDTLS_MD_SHA512: return PSA_ALG_SHA_512; #endif #if defined(MBEDTLS_MD_SHA3_224_VIA_PSA) case MBEDTLS_MD_SHA3_224: return PSA_ALG_SHA3_224; #endif #if defined(MBEDTLS_MD_SHA3_256_VIA_PSA) case MBEDTLS_MD_SHA3_256: return PSA_ALG_SHA3_256; #endif #if defined(MBEDTLS_MD_SHA3_384_VIA_PSA) case MBEDTLS_MD_SHA3_384: return PSA_ALG_SHA3_384; #endif #if defined(MBEDTLS_MD_SHA3_512_VIA_PSA) case MBEDTLS_MD_SHA3_512: return PSA_ALG_SHA3_512; #endif default: return PSA_ALG_NONE; } } static int md_can_use_psa(const mbedtls_md_info_t *info) { psa_algorithm_t alg = psa_alg_of_md(info); if (alg == PSA_ALG_NONE) { return 0; } return psa_can_do_hash(alg); } #endif /* MBEDTLS_MD_SOME_PSA */ void mbedtls_md_init(mbedtls_md_context_t *ctx) { /* Note: this sets engine (if present) to MBEDTLS_MD_ENGINE_LEGACY */ memset(ctx, 0, sizeof(mbedtls_md_context_t)); } void mbedtls_md_free(mbedtls_md_context_t *ctx) { if (ctx == NULL || ctx->md_info == NULL) { return; } if (ctx->md_ctx != NULL) { #if defined(MBEDTLS_MD_SOME_PSA) if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { psa_hash_abort(ctx->md_ctx); } else #endif switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: mbedtls_md5_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: mbedtls_ripemd160_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: mbedtls_sha1_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: mbedtls_sha256_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: mbedtls_sha256_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: mbedtls_sha512_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: mbedtls_sha512_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: mbedtls_sha3_free(ctx->md_ctx); break; #endif default: /* Shouldn't happen */ break; } mbedtls_free(ctx->md_ctx); } #if defined(MBEDTLS_MD_C) if (ctx->hmac_ctx != NULL) { mbedtls_zeroize_and_free(ctx->hmac_ctx, 2 * ctx->md_info->block_size); } #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md_context_t)); } int mbedtls_md_clone(mbedtls_md_context_t *dst, const mbedtls_md_context_t *src) { if (dst == NULL || dst->md_info == NULL || src == NULL || src->md_info == NULL || dst->md_info != src->md_info) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #if defined(MBEDTLS_MD_SOME_PSA) if (src->engine != dst->engine) { /* This can happen with src set to legacy because PSA wasn't ready * yet, and dst to PSA because it became ready in the meantime. * We currently don't support that case (we'd need to re-allocate * md_ctx to the size of the appropriate MD context). */ return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; } if (src->engine == MBEDTLS_MD_ENGINE_PSA) { psa_status_t status = psa_hash_clone(src->md_ctx, dst->md_ctx); return mbedtls_md_error_from_psa(status); } #endif switch (src->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: mbedtls_md5_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: mbedtls_ripemd160_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: mbedtls_sha1_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: mbedtls_sha256_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: mbedtls_sha256_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: mbedtls_sha512_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: mbedtls_sha512_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: mbedtls_sha3_clone(dst->md_ctx, src->md_ctx); break; #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } return 0; } #define ALLOC(type) \ do { \ ctx->md_ctx = mbedtls_calloc(1, sizeof(mbedtls_##type##_context)); \ if (ctx->md_ctx == NULL) \ return MBEDTLS_ERR_MD_ALLOC_FAILED; \ mbedtls_##type##_init(ctx->md_ctx); \ } \ while (0) int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac) { #if defined(MBEDTLS_MD_C) if (ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif if (md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } ctx->md_info = md_info; ctx->md_ctx = NULL; #if defined(MBEDTLS_MD_C) ctx->hmac_ctx = NULL; #else if (hmac != 0) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif #if defined(MBEDTLS_MD_SOME_PSA) if (md_can_use_psa(ctx->md_info)) { ctx->md_ctx = mbedtls_calloc(1, sizeof(psa_hash_operation_t)); if (ctx->md_ctx == NULL) { return MBEDTLS_ERR_MD_ALLOC_FAILED; } ctx->engine = MBEDTLS_MD_ENGINE_PSA; } else #endif switch (md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: ALLOC(md5); break; #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: ALLOC(ripemd160); break; #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: ALLOC(sha1); break; #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: ALLOC(sha256); break; #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: ALLOC(sha256); break; #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: ALLOC(sha512); break; #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: ALLOC(sha512); break; #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: ALLOC(sha3); break; #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #if defined(MBEDTLS_MD_C) if (hmac != 0) { ctx->hmac_ctx = mbedtls_calloc(2, md_info->block_size); if (ctx->hmac_ctx == NULL) { mbedtls_md_free(ctx); return MBEDTLS_ERR_MD_ALLOC_FAILED; } } #endif return 0; } #undef ALLOC int mbedtls_md_starts(mbedtls_md_context_t *ctx) { #if defined(MBEDTLS_MD_C) if (ctx == NULL || ctx->md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif #if defined(MBEDTLS_MD_SOME_PSA) if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { psa_algorithm_t alg = psa_alg_of_md(ctx->md_info); psa_hash_abort(ctx->md_ctx); psa_status_t status = psa_hash_setup(ctx->md_ctx, alg); return mbedtls_md_error_from_psa(status); } #endif switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: return mbedtls_md5_starts(ctx->md_ctx); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: return mbedtls_ripemd160_starts(ctx->md_ctx); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: return mbedtls_sha1_starts(ctx->md_ctx); #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: return mbedtls_sha256_starts(ctx->md_ctx, 1); #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: return mbedtls_sha256_starts(ctx->md_ctx, 0); #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: return mbedtls_sha512_starts(ctx->md_ctx, 1); #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: return mbedtls_sha512_starts(ctx->md_ctx, 0); #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_224); case MBEDTLS_MD_SHA3_256: return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_256); case MBEDTLS_MD_SHA3_384: return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_384); case MBEDTLS_MD_SHA3_512: return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_512); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } } int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen) { #if defined(MBEDTLS_MD_C) if (ctx == NULL || ctx->md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif #if defined(MBEDTLS_MD_SOME_PSA) if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { psa_status_t status = psa_hash_update(ctx->md_ctx, input, ilen); return mbedtls_md_error_from_psa(status); } #endif switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: return mbedtls_md5_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: return mbedtls_ripemd160_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: return mbedtls_sha1_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: return mbedtls_sha256_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: return mbedtls_sha256_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: return mbedtls_sha512_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: return mbedtls_sha512_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: return mbedtls_sha3_update(ctx->md_ctx, input, ilen); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } } int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output) { #if defined(MBEDTLS_MD_C) if (ctx == NULL || ctx->md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif #if defined(MBEDTLS_MD_SOME_PSA) if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { size_t size = ctx->md_info->size; psa_status_t status = psa_hash_finish(ctx->md_ctx, output, size, &size); return mbedtls_md_error_from_psa(status); } #endif switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: return mbedtls_md5_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: return mbedtls_ripemd160_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: return mbedtls_sha1_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: return mbedtls_sha256_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: return mbedtls_sha256_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: return mbedtls_sha512_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: return mbedtls_sha512_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: return mbedtls_sha3_finish(ctx->md_ctx, output, ctx->md_info->size); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } } int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output) { if (md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #if defined(MBEDTLS_MD_SOME_PSA) if (md_can_use_psa(md_info)) { size_t size = md_info->size; psa_status_t status = psa_hash_compute(psa_alg_of_md(md_info), input, ilen, output, size, &size); return mbedtls_md_error_from_psa(status); } #endif switch (md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: return mbedtls_md5(input, ilen, output); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: return mbedtls_ripemd160(input, ilen, output); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: return mbedtls_sha1(input, ilen, output); #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: return mbedtls_sha256(input, ilen, output, 1); #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: return mbedtls_sha256(input, ilen, output, 0); #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: return mbedtls_sha512(input, ilen, output, 1); #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: return mbedtls_sha512(input, ilen, output, 0); #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: return mbedtls_sha3(MBEDTLS_SHA3_224, input, ilen, output, md_info->size); case MBEDTLS_MD_SHA3_256: return mbedtls_sha3(MBEDTLS_SHA3_256, input, ilen, output, md_info->size); case MBEDTLS_MD_SHA3_384: return mbedtls_sha3(MBEDTLS_SHA3_384, input, ilen, output, md_info->size); case MBEDTLS_MD_SHA3_512: return mbedtls_sha3(MBEDTLS_SHA3_512, input, ilen, output, md_info->size); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } } unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info) { if (md_info == NULL) { return 0; } return md_info->size; } mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info) { if (md_info == NULL) { return MBEDTLS_MD_NONE; } return md_info->type; } #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) int mbedtls_md_error_from_psa(psa_status_t status) { return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_md_errors, psa_generic_status_to_mbedtls); } #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ /************************************************************************ * Functions above this separator are part of MBEDTLS_MD_LIGHT, * * functions below are only available when MBEDTLS_MD_C is set. * ************************************************************************/ #if defined(MBEDTLS_MD_C) /* * Reminder: update profiles in x509_crt.c when adding a new hash! */ static const int supported_digests[] = { #if defined(MBEDTLS_MD_CAN_SHA512) MBEDTLS_MD_SHA512, #endif #if defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_MD_SHA384, #endif #if defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_MD_SHA256, #endif #if defined(MBEDTLS_MD_CAN_SHA224) MBEDTLS_MD_SHA224, #endif #if defined(MBEDTLS_MD_CAN_SHA1) MBEDTLS_MD_SHA1, #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) MBEDTLS_MD_RIPEMD160, #endif #if defined(MBEDTLS_MD_CAN_MD5) MBEDTLS_MD_MD5, #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) MBEDTLS_MD_SHA3_224, #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) MBEDTLS_MD_SHA3_256, #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) MBEDTLS_MD_SHA3_384, #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) MBEDTLS_MD_SHA3_512, #endif MBEDTLS_MD_NONE }; const int *mbedtls_md_list(void) { return supported_digests; } typedef struct { const char *md_name; mbedtls_md_type_t md_type; } md_name_entry; static const md_name_entry md_names[] = { #if defined(MBEDTLS_MD_CAN_MD5) { "MD5", MBEDTLS_MD_MD5 }, #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) { "RIPEMD160", MBEDTLS_MD_RIPEMD160 }, #endif #if defined(MBEDTLS_MD_CAN_SHA1) { "SHA1", MBEDTLS_MD_SHA1 }, { "SHA", MBEDTLS_MD_SHA1 }, // compatibility fallback #endif #if defined(MBEDTLS_MD_CAN_SHA224) { "SHA224", MBEDTLS_MD_SHA224 }, #endif #if defined(MBEDTLS_MD_CAN_SHA256) { "SHA256", MBEDTLS_MD_SHA256 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { "SHA384", MBEDTLS_MD_SHA384 }, #endif #if defined(MBEDTLS_MD_CAN_SHA512) { "SHA512", MBEDTLS_MD_SHA512 }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) { "SHA3-224", MBEDTLS_MD_SHA3_224 }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) { "SHA3-256", MBEDTLS_MD_SHA3_256 }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) { "SHA3-384", MBEDTLS_MD_SHA3_384 }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) { "SHA3-512", MBEDTLS_MD_SHA3_512 }, #endif { NULL, MBEDTLS_MD_NONE }, }; const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name) { if (NULL == md_name) { return NULL; } const md_name_entry *entry = md_names; while (entry->md_name != NULL && strcmp(entry->md_name, md_name) != 0) { ++entry; } return mbedtls_md_info_from_type(entry->md_type); } const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info) { if (md_info == NULL) { return NULL; } const md_name_entry *entry = md_names; while (entry->md_type != MBEDTLS_MD_NONE && entry->md_type != md_info->type) { ++entry; } return entry->md_name; } const mbedtls_md_info_t *mbedtls_md_info_from_ctx( const mbedtls_md_context_t *ctx) { if (ctx == NULL) { return NULL; } return ctx->MBEDTLS_PRIVATE(md_info); } #if defined(MBEDTLS_FS_IO) int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; FILE *f; size_t n; mbedtls_md_context_t ctx; unsigned char buf[1024]; if (md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_MD_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); mbedtls_md_init(&ctx); if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) { goto cleanup; } if ((ret = mbedtls_md_starts(&ctx)) != 0) { goto cleanup; } while ((n = fread(buf, 1, sizeof(buf), f)) > 0) { if ((ret = mbedtls_md_update(&ctx, buf, n)) != 0) { goto cleanup; } } if (ferror(f) != 0) { ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; } else { ret = mbedtls_md_finish(&ctx, output); } cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); fclose(f); mbedtls_md_free(&ctx); return ret; } #endif /* MBEDTLS_FS_IO */ int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char sum[MBEDTLS_MD_MAX_SIZE]; unsigned char *ipad, *opad; if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } if (keylen > (size_t) ctx->md_info->block_size) { if ((ret = mbedtls_md_starts(ctx)) != 0) { goto cleanup; } if ((ret = mbedtls_md_update(ctx, key, keylen)) != 0) { goto cleanup; } if ((ret = mbedtls_md_finish(ctx, sum)) != 0) { goto cleanup; } keylen = ctx->md_info->size; key = sum; } ipad = (unsigned char *) ctx->hmac_ctx; opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; memset(ipad, 0x36, ctx->md_info->block_size); memset(opad, 0x5C, ctx->md_info->block_size); mbedtls_xor(ipad, ipad, key, keylen); mbedtls_xor(opad, opad, key, keylen); if ((ret = mbedtls_md_starts(ctx)) != 0) { goto cleanup; } if ((ret = mbedtls_md_update(ctx, ipad, ctx->md_info->block_size)) != 0) { goto cleanup; } cleanup: mbedtls_platform_zeroize(sum, sizeof(sum)); return ret; } int mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen) { if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } return mbedtls_md_update(ctx, input, ilen); } int mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; unsigned char *opad; if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; if ((ret = mbedtls_md_finish(ctx, tmp)) != 0) { return ret; } if ((ret = mbedtls_md_starts(ctx)) != 0) { return ret; } if ((ret = mbedtls_md_update(ctx, opad, ctx->md_info->block_size)) != 0) { return ret; } if ((ret = mbedtls_md_update(ctx, tmp, ctx->md_info->size)) != 0) { return ret; } return mbedtls_md_finish(ctx, output); } int mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *ipad; if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } ipad = (unsigned char *) ctx->hmac_ctx; if ((ret = mbedtls_md_starts(ctx)) != 0) { return ret; } return mbedtls_md_update(ctx, ipad, ctx->md_info->block_size); } int mbedtls_md_hmac(const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output) { mbedtls_md_context_t ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } mbedtls_md_init(&ctx); if ((ret = mbedtls_md_setup(&ctx, md_info, 1)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_starts(&ctx, key, keylen)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_update(&ctx, input, ilen)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_finish(&ctx, output)) != 0) { goto cleanup; } cleanup: mbedtls_md_free(&ctx); return ret; } #endif /* MBEDTLS_MD_C */ #endif /* MBEDTLS_MD_LIGHT */ webfakes/src/mbedtls/library/cmac.c0000644000176200001440000010144714740737024017014 0ustar liggesusers/** * \file cmac.c * * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The * CMAC Mode for Authentication * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf * * - RFC 4493 - The AES-CMAC Algorithm * https://tools.ietf.org/html/rfc4493 * * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) * Algorithm for the Internet Key Exchange Protocol (IKE) * https://tools.ietf.org/html/rfc4615 * * Additional test vectors: ISO/IEC 9797-1 * */ #include "common.h" #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "constant_time_internal.h" #include #if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) /* * Multiplication by u in the Galois field of GF(2^n) * * As explained in NIST SP 800-38B, this can be computed: * * If MSB(p) = 0, then p = (p << 1) * If MSB(p) = 1, then p = (p << 1) ^ R_n * with R_64 = 0x1B and R_128 = 0x87 * * Input and output MUST NOT point to the same buffer * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. */ static int cmac_multiply_by_u(unsigned char *output, const unsigned char *input, size_t blocksize) { const unsigned char R_128 = 0x87; unsigned char R_n; uint32_t overflow = 0x00; int i; if (blocksize == MBEDTLS_AES_BLOCK_SIZE) { R_n = R_128; } #if defined(MBEDTLS_DES_C) else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) { const unsigned char R_64 = 0x1B; R_n = R_64; } #endif else { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } for (i = (int) blocksize - 4; i >= 0; i -= 4) { uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0); uint32_t new_overflow = i32 >> 31; i32 = (i32 << 1) | overflow; MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0); overflow = new_overflow; } R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n); output[blocksize - 1] ^= R_n; return 0; } /* * Generate subkeys * * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm */ static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx, unsigned char *K1, unsigned char *K2) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char L[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; size_t olen, block_size; mbedtls_platform_zeroize(L, sizeof(L)); block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); /* Calculate Ek(0) */ if ((ret = mbedtls_cipher_update(ctx, L, block_size, L, &olen)) != 0) { goto exit; } /* * Generate K1 and K2 */ if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0) { goto exit; } if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0) { goto exit; } exit: mbedtls_platform_zeroize(L, sizeof(L)); return ret; } #endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ #if !defined(MBEDTLS_CMAC_ALT) /* * Create padded last block from (partial) last block. * * We can't use the padding option from the cipher layer, as it only works for * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. */ static void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE], size_t padded_block_len, const unsigned char *last_block, size_t last_block_len) { size_t j; for (j = 0; j < padded_block_len; j++) { if (j < last_block_len) { padded_block[j] = last_block[j]; } else if (j == last_block_len) { padded_block[j] = 0x80; } else { padded_block[j] = 0x00; } } } int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx, const unsigned char *key, size_t keybits) { mbedtls_cipher_type_t type; mbedtls_cmac_context_t *cmac_ctx; int retval; if (ctx == NULL || ctx->cipher_info == NULL || key == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if ((retval = mbedtls_cipher_setkey(ctx, key, (int) keybits, MBEDTLS_ENCRYPT)) != 0) { return retval; } type = mbedtls_cipher_info_get_type(ctx->cipher_info); switch (type) { case MBEDTLS_CIPHER_AES_128_ECB: case MBEDTLS_CIPHER_AES_192_ECB: case MBEDTLS_CIPHER_AES_256_ECB: case MBEDTLS_CIPHER_DES_EDE3_ECB: break; default: return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* Allocated and initialise in the cipher context memory for the CMAC * context */ cmac_ctx = mbedtls_calloc(1, sizeof(mbedtls_cmac_context_t)); if (cmac_ctx == NULL) { return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; } ctx->cmac_ctx = cmac_ctx; mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state)); return 0; } int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen) { mbedtls_cmac_context_t *cmac_ctx; unsigned char *state; int ret = 0; size_t n, j, olen, block_size; if (ctx == NULL || ctx->cipher_info == NULL || input == NULL || ctx->cmac_ctx == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } cmac_ctx = ctx->cmac_ctx; block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); state = ctx->cmac_ctx->state; /* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form * error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */ MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); /* Is there data still to process from the last call, that's greater in * size than a block? */ if (cmac_ctx->unprocessed_len > 0 && ilen > block_size - cmac_ctx->unprocessed_len) { memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], input, block_size - cmac_ctx->unprocessed_len); mbedtls_xor_no_simd(state, cmac_ctx->unprocessed_block, state, block_size); if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) != 0) { goto exit; } input += block_size - cmac_ctx->unprocessed_len; ilen -= block_size - cmac_ctx->unprocessed_len; cmac_ctx->unprocessed_len = 0; } /* n is the number of blocks including any final partial block */ n = (ilen + block_size - 1) / block_size; /* Iterate across the input data in block sized chunks, excluding any * final partial or complete block */ for (j = 1; j < n; j++) { mbedtls_xor_no_simd(state, input, state, block_size); if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) != 0) { goto exit; } ilen -= block_size; input += block_size; } /* If there is data left over that wasn't aligned to a block */ if (ilen > 0) { memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], input, ilen); cmac_ctx->unprocessed_len += ilen; } exit: return ret; } int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, unsigned char *output) { mbedtls_cmac_context_t *cmac_ctx; unsigned char *state, *last_block; unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; unsigned char M_last[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen, block_size; if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || output == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } cmac_ctx = ctx->cmac_ctx; block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); // silence GCC warning state = cmac_ctx->state; mbedtls_platform_zeroize(K1, sizeof(K1)); mbedtls_platform_zeroize(K2, sizeof(K2)); cmac_generate_subkeys(ctx, K1, K2); last_block = cmac_ctx->unprocessed_block; /* Calculate last block */ if (cmac_ctx->unprocessed_len < block_size) { cmac_pad(M_last, block_size, last_block, cmac_ctx->unprocessed_len); mbedtls_xor(M_last, M_last, K2, block_size); } else { /* Last block is complete block */ mbedtls_xor(M_last, last_block, K1, block_size); } mbedtls_xor(state, M_last, state, block_size); if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) != 0) { goto exit; } memcpy(output, state, block_size); exit: /* Wipe the generated keys on the stack, and any other transients to avoid * side channel leakage */ mbedtls_platform_zeroize(K1, sizeof(K1)); mbedtls_platform_zeroize(K2, sizeof(K2)); cmac_ctx->unprocessed_len = 0; mbedtls_platform_zeroize(cmac_ctx->unprocessed_block, sizeof(cmac_ctx->unprocessed_block)); mbedtls_platform_zeroize(state, MBEDTLS_CMAC_MAX_BLOCK_SIZE); return ret; } int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx) { mbedtls_cmac_context_t *cmac_ctx; if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } cmac_ctx = ctx->cmac_ctx; /* Reset the internal state */ cmac_ctx->unprocessed_len = 0; mbedtls_platform_zeroize(cmac_ctx->unprocessed_block, sizeof(cmac_ctx->unprocessed_block)); mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state)); return 0; } int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output) { mbedtls_cipher_context_t ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (cipher_info == NULL || key == NULL || input == NULL || output == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } mbedtls_cipher_init(&ctx); if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) { goto exit; } ret = mbedtls_cipher_cmac_starts(&ctx, key, keylen); if (ret != 0) { goto exit; } ret = mbedtls_cipher_cmac_update(&ctx, input, ilen); if (ret != 0) { goto exit; } ret = mbedtls_cipher_cmac_finish(&ctx, output); exit: mbedtls_cipher_free(&ctx); return ret; } #if defined(MBEDTLS_AES_C) /* * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 */ int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length, const unsigned char *input, size_t in_len, unsigned char output[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_cipher_info_t *cipher_info; unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; if (key == NULL || input == NULL || output == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); if (cipher_info == NULL) { /* Failing at this point must be due to a build issue */ ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; goto exit; } if (key_length == MBEDTLS_AES_BLOCK_SIZE) { /* Use key as is */ memcpy(int_key, key, MBEDTLS_AES_BLOCK_SIZE); } else { memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE); ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key, key_length, int_key); if (ret != 0) { goto exit; } } ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len, output); exit: mbedtls_platform_zeroize(int_key, sizeof(int_key)); return ret; } #endif /* MBEDTLS_AES_C */ #endif /* !MBEDTLS_CMAC_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * CMAC test data for SP800-38B * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf * * AES-CMAC-PRF-128 test data from RFC 4615 * https://tools.ietf.org/html/rfc4615#page-4 */ #define NB_CMAC_TESTS_PER_KEY 4 #define NB_PRF_TESTS 3 #if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) /* All CMAC test inputs are truncated from the same 64 byte buffer. */ static const unsigned char test_message[] = { /* PT */ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; #endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) /* Truncation point of message for AES CMAC tests */ static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { /* Mlen */ 0, 16, 20, 64 }; /* CMAC-AES128 Test Data */ static const unsigned char aes_128_key[16] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { { /* K1 */ 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde }, { /* K2 */ 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b } }; static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { { /* Example #1 */ 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 }, { /* Example #2 */ 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c }, { /* Example #3 */ 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde }, { /* Example #4 */ 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } }; /* CMAC-AES192 Test Data */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const unsigned char aes_192_key[24] = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b }; static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { { /* K1 */ 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 }, { /* K2 */ 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c } }; static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { { /* Example #1 */ 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 }, { /* Example #2 */ 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 }, { /* Example #3 */ 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 }, { /* Example #4 */ 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 } }; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* CMAC-AES256 Test Data */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const unsigned char aes_256_key[32] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 }; static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { { /* K1 */ 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f }, { /* K2 */ 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 } }; static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { { /* Example #1 */ 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 }, { /* Example #2 */ 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c }, { /* Example #3 */ 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 }, { /* Example #4 */ 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 } }; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_DES_C) /* Truncation point of message for 3DES CMAC tests */ static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { 0, 16, 20, 32 }; /* CMAC-TDES (Generation) - 2 Key Test Data */ static const unsigned char des3_2key_key[24] = { /* Key1 */ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, /* Key2 */ 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, /* Key3 */ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; static const unsigned char des3_2key_subkeys[2][8] = { { /* K1 */ 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 }, { /* K2 */ 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 } }; static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { { /* Sample #1 */ 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 }, { /* Sample #2 */ 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b }, { /* Sample #3 */ 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 }, { /* Sample #4 */ 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb } }; /* CMAC-TDES (Generation) - 3 Key Test Data */ static const unsigned char des3_3key_key[24] = { /* Key1 */ 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, /* Key2 */ 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, /* Key3 */ 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 }; static const unsigned char des3_3key_subkeys[2][8] = { { /* K1 */ 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 }, { /* K2 */ 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b } }; static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { { /* Sample #1 */ 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 }, { /* Sample #2 */ 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 }, { /* Sample #3 */ 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 }, { /* Sample #4 */ 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 } }; #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) /* AES AES-CMAC-PRF-128 Test Data */ static const unsigned char PRFK[] = { /* Key */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xed, 0xcb }; /* Sizes in bytes */ static const size_t PRFKlen[NB_PRF_TESTS] = { 18, 16, 10 }; /* Message */ static const unsigned char PRFM[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 }; static const unsigned char PRFT[NB_PRF_TESTS][16] = { { 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a }, { 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d }, { 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d } }; #endif /* MBEDTLS_AES_C */ static int cmac_test_subkeys(int verbose, const char *testname, const unsigned char *key, int keybits, const unsigned char *subkeys, mbedtls_cipher_type_t cipher_type, int block_size, int num_tests) { int i, ret = 0; mbedtls_cipher_context_t ctx; const mbedtls_cipher_info_t *cipher_info; unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (cipher_info == NULL) { /* Failing at this point must be due to a build issue */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } for (i = 0; i < num_tests; i++) { if (verbose != 0) { mbedtls_printf(" %s CMAC subkey #%d: ", testname, i + 1); } mbedtls_cipher_init(&ctx); if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) { if (verbose != 0) { mbedtls_printf("test execution failed\n"); } goto cleanup; } if ((ret = mbedtls_cipher_setkey(&ctx, key, keybits, MBEDTLS_ENCRYPT)) != 0) { /* When CMAC is implemented by an alternative implementation, or * the underlying primitive itself is implemented alternatively, * AES-192 may be unavailable. This should not cause the selftest * function to fail. */ if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED || ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) && cipher_type == MBEDTLS_CIPHER_AES_192_ECB) { if (verbose != 0) { mbedtls_printf("skipped\n"); } goto next_test; } if (verbose != 0) { mbedtls_printf("test execution failed\n"); } goto cleanup; } ret = cmac_generate_subkeys(&ctx, K1, K2); if (ret != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto cleanup; } if ((ret = memcmp(K1, subkeys, block_size)) != 0 || (ret = memcmp(K2, &subkeys[block_size], block_size)) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } next_test: mbedtls_cipher_free(&ctx); } ret = 0; goto exit; cleanup: mbedtls_cipher_free(&ctx); exit: return ret; } static int cmac_test_wth_cipher(int verbose, const char *testname, const unsigned char *key, int keybits, const unsigned char *messages, const unsigned int message_lengths[4], const unsigned char *expected_result, mbedtls_cipher_type_t cipher_type, int block_size, int num_tests) { const mbedtls_cipher_info_t *cipher_info; int i, ret = 0; unsigned char output[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (cipher_info == NULL) { /* Failing at this point must be due to a build issue */ ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; goto exit; } for (i = 0; i < num_tests; i++) { if (verbose != 0) { mbedtls_printf(" %s CMAC #%d: ", testname, i + 1); } if ((ret = mbedtls_cipher_cmac(cipher_info, key, keybits, messages, message_lengths[i], output)) != 0) { /* When CMAC is implemented by an alternative implementation, or * the underlying primitive itself is implemented alternatively, * AES-192 and/or 3DES may be unavailable. This should not cause * the selftest function to fail. */ if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED || ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) && (cipher_type == MBEDTLS_CIPHER_AES_192_ECB || cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB)) { if (verbose != 0) { mbedtls_printf("skipped\n"); } continue; } if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } if ((ret = memcmp(output, &expected_result[i * block_size], block_size)) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } ret = 0; exit: return ret; } #if defined(MBEDTLS_AES_C) static int test_aes128_cmac_prf(int verbose) { int i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; for (i = 0; i < NB_PRF_TESTS; i++) { mbedtls_printf(" AES CMAC 128 PRF #%d: ", i); ret = mbedtls_aes_cmac_prf_128(PRFK, PRFKlen[i], PRFM, 20, output); if (ret != 0 || memcmp(output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return ret; } else if (verbose != 0) { mbedtls_printf("passed\n"); } } return ret; } #endif /* MBEDTLS_AES_C */ int mbedtls_cmac_self_test(int verbose) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_AES_C) /* AES-128 */ if ((ret = cmac_test_subkeys(verbose, "AES 128", aes_128_key, 128, (const unsigned char *) aes_128_subkeys, MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "AES 128", aes_128_key, 128, test_message, aes_message_lengths, (const unsigned char *) aes_128_expected_result, MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } /* AES-192 */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) if ((ret = cmac_test_subkeys(verbose, "AES 192", aes_192_key, 192, (const unsigned char *) aes_192_subkeys, MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "AES 192", aes_192_key, 192, test_message, aes_message_lengths, (const unsigned char *) aes_192_expected_result, MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* AES-256 */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) if ((ret = cmac_test_subkeys(verbose, "AES 256", aes_256_key, 256, (const unsigned char *) aes_256_subkeys, MBEDTLS_CIPHER_AES_256_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "AES 256", aes_256_key, 256, test_message, aes_message_lengths, (const unsigned char *) aes_256_expected_result, MBEDTLS_CIPHER_AES_256_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_DES_C) /* 3DES 2 key */ if ((ret = cmac_test_subkeys(verbose, "3DES 2 key", des3_2key_key, 192, (const unsigned char *) des3_2key_subkeys, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "3DES 2 key", des3_2key_key, 192, test_message, des3_message_lengths, (const unsigned char *) des3_2key_expected_result, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } /* 3DES 3 key */ if ((ret = cmac_test_subkeys(verbose, "3DES 3 key", des3_3key_key, 192, (const unsigned char *) des3_3key_subkeys, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "3DES 3 key", des3_3key_key, 192, test_message, des3_message_lengths, (const unsigned char *) des3_3key_expected_result, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) if ((ret = test_aes128_cmac_prf(verbose)) != 0) { return ret; } #endif /* MBEDTLS_AES_C */ if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_CMAC_C */ webfakes/src/mbedtls/library/sha256.c0000644000176200001440000007266214740737024017127 0ustar liggesusers/* * FIPS-180-2 compliant SHA-256 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-256 Secure Hash Standard was published by NIST in 2002. * * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ #if defined(__clang__) && (__clang_major__ >= 4) /* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if, * but that is defined by build_info.h, and we need this block to happen first. */ #if defined(__ARM_ARCH) && (__ARM_ARCH_PROFILE == 'A') #if __ARM_ARCH >= 8 #define MBEDTLS_SHA256_ARCH_IS_ARMV8_A #endif #endif #if defined(MBEDTLS_SHA256_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO) /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. * * The intrinsic declaration are guarded by predefined ACLE macros in clang: * these are normally only enabled by the -march option on the command line. * By defining the macros ourselves we gain access to those declarations without * requiring -march on the command line. * * `arm_neon.h` is included by common.h, so we put these defines * at the top of this file, before any includes. */ #define __ARM_FEATURE_CRYPTO 1 /* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions * * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it * for older compilers. */ #define __ARM_FEATURE_SHA2 1 #define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG #endif #endif /* defined(__clang__) && (__clang_major__ >= 4) */ /* Ensure that SIG_SETMASK is defined when -std=c99 is used. */ #if !defined(_GNU_SOURCE) #define _GNU_SOURCE #endif #include "common.h" #if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C) #include "mbedtls/sha256.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if defined(MBEDTLS_ARCH_IS_ARMV8_A) # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) # if !defined(MBEDTLS_HAVE_NEON_INTRINSICS) # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) # warning "Target does not support NEON instructions" # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT # else # error "Target does not support NEON instructions" # endif # endif # endif # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) /* *INDENT-OFF* */ # if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) # if defined(__ARMCOMPILER_VERSION) # if __ARMCOMPILER_VERSION <= 6090000 # error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" # endif # pragma clang attribute push (__attribute__((target("sha2"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # elif defined(__clang__) # if __clang_major__ < 4 # error "A more recent Clang is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" # endif # pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # elif defined(__GNUC__) /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some * intrinsics are missing. Missing intrinsics could be worked around. */ # if __GNUC__ < 6 # error "A more recent GCC is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" # else # pragma GCC push_options # pragma GCC target ("arch=armv8-a+crypto") # define MBEDTLS_POP_TARGET_PRAGMA # endif # else # error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" # endif # endif /* *INDENT-ON* */ # endif # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) # if defined(__unix__) # if defined(__linux__) /* Our preferred method of detection is getauxval() */ # include /* These are not always defined via sys/auxv.h */ # if !defined(HWCAP_SHA2) # define HWCAP_SHA2 (1 << 6) # endif # if !defined(HWCAP2_SHA2) # define HWCAP2_SHA2 (1 << 3) # endif # endif /* Use SIGILL on Unix, and fall back to it on Linux */ # include # endif # endif #elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) /* * Capability detection code comes early, so we can disable * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT if no detection mechanism found */ #if defined(MBEDTLS_ARCH_IS_ARM64) && defined(HWCAP_SHA2) static int mbedtls_a64_crypto_sha256_determine_support(void) { return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0; } #elif defined(MBEDTLS_ARCH_IS_ARM32) && defined(HWCAP2_SHA2) static int mbedtls_a64_crypto_sha256_determine_support(void) { return (getauxval(AT_HWCAP2) & HWCAP2_SHA2) ? 1 : 0; } #elif defined(__APPLE__) static int mbedtls_a64_crypto_sha256_determine_support(void) { return 1; } #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #include static int mbedtls_a64_crypto_sha256_determine_support(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } #elif defined(__unix__) && defined(SIG_SETMASK) /* Detection with SIGILL, setjmp() and longjmp() */ #include #include static jmp_buf return_from_sigill; /* * Armv8-A SHA256 support detection via SIGILL */ static void sigill_handler(int signal) { (void) signal; longjmp(return_from_sigill, 1); } static int mbedtls_a64_crypto_sha256_determine_support(void) { struct sigaction old_action, new_action; sigset_t old_mask; if (sigprocmask(0, NULL, &old_mask)) { return 0; } sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; new_action.sa_handler = sigill_handler; sigaction(SIGILL, &new_action, &old_action); static int ret = 0; if (setjmp(return_from_sigill) == 0) { /* First return only */ /* If this traps, we will return a second time from setjmp() with 1 */ #if defined(MBEDTLS_ARCH_IS_ARM64) asm volatile ("sha256h q0, q0, v0.4s" : : : "v0"); #else asm volatile ("sha256h.32 q0, q0, q0" : : : "q0"); #endif ret = 1; } sigaction(SIGILL, &old_action, NULL); sigprocmask(SIG_SETMASK, &old_mask, NULL); return ret; } #else #warning "No mechanism to detect ARMV8_CRYPTO found, using C code only" #undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT #endif /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */ #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ #if !defined(MBEDTLS_SHA256_ALT) #define SHA256_BLOCK_SIZE 64 void mbedtls_sha256_init(mbedtls_sha256_context *ctx) { memset(ctx, 0, sizeof(mbedtls_sha256_context)); } void mbedtls_sha256_free(mbedtls_sha256_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha256_context)); } void mbedtls_sha256_clone(mbedtls_sha256_context *dst, const mbedtls_sha256_context *src) { *dst = *src; } /* * SHA-256 context setup */ int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224) { #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) if (is224 != 0 && is224 != 1) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #elif defined(MBEDTLS_SHA256_C) if (is224 != 0) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #else /* defined MBEDTLS_SHA224_C only */ if (is224 == 0) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #endif ctx->total[0] = 0; ctx->total[1] = 0; if (is224 == 0) { #if defined(MBEDTLS_SHA256_C) ctx->state[0] = 0x6A09E667; ctx->state[1] = 0xBB67AE85; ctx->state[2] = 0x3C6EF372; ctx->state[3] = 0xA54FF53A; ctx->state[4] = 0x510E527F; ctx->state[5] = 0x9B05688C; ctx->state[6] = 0x1F83D9AB; ctx->state[7] = 0x5BE0CD19; #endif } else { #if defined(MBEDTLS_SHA224_C) ctx->state[0] = 0xC1059ED8; ctx->state[1] = 0x367CD507; ctx->state[2] = 0x3070DD17; ctx->state[3] = 0xF70E5939; ctx->state[4] = 0xFFC00B31; ctx->state[5] = 0x68581511; ctx->state[6] = 0x64F98FA7; ctx->state[7] = 0xBEFA4FA4; #endif } #if defined(MBEDTLS_SHA224_C) ctx->is224 = is224; #endif return 0; } #if !defined(MBEDTLS_SHA256_PROCESS_ALT) static const uint32_t K[] = { 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, }; #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) # define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many # define mbedtls_internal_sha256_process_a64_crypto mbedtls_internal_sha256_process #endif static size_t mbedtls_internal_sha256_process_many_a64_crypto( mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len) { uint32x4_t abcd = vld1q_u32(&ctx->state[0]); uint32x4_t efgh = vld1q_u32(&ctx->state[4]); size_t processed = 0; for (; len >= SHA256_BLOCK_SIZE; processed += SHA256_BLOCK_SIZE, msg += SHA256_BLOCK_SIZE, len -= SHA256_BLOCK_SIZE) { uint32x4_t tmp, abcd_prev; uint32x4_t abcd_orig = abcd; uint32x4_t efgh_orig = efgh; uint32x4_t sched0 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 0)); uint32x4_t sched1 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 1)); uint32x4_t sched2 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 2)); uint32x4_t sched3 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 3)); #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* Will be true if not defined */ /* Untested on BE */ sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0))); sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1))); sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2))); sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3))); #endif /* Rounds 0 to 3 */ tmp = vaddq_u32(sched0, vld1q_u32(&K[0])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds 4 to 7 */ tmp = vaddq_u32(sched1, vld1q_u32(&K[4])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds 8 to 11 */ tmp = vaddq_u32(sched2, vld1q_u32(&K[8])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds 12 to 15 */ tmp = vaddq_u32(sched3, vld1q_u32(&K[12])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); for (int t = 16; t < 64; t += 16) { /* Rounds t to t + 3 */ sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3); tmp = vaddq_u32(sched0, vld1q_u32(&K[t])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds t + 4 to t + 7 */ sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0); tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds t + 8 to t + 11 */ sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1); tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds t + 12 to t + 15 */ sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2); tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); } abcd = vaddq_u32(abcd, abcd_orig); efgh = vaddq_u32(efgh, efgh_orig); } vst1q_u32(&ctx->state[0], abcd); vst1q_u32(&ctx->state[4], efgh); return processed; } #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) /* * This function is for internal use only if we are building both C and Armv8-A * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() */ static #endif int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_SIZE]) { return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data, SHA256_BLOCK_SIZE) == SHA256_BLOCK_SIZE) ? 0 : -1; } #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ #if defined(MBEDTLS_POP_TARGET_PRAGMA) #if defined(__clang__) #pragma clang attribute pop #elif defined(__GNUC__) #pragma GCC pop_options #endif #undef MBEDTLS_POP_TARGET_PRAGMA #endif #if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) #define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many #define mbedtls_internal_sha256_process_c mbedtls_internal_sha256_process #endif #if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \ !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #define SHR(x, n) (((x) & 0xFFFFFFFF) >> (n)) #define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n)))) #define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) #define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) #define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) #define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) #define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y)))) #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define R(t) \ ( \ local.W[t] = S1(local.W[(t) - 2]) + local.W[(t) - 7] + \ S0(local.W[(t) - 15]) + local.W[(t) - 16] \ ) #define P(a, b, c, d, e, f, g, h, x, K) \ do \ { \ local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x); \ local.temp2 = S2(a) + F0((a), (b), (c)); \ (d) += local.temp1; (h) = local.temp1 + local.temp2; \ } while (0) #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) /* * This function is for internal use only if we are building both C and Armv8 * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() */ static #endif int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_SIZE]) { struct { uint32_t temp1, temp2, W[64]; uint32_t A[8]; } local; unsigned int i; for (i = 0; i < 8; i++) { local.A[i] = ctx->state[i]; } #if defined(MBEDTLS_SHA256_SMALLER) for (i = 0; i < 64; i++) { if (i < 16) { local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i); } else { R(i); } P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i], K[i]); local.temp1 = local.A[7]; local.A[7] = local.A[6]; local.A[6] = local.A[5]; local.A[5] = local.A[4]; local.A[4] = local.A[3]; local.A[3] = local.A[2]; local.A[2] = local.A[1]; local.A[1] = local.A[0]; local.A[0] = local.temp1; } #else /* MBEDTLS_SHA256_SMALLER */ for (i = 0; i < 16; i++) { local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i); } for (i = 0; i < 16; i += 8) { P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0]); P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1]); P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2]); P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3]); P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4]); P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5]); P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6]); P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7]); } for (i = 16; i < 64; i += 8) { P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], R(i+0), K[i+0]); P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], R(i+1), K[i+1]); P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], R(i+2), K[i+2]); P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], R(i+3), K[i+3]); P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], R(i+4), K[i+4]); P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], R(i+5), K[i+5]); P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], R(i+6), K[i+6]); P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], R(i+7), K[i+7]); } #endif /* MBEDTLS_SHA256_SMALLER */ for (i = 0; i < 8; i++) { ctx->state[i] += local.A[i]; } /* Zeroise buffers and variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ #if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) static size_t mbedtls_internal_sha256_process_many_c( mbedtls_sha256_context *ctx, const uint8_t *data, size_t len) { size_t processed = 0; while (len >= SHA256_BLOCK_SIZE) { if (mbedtls_internal_sha256_process_c(ctx, data) != 0) { return 0; } data += SHA256_BLOCK_SIZE; len -= SHA256_BLOCK_SIZE; processed += SHA256_BLOCK_SIZE; } return processed; } #endif /* !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) static int mbedtls_a64_crypto_sha256_has_support(void) { static int done = 0; static int supported = 0; if (!done) { supported = mbedtls_a64_crypto_sha256_determine_support(); done = 1; } return supported; } static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len) { if (mbedtls_a64_crypto_sha256_has_support()) { return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len); } else { return mbedtls_internal_sha256_process_many_c(ctx, msg, len); } } int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_SIZE]) { if (mbedtls_a64_crypto_sha256_has_support()) { return mbedtls_internal_sha256_process_a64_crypto(ctx, data); } else { return mbedtls_internal_sha256_process_c(ctx, data); } } #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ /* * SHA-256 process buffer */ int mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; if (ilen == 0) { return 0; } left = ctx->total[0] & 0x3F; fill = SHA256_BLOCK_SIZE - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if (ctx->total[0] < (uint32_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= SHA256_BLOCK_SIZE) { size_t processed = mbedtls_internal_sha256_process_many(ctx, input, ilen); if (processed < SHA256_BLOCK_SIZE) { return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } input += processed; ilen -= processed; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } /* * SHA-256 final digest */ int mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t used; uint32_t high, low; int truncated = 0; /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ used = ctx->total[0] & 0x3F; ctx->buffer[used++] = 0x80; if (used <= 56) { /* Enough room for padding + length in current block */ memset(ctx->buffer + used, 0, 56 - used); } else { /* We'll need an extra block */ memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used); if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { goto exit; } memset(ctx->buffer, 0, 56); } /* * Add message length */ high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56); MBEDTLS_PUT_UINT32_BE(low, ctx->buffer, 60); if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { goto exit; } /* * Output final state */ MBEDTLS_PUT_UINT32_BE(ctx->state[0], output, 0); MBEDTLS_PUT_UINT32_BE(ctx->state[1], output, 4); MBEDTLS_PUT_UINT32_BE(ctx->state[2], output, 8); MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12); MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16); MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20); MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24); #if defined(MBEDTLS_SHA224_C) truncated = ctx->is224; #endif if (!truncated) { MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28); } ret = 0; exit: mbedtls_sha256_free(ctx); return ret; } #endif /* !MBEDTLS_SHA256_ALT */ /* * output = SHA-256( input buffer ) */ int mbedtls_sha256(const unsigned char *input, size_t ilen, unsigned char *output, int is224) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha256_context ctx; #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) if (is224 != 0 && is224 != 1) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #elif defined(MBEDTLS_SHA256_C) if (is224 != 0) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #else /* defined MBEDTLS_SHA224_C only */ if (is224 == 0) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #endif mbedtls_sha256_init(&ctx); if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { goto exit; } if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_sha256_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors */ static const unsigned char sha_test_buf[3][57] = { { "abc" }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { "" } }; static const size_t sha_test_buflen[3] = { 3, 56, 1000 }; typedef const unsigned char (sha_test_sum_t)[32]; /* * SHA-224 test vectors */ #if defined(MBEDTLS_SHA224_C) static sha_test_sum_t sha224_test_sum[] = { { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, 0xE3, 0x6C, 0x9D, 0xA7 }, { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, 0x52, 0x52, 0x25, 0x25 }, { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, 0x4E, 0xE7, 0xAD, 0x67 } }; #endif /* * SHA-256 test vectors */ #if defined(MBEDTLS_SHA256_C) static sha_test_sum_t sha256_test_sum[] = { { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } }; #endif /* * Checkup routine */ static int mbedtls_sha256_common_self_test(int verbose, int is224) { int i, buflen, ret = 0; unsigned char *buf; unsigned char sha256sum[32]; mbedtls_sha256_context ctx; #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum; #elif defined(MBEDTLS_SHA256_C) sha_test_sum_t *sha_test_sum = sha256_test_sum; #else sha_test_sum_t *sha_test_sum = sha224_test_sum; #endif buf = mbedtls_calloc(1024, sizeof(unsigned char)); if (NULL == buf) { if (verbose != 0) { mbedtls_printf("Buffer allocation failed\n"); } return 1; } mbedtls_sha256_init(&ctx); for (i = 0; i < 3; i++) { if (verbose != 0) { mbedtls_printf(" SHA-%d test #%d: ", 256 - is224 * 32, i + 1); } if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { goto fail; } if (i == 2) { memset(buf, 'a', buflen = 1000); for (int j = 0; j < 1000; j++) { ret = mbedtls_sha256_update(&ctx, buf, buflen); if (ret != 0) { goto fail; } } } else { ret = mbedtls_sha256_update(&ctx, sha_test_buf[i], sha_test_buflen[i]); if (ret != 0) { goto fail; } } if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) { goto fail; } if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 4) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } goto exit; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } exit: mbedtls_sha256_free(&ctx); mbedtls_free(buf); return ret; } #if defined(MBEDTLS_SHA256_C) int mbedtls_sha256_self_test(int verbose) { return mbedtls_sha256_common_self_test(verbose, 0); } #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA224_C) int mbedtls_sha224_self_test(int verbose) { return mbedtls_sha256_common_self_test(verbose, 1); } #endif /* MBEDTLS_SHA224_C */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */ webfakes/src/mbedtls/library/aes.c0000644000176200001440000023171614740737024016664 0ustar liggesusers/* * FIPS-197 compliant AES implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. * * https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf */ #include "common.h" #if defined(MBEDTLS_AES_C) #include #include "mbedtls/aes.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) #if !((defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_AESCE_C)) || \ (defined(MBEDTLS_ARCH_IS_X64) && defined(MBEDTLS_AESNI_C)) || \ (defined(MBEDTLS_ARCH_IS_X86) && defined(MBEDTLS_AESNI_C))) #error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites" #endif #endif #if defined(MBEDTLS_ARCH_IS_X86) #if defined(MBEDTLS_PADLOCK_C) #if !defined(MBEDTLS_HAVE_ASM) #error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) #error "MBEDTLS_AES_USE_HARDWARE_ONLY cannot be defined when " \ "MBEDTLS_PADLOCK_C is set" #endif #endif #endif #if defined(MBEDTLS_PADLOCK_C) #include "padlock.h" #endif #if defined(MBEDTLS_AESNI_C) #include "aesni.h" #endif #if defined(MBEDTLS_AESCE_C) #include "aesce.h" #endif #include "mbedtls/platform.h" #include "ctr.h" /* * This is a convenience shorthand macro to check if we need reverse S-box and * reverse tables. It's private and only defined in this file. */ #if (!defined(MBEDTLS_AES_DECRYPT_ALT) || \ (!defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY))) && \ !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) #define MBEDTLS_AES_NEED_REVERSE_TABLES #endif #if !defined(MBEDTLS_AES_ALT) #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) static int aes_padlock_ace = -1; #endif #if defined(MBEDTLS_AES_ROM_TABLES) /* * Forward S-box */ MBEDTLS_MAYBE_UNUSED static const unsigned char FSb[256] = { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; /* * Forward tables */ #define FT \ \ V(A5, 63, 63, C6), V(84, 7C, 7C, F8), V(99, 77, 77, EE), V(8D, 7B, 7B, F6), \ V(0D, F2, F2, FF), V(BD, 6B, 6B, D6), V(B1, 6F, 6F, DE), V(54, C5, C5, 91), \ V(50, 30, 30, 60), V(03, 01, 01, 02), V(A9, 67, 67, CE), V(7D, 2B, 2B, 56), \ V(19, FE, FE, E7), V(62, D7, D7, B5), V(E6, AB, AB, 4D), V(9A, 76, 76, EC), \ V(45, CA, CA, 8F), V(9D, 82, 82, 1F), V(40, C9, C9, 89), V(87, 7D, 7D, FA), \ V(15, FA, FA, EF), V(EB, 59, 59, B2), V(C9, 47, 47, 8E), V(0B, F0, F0, FB), \ V(EC, AD, AD, 41), V(67, D4, D4, B3), V(FD, A2, A2, 5F), V(EA, AF, AF, 45), \ V(BF, 9C, 9C, 23), V(F7, A4, A4, 53), V(96, 72, 72, E4), V(5B, C0, C0, 9B), \ V(C2, B7, B7, 75), V(1C, FD, FD, E1), V(AE, 93, 93, 3D), V(6A, 26, 26, 4C), \ V(5A, 36, 36, 6C), V(41, 3F, 3F, 7E), V(02, F7, F7, F5), V(4F, CC, CC, 83), \ V(5C, 34, 34, 68), V(F4, A5, A5, 51), V(34, E5, E5, D1), V(08, F1, F1, F9), \ V(93, 71, 71, E2), V(73, D8, D8, AB), V(53, 31, 31, 62), V(3F, 15, 15, 2A), \ V(0C, 04, 04, 08), V(52, C7, C7, 95), V(65, 23, 23, 46), V(5E, C3, C3, 9D), \ V(28, 18, 18, 30), V(A1, 96, 96, 37), V(0F, 05, 05, 0A), V(B5, 9A, 9A, 2F), \ V(09, 07, 07, 0E), V(36, 12, 12, 24), V(9B, 80, 80, 1B), V(3D, E2, E2, DF), \ V(26, EB, EB, CD), V(69, 27, 27, 4E), V(CD, B2, B2, 7F), V(9F, 75, 75, EA), \ V(1B, 09, 09, 12), V(9E, 83, 83, 1D), V(74, 2C, 2C, 58), V(2E, 1A, 1A, 34), \ V(2D, 1B, 1B, 36), V(B2, 6E, 6E, DC), V(EE, 5A, 5A, B4), V(FB, A0, A0, 5B), \ V(F6, 52, 52, A4), V(4D, 3B, 3B, 76), V(61, D6, D6, B7), V(CE, B3, B3, 7D), \ V(7B, 29, 29, 52), V(3E, E3, E3, DD), V(71, 2F, 2F, 5E), V(97, 84, 84, 13), \ V(F5, 53, 53, A6), V(68, D1, D1, B9), V(00, 00, 00, 00), V(2C, ED, ED, C1), \ V(60, 20, 20, 40), V(1F, FC, FC, E3), V(C8, B1, B1, 79), V(ED, 5B, 5B, B6), \ V(BE, 6A, 6A, D4), V(46, CB, CB, 8D), V(D9, BE, BE, 67), V(4B, 39, 39, 72), \ V(DE, 4A, 4A, 94), V(D4, 4C, 4C, 98), V(E8, 58, 58, B0), V(4A, CF, CF, 85), \ V(6B, D0, D0, BB), V(2A, EF, EF, C5), V(E5, AA, AA, 4F), V(16, FB, FB, ED), \ V(C5, 43, 43, 86), V(D7, 4D, 4D, 9A), V(55, 33, 33, 66), V(94, 85, 85, 11), \ V(CF, 45, 45, 8A), V(10, F9, F9, E9), V(06, 02, 02, 04), V(81, 7F, 7F, FE), \ V(F0, 50, 50, A0), V(44, 3C, 3C, 78), V(BA, 9F, 9F, 25), V(E3, A8, A8, 4B), \ V(F3, 51, 51, A2), V(FE, A3, A3, 5D), V(C0, 40, 40, 80), V(8A, 8F, 8F, 05), \ V(AD, 92, 92, 3F), V(BC, 9D, 9D, 21), V(48, 38, 38, 70), V(04, F5, F5, F1), \ V(DF, BC, BC, 63), V(C1, B6, B6, 77), V(75, DA, DA, AF), V(63, 21, 21, 42), \ V(30, 10, 10, 20), V(1A, FF, FF, E5), V(0E, F3, F3, FD), V(6D, D2, D2, BF), \ V(4C, CD, CD, 81), V(14, 0C, 0C, 18), V(35, 13, 13, 26), V(2F, EC, EC, C3), \ V(E1, 5F, 5F, BE), V(A2, 97, 97, 35), V(CC, 44, 44, 88), V(39, 17, 17, 2E), \ V(57, C4, C4, 93), V(F2, A7, A7, 55), V(82, 7E, 7E, FC), V(47, 3D, 3D, 7A), \ V(AC, 64, 64, C8), V(E7, 5D, 5D, BA), V(2B, 19, 19, 32), V(95, 73, 73, E6), \ V(A0, 60, 60, C0), V(98, 81, 81, 19), V(D1, 4F, 4F, 9E), V(7F, DC, DC, A3), \ V(66, 22, 22, 44), V(7E, 2A, 2A, 54), V(AB, 90, 90, 3B), V(83, 88, 88, 0B), \ V(CA, 46, 46, 8C), V(29, EE, EE, C7), V(D3, B8, B8, 6B), V(3C, 14, 14, 28), \ V(79, DE, DE, A7), V(E2, 5E, 5E, BC), V(1D, 0B, 0B, 16), V(76, DB, DB, AD), \ V(3B, E0, E0, DB), V(56, 32, 32, 64), V(4E, 3A, 3A, 74), V(1E, 0A, 0A, 14), \ V(DB, 49, 49, 92), V(0A, 06, 06, 0C), V(6C, 24, 24, 48), V(E4, 5C, 5C, B8), \ V(5D, C2, C2, 9F), V(6E, D3, D3, BD), V(EF, AC, AC, 43), V(A6, 62, 62, C4), \ V(A8, 91, 91, 39), V(A4, 95, 95, 31), V(37, E4, E4, D3), V(8B, 79, 79, F2), \ V(32, E7, E7, D5), V(43, C8, C8, 8B), V(59, 37, 37, 6E), V(B7, 6D, 6D, DA), \ V(8C, 8D, 8D, 01), V(64, D5, D5, B1), V(D2, 4E, 4E, 9C), V(E0, A9, A9, 49), \ V(B4, 6C, 6C, D8), V(FA, 56, 56, AC), V(07, F4, F4, F3), V(25, EA, EA, CF), \ V(AF, 65, 65, CA), V(8E, 7A, 7A, F4), V(E9, AE, AE, 47), V(18, 08, 08, 10), \ V(D5, BA, BA, 6F), V(88, 78, 78, F0), V(6F, 25, 25, 4A), V(72, 2E, 2E, 5C), \ V(24, 1C, 1C, 38), V(F1, A6, A6, 57), V(C7, B4, B4, 73), V(51, C6, C6, 97), \ V(23, E8, E8, CB), V(7C, DD, DD, A1), V(9C, 74, 74, E8), V(21, 1F, 1F, 3E), \ V(DD, 4B, 4B, 96), V(DC, BD, BD, 61), V(86, 8B, 8B, 0D), V(85, 8A, 8A, 0F), \ V(90, 70, 70, E0), V(42, 3E, 3E, 7C), V(C4, B5, B5, 71), V(AA, 66, 66, CC), \ V(D8, 48, 48, 90), V(05, 03, 03, 06), V(01, F6, F6, F7), V(12, 0E, 0E, 1C), \ V(A3, 61, 61, C2), V(5F, 35, 35, 6A), V(F9, 57, 57, AE), V(D0, B9, B9, 69), \ V(91, 86, 86, 17), V(58, C1, C1, 99), V(27, 1D, 1D, 3A), V(B9, 9E, 9E, 27), \ V(38, E1, E1, D9), V(13, F8, F8, EB), V(B3, 98, 98, 2B), V(33, 11, 11, 22), \ V(BB, 69, 69, D2), V(70, D9, D9, A9), V(89, 8E, 8E, 07), V(A7, 94, 94, 33), \ V(B6, 9B, 9B, 2D), V(22, 1E, 1E, 3C), V(92, 87, 87, 15), V(20, E9, E9, C9), \ V(49, CE, CE, 87), V(FF, 55, 55, AA), V(78, 28, 28, 50), V(7A, DF, DF, A5), \ V(8F, 8C, 8C, 03), V(F8, A1, A1, 59), V(80, 89, 89, 09), V(17, 0D, 0D, 1A), \ V(DA, BF, BF, 65), V(31, E6, E6, D7), V(C6, 42, 42, 84), V(B8, 68, 68, D0), \ V(C3, 41, 41, 82), V(B0, 99, 99, 29), V(77, 2D, 2D, 5A), V(11, 0F, 0F, 1E), \ V(CB, B0, B0, 7B), V(FC, 54, 54, A8), V(D6, BB, BB, 6D), V(3A, 16, 16, 2C) #define V(a, b, c, d) 0x##a##b##c##d MBEDTLS_MAYBE_UNUSED static const uint32_t FT0[256] = { FT }; #undef V #define V(a, b, c, d) 0x##b##c##d##a MBEDTLS_MAYBE_UNUSED static const uint32_t FT1[256] = { FT }; #undef V #define V(a, b, c, d) 0x##c##d##a##b MBEDTLS_MAYBE_UNUSED static const uint32_t FT2[256] = { FT }; #undef V #define V(a, b, c, d) 0x##d##a##b##c MBEDTLS_MAYBE_UNUSED static const uint32_t FT3[256] = { FT }; #undef V #undef FT /* * Reverse S-box */ MBEDTLS_MAYBE_UNUSED static const unsigned char RSb[256] = { 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D }; /* * Reverse tables */ #define RT \ \ V(50, A7, F4, 51), V(53, 65, 41, 7E), V(C3, A4, 17, 1A), V(96, 5E, 27, 3A), \ V(CB, 6B, AB, 3B), V(F1, 45, 9D, 1F), V(AB, 58, FA, AC), V(93, 03, E3, 4B), \ V(55, FA, 30, 20), V(F6, 6D, 76, AD), V(91, 76, CC, 88), V(25, 4C, 02, F5), \ V(FC, D7, E5, 4F), V(D7, CB, 2A, C5), V(80, 44, 35, 26), V(8F, A3, 62, B5), \ V(49, 5A, B1, DE), V(67, 1B, BA, 25), V(98, 0E, EA, 45), V(E1, C0, FE, 5D), \ V(02, 75, 2F, C3), V(12, F0, 4C, 81), V(A3, 97, 46, 8D), V(C6, F9, D3, 6B), \ V(E7, 5F, 8F, 03), V(95, 9C, 92, 15), V(EB, 7A, 6D, BF), V(DA, 59, 52, 95), \ V(2D, 83, BE, D4), V(D3, 21, 74, 58), V(29, 69, E0, 49), V(44, C8, C9, 8E), \ V(6A, 89, C2, 75), V(78, 79, 8E, F4), V(6B, 3E, 58, 99), V(DD, 71, B9, 27), \ V(B6, 4F, E1, BE), V(17, AD, 88, F0), V(66, AC, 20, C9), V(B4, 3A, CE, 7D), \ V(18, 4A, DF, 63), V(82, 31, 1A, E5), V(60, 33, 51, 97), V(45, 7F, 53, 62), \ V(E0, 77, 64, B1), V(84, AE, 6B, BB), V(1C, A0, 81, FE), V(94, 2B, 08, F9), \ V(58, 68, 48, 70), V(19, FD, 45, 8F), V(87, 6C, DE, 94), V(B7, F8, 7B, 52), \ V(23, D3, 73, AB), V(E2, 02, 4B, 72), V(57, 8F, 1F, E3), V(2A, AB, 55, 66), \ V(07, 28, EB, B2), V(03, C2, B5, 2F), V(9A, 7B, C5, 86), V(A5, 08, 37, D3), \ V(F2, 87, 28, 30), V(B2, A5, BF, 23), V(BA, 6A, 03, 02), V(5C, 82, 16, ED), \ V(2B, 1C, CF, 8A), V(92, B4, 79, A7), V(F0, F2, 07, F3), V(A1, E2, 69, 4E), \ V(CD, F4, DA, 65), V(D5, BE, 05, 06), V(1F, 62, 34, D1), V(8A, FE, A6, C4), \ V(9D, 53, 2E, 34), V(A0, 55, F3, A2), V(32, E1, 8A, 05), V(75, EB, F6, A4), \ V(39, EC, 83, 0B), V(AA, EF, 60, 40), V(06, 9F, 71, 5E), V(51, 10, 6E, BD), \ V(F9, 8A, 21, 3E), V(3D, 06, DD, 96), V(AE, 05, 3E, DD), V(46, BD, E6, 4D), \ V(B5, 8D, 54, 91), V(05, 5D, C4, 71), V(6F, D4, 06, 04), V(FF, 15, 50, 60), \ V(24, FB, 98, 19), V(97, E9, BD, D6), V(CC, 43, 40, 89), V(77, 9E, D9, 67), \ V(BD, 42, E8, B0), V(88, 8B, 89, 07), V(38, 5B, 19, E7), V(DB, EE, C8, 79), \ V(47, 0A, 7C, A1), V(E9, 0F, 42, 7C), V(C9, 1E, 84, F8), V(00, 00, 00, 00), \ V(83, 86, 80, 09), V(48, ED, 2B, 32), V(AC, 70, 11, 1E), V(4E, 72, 5A, 6C), \ V(FB, FF, 0E, FD), V(56, 38, 85, 0F), V(1E, D5, AE, 3D), V(27, 39, 2D, 36), \ V(64, D9, 0F, 0A), V(21, A6, 5C, 68), V(D1, 54, 5B, 9B), V(3A, 2E, 36, 24), \ V(B1, 67, 0A, 0C), V(0F, E7, 57, 93), V(D2, 96, EE, B4), V(9E, 91, 9B, 1B), \ V(4F, C5, C0, 80), V(A2, 20, DC, 61), V(69, 4B, 77, 5A), V(16, 1A, 12, 1C), \ V(0A, BA, 93, E2), V(E5, 2A, A0, C0), V(43, E0, 22, 3C), V(1D, 17, 1B, 12), \ V(0B, 0D, 09, 0E), V(AD, C7, 8B, F2), V(B9, A8, B6, 2D), V(C8, A9, 1E, 14), \ V(85, 19, F1, 57), V(4C, 07, 75, AF), V(BB, DD, 99, EE), V(FD, 60, 7F, A3), \ V(9F, 26, 01, F7), V(BC, F5, 72, 5C), V(C5, 3B, 66, 44), V(34, 7E, FB, 5B), \ V(76, 29, 43, 8B), V(DC, C6, 23, CB), V(68, FC, ED, B6), V(63, F1, E4, B8), \ V(CA, DC, 31, D7), V(10, 85, 63, 42), V(40, 22, 97, 13), V(20, 11, C6, 84), \ V(7D, 24, 4A, 85), V(F8, 3D, BB, D2), V(11, 32, F9, AE), V(6D, A1, 29, C7), \ V(4B, 2F, 9E, 1D), V(F3, 30, B2, DC), V(EC, 52, 86, 0D), V(D0, E3, C1, 77), \ V(6C, 16, B3, 2B), V(99, B9, 70, A9), V(FA, 48, 94, 11), V(22, 64, E9, 47), \ V(C4, 8C, FC, A8), V(1A, 3F, F0, A0), V(D8, 2C, 7D, 56), V(EF, 90, 33, 22), \ V(C7, 4E, 49, 87), V(C1, D1, 38, D9), V(FE, A2, CA, 8C), V(36, 0B, D4, 98), \ V(CF, 81, F5, A6), V(28, DE, 7A, A5), V(26, 8E, B7, DA), V(A4, BF, AD, 3F), \ V(E4, 9D, 3A, 2C), V(0D, 92, 78, 50), V(9B, CC, 5F, 6A), V(62, 46, 7E, 54), \ V(C2, 13, 8D, F6), V(E8, B8, D8, 90), V(5E, F7, 39, 2E), V(F5, AF, C3, 82), \ V(BE, 80, 5D, 9F), V(7C, 93, D0, 69), V(A9, 2D, D5, 6F), V(B3, 12, 25, CF), \ V(3B, 99, AC, C8), V(A7, 7D, 18, 10), V(6E, 63, 9C, E8), V(7B, BB, 3B, DB), \ V(09, 78, 26, CD), V(F4, 18, 59, 6E), V(01, B7, 9A, EC), V(A8, 9A, 4F, 83), \ V(65, 6E, 95, E6), V(7E, E6, FF, AA), V(08, CF, BC, 21), V(E6, E8, 15, EF), \ V(D9, 9B, E7, BA), V(CE, 36, 6F, 4A), V(D4, 09, 9F, EA), V(D6, 7C, B0, 29), \ V(AF, B2, A4, 31), V(31, 23, 3F, 2A), V(30, 94, A5, C6), V(C0, 66, A2, 35), \ V(37, BC, 4E, 74), V(A6, CA, 82, FC), V(B0, D0, 90, E0), V(15, D8, A7, 33), \ V(4A, 98, 04, F1), V(F7, DA, EC, 41), V(0E, 50, CD, 7F), V(2F, F6, 91, 17), \ V(8D, D6, 4D, 76), V(4D, B0, EF, 43), V(54, 4D, AA, CC), V(DF, 04, 96, E4), \ V(E3, B5, D1, 9E), V(1B, 88, 6A, 4C), V(B8, 1F, 2C, C1), V(7F, 51, 65, 46), \ V(04, EA, 5E, 9D), V(5D, 35, 8C, 01), V(73, 74, 87, FA), V(2E, 41, 0B, FB), \ V(5A, 1D, 67, B3), V(52, D2, DB, 92), V(33, 56, 10, E9), V(13, 47, D6, 6D), \ V(8C, 61, D7, 9A), V(7A, 0C, A1, 37), V(8E, 14, F8, 59), V(89, 3C, 13, EB), \ V(EE, 27, A9, CE), V(35, C9, 61, B7), V(ED, E5, 1C, E1), V(3C, B1, 47, 7A), \ V(59, DF, D2, 9C), V(3F, 73, F2, 55), V(79, CE, 14, 18), V(BF, 37, C7, 73), \ V(EA, CD, F7, 53), V(5B, AA, FD, 5F), V(14, 6F, 3D, DF), V(86, DB, 44, 78), \ V(81, F3, AF, CA), V(3E, C4, 68, B9), V(2C, 34, 24, 38), V(5F, 40, A3, C2), \ V(72, C3, 1D, 16), V(0C, 25, E2, BC), V(8B, 49, 3C, 28), V(41, 95, 0D, FF), \ V(71, 01, A8, 39), V(DE, B3, 0C, 08), V(9C, E4, B4, D8), V(90, C1, 56, 64), \ V(61, 84, CB, 7B), V(70, B6, 32, D5), V(74, 5C, 6C, 48), V(42, 57, B8, D0) #define V(a, b, c, d) 0x##a##b##c##d MBEDTLS_MAYBE_UNUSED static const uint32_t RT0[256] = { RT }; #undef V #define V(a, b, c, d) 0x##b##c##d##a MBEDTLS_MAYBE_UNUSED static const uint32_t RT1[256] = { RT }; #undef V #define V(a, b, c, d) 0x##c##d##a##b MBEDTLS_MAYBE_UNUSED static const uint32_t RT2[256] = { RT }; #undef V #define V(a, b, c, d) 0x##d##a##b##c MBEDTLS_MAYBE_UNUSED static const uint32_t RT3[256] = { RT }; #undef V #undef RT /* * Round constants */ MBEDTLS_MAYBE_UNUSED static const uint32_t round_constants[10] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x0000001B, 0x00000036 }; #else /* MBEDTLS_AES_ROM_TABLES */ /* * Forward S-box & tables */ MBEDTLS_MAYBE_UNUSED static unsigned char FSb[256]; MBEDTLS_MAYBE_UNUSED static uint32_t FT0[256]; MBEDTLS_MAYBE_UNUSED static uint32_t FT1[256]; MBEDTLS_MAYBE_UNUSED static uint32_t FT2[256]; MBEDTLS_MAYBE_UNUSED static uint32_t FT3[256]; /* * Reverse S-box & tables */ MBEDTLS_MAYBE_UNUSED static unsigned char RSb[256]; MBEDTLS_MAYBE_UNUSED static uint32_t RT0[256]; MBEDTLS_MAYBE_UNUSED static uint32_t RT1[256]; MBEDTLS_MAYBE_UNUSED static uint32_t RT2[256]; MBEDTLS_MAYBE_UNUSED static uint32_t RT3[256]; /* * Round constants */ MBEDTLS_MAYBE_UNUSED static uint32_t round_constants[10]; /* * Tables generation code */ #define ROTL8(x) (((x) << 8) & 0xFFFFFFFF) | ((x) >> 24) #define XTIME(x) (((x) << 1) ^ (((x) & 0x80) ? 0x1B : 0x00)) #define MUL(x, y) (((x) && (y)) ? pow[(log[(x)]+log[(y)]) % 255] : 0) MBEDTLS_MAYBE_UNUSED static int aes_init_done = 0; MBEDTLS_MAYBE_UNUSED static void aes_gen_tables(void) { int i; uint8_t x, y, z; uint8_t pow[256]; uint8_t log[256]; /* * compute pow and log tables over GF(2^8) */ for (i = 0, x = 1; i < 256; i++) { pow[i] = x; log[x] = (uint8_t) i; x ^= XTIME(x); } /* * calculate the round constants */ for (i = 0, x = 1; i < 10; i++) { round_constants[i] = x; x = XTIME(x); } /* * generate the forward and reverse S-boxes */ FSb[0x00] = 0x63; #if defined(MBEDTLS_AES_NEED_REVERSE_TABLES) RSb[0x63] = 0x00; #endif for (i = 1; i < 256; i++) { x = pow[255 - log[i]]; y = x; y = (y << 1) | (y >> 7); x ^= y; y = (y << 1) | (y >> 7); x ^= y; y = (y << 1) | (y >> 7); x ^= y; y = (y << 1) | (y >> 7); x ^= y ^ 0x63; FSb[i] = x; #if defined(MBEDTLS_AES_NEED_REVERSE_TABLES) RSb[x] = (unsigned char) i; #endif } /* * generate the forward and reverse tables */ for (i = 0; i < 256; i++) { x = FSb[i]; y = XTIME(x); z = y ^ x; FT0[i] = ((uint32_t) y) ^ ((uint32_t) x << 8) ^ ((uint32_t) x << 16) ^ ((uint32_t) z << 24); #if !defined(MBEDTLS_AES_FEWER_TABLES) FT1[i] = ROTL8(FT0[i]); FT2[i] = ROTL8(FT1[i]); FT3[i] = ROTL8(FT2[i]); #endif /* !MBEDTLS_AES_FEWER_TABLES */ #if defined(MBEDTLS_AES_NEED_REVERSE_TABLES) x = RSb[i]; RT0[i] = ((uint32_t) MUL(0x0E, x)) ^ ((uint32_t) MUL(0x09, x) << 8) ^ ((uint32_t) MUL(0x0D, x) << 16) ^ ((uint32_t) MUL(0x0B, x) << 24); #if !defined(MBEDTLS_AES_FEWER_TABLES) RT1[i] = ROTL8(RT0[i]); RT2[i] = ROTL8(RT1[i]); RT3[i] = ROTL8(RT2[i]); #endif /* !MBEDTLS_AES_FEWER_TABLES */ #endif /* MBEDTLS_AES_NEED_REVERSE_TABLES */ } } #undef ROTL8 #endif /* MBEDTLS_AES_ROM_TABLES */ #if defined(MBEDTLS_AES_FEWER_TABLES) #define ROTL8(x) ((uint32_t) ((x) << 8) + (uint32_t) ((x) >> 24)) #define ROTL16(x) ((uint32_t) ((x) << 16) + (uint32_t) ((x) >> 16)) #define ROTL24(x) ((uint32_t) ((x) << 24) + (uint32_t) ((x) >> 8)) #define AES_RT0(idx) RT0[idx] #define AES_RT1(idx) ROTL8(RT0[idx]) #define AES_RT2(idx) ROTL16(RT0[idx]) #define AES_RT3(idx) ROTL24(RT0[idx]) #define AES_FT0(idx) FT0[idx] #define AES_FT1(idx) ROTL8(FT0[idx]) #define AES_FT2(idx) ROTL16(FT0[idx]) #define AES_FT3(idx) ROTL24(FT0[idx]) #else /* MBEDTLS_AES_FEWER_TABLES */ #define AES_RT0(idx) RT0[idx] #define AES_RT1(idx) RT1[idx] #define AES_RT2(idx) RT2[idx] #define AES_RT3(idx) RT3[idx] #define AES_FT0(idx) FT0[idx] #define AES_FT1(idx) FT1[idx] #define AES_FT2(idx) FT2[idx] #define AES_FT3(idx) FT3[idx] #endif /* MBEDTLS_AES_FEWER_TABLES */ void mbedtls_aes_init(mbedtls_aes_context *ctx) { memset(ctx, 0, sizeof(mbedtls_aes_context)); } void mbedtls_aes_free(mbedtls_aes_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aes_context)); } #if defined(MBEDTLS_CIPHER_MODE_XTS) void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx) { mbedtls_aes_init(&ctx->crypt); mbedtls_aes_init(&ctx->tweak); } void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx) { if (ctx == NULL) { return; } mbedtls_aes_free(&ctx->crypt); mbedtls_aes_free(&ctx->tweak); } #endif /* MBEDTLS_CIPHER_MODE_XTS */ /* Some implementations need the round keys to be aligned. * Return an offset to be added to buf, such that (buf + offset) is * correctly aligned. * Note that the offset is in units of elements of buf, i.e. 32-bit words, * i.e. an offset of 1 means 4 bytes and so on. */ #if (defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)) || \ (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2) #define MAY_NEED_TO_ALIGN #endif MBEDTLS_MAYBE_UNUSED static unsigned mbedtls_aes_rk_offset(uint32_t *buf) { #if defined(MAY_NEED_TO_ALIGN) int align_16_bytes = 0; #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) if (aes_padlock_ace == -1) { aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE); } if (aes_padlock_ace) { align_16_bytes = 1; } #endif #if defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { align_16_bytes = 1; } #endif if (align_16_bytes) { /* These implementations needs 16-byte alignment * for the round key array. */ unsigned delta = ((uintptr_t) buf & 0x0000000fU) / 4; if (delta == 0) { return 0; } else { return 4 - delta; // 16 bytes = 4 uint32_t } } #else /* MAY_NEED_TO_ALIGN */ (void) buf; #endif /* MAY_NEED_TO_ALIGN */ return 0; } /* * AES key schedule (encryption) */ #if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) { uint32_t *RK; switch (keybits) { case 128: ctx->nr = 10; break; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 192: ctx->nr = 12; break; case 256: ctx->nr = 14; break; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } #if !defined(MBEDTLS_AES_ROM_TABLES) if (aes_init_done == 0) { aes_gen_tables(); aes_init_done = 1; } #endif ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf); RK = ctx->buf + ctx->rk_offset; #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { return mbedtls_aesni_setkey_enc((unsigned char *) RK, key, keybits); } #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { return mbedtls_aesce_setkey_enc((unsigned char *) RK, key, keybits); } #endif #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) for (unsigned int i = 0; i < (keybits >> 5); i++) { RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2); } switch (ctx->nr) { case 10: for (unsigned int i = 0; i < 10; i++, RK += 4) { RK[4] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[3])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[3])] << 24); RK[5] = RK[1] ^ RK[4]; RK[6] = RK[2] ^ RK[5]; RK[7] = RK[3] ^ RK[6]; } break; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 12: for (unsigned int i = 0; i < 8; i++, RK += 6) { RK[6] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[5])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[5])] << 24); RK[7] = RK[1] ^ RK[6]; RK[8] = RK[2] ^ RK[7]; RK[9] = RK[3] ^ RK[8]; RK[10] = RK[4] ^ RK[9]; RK[11] = RK[5] ^ RK[10]; } break; case 14: for (unsigned int i = 0; i < 7; i++, RK += 8) { RK[8] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[7])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[7])] << 24); RK[9] = RK[1] ^ RK[8]; RK[10] = RK[2] ^ RK[9]; RK[11] = RK[3] ^ RK[10]; RK[12] = RK[4] ^ ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[11])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[11])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[11])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[11])] << 24); RK[13] = RK[5] ^ RK[12]; RK[14] = RK[6] ^ RK[13]; RK[15] = RK[7] ^ RK[14]; } break; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ } return 0; #endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ } #endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ /* * AES key schedule (decryption) */ #if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) { #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) uint32_t *SK; #endif int ret; mbedtls_aes_context cty; uint32_t *RK; mbedtls_aes_init(&cty); ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf); RK = ctx->buf + ctx->rk_offset; /* Also checks keybits */ if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) { goto exit; } ctx->nr = cty.nr; #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { mbedtls_aesni_inverse_key((unsigned char *) RK, (const unsigned char *) (cty.buf + cty.rk_offset), ctx->nr); goto exit; } #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { mbedtls_aesce_inverse_key( (unsigned char *) RK, (const unsigned char *) (cty.buf + cty.rk_offset), ctx->nr); goto exit; } #endif #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) SK = cty.buf + cty.rk_offset + cty.nr * 4; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; SK -= 8; for (int i = ctx->nr - 1; i > 0; i--, SK -= 8) { for (int j = 0; j < 4; j++, SK++) { *RK++ = AES_RT0(FSb[MBEDTLS_BYTE_0(*SK)]) ^ AES_RT1(FSb[MBEDTLS_BYTE_1(*SK)]) ^ AES_RT2(FSb[MBEDTLS_BYTE_2(*SK)]) ^ AES_RT3(FSb[MBEDTLS_BYTE_3(*SK)]); } } *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; #endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ exit: mbedtls_aes_free(&cty); return ret; } #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_CIPHER_MODE_XTS) static int mbedtls_aes_xts_decode_keys(const unsigned char *key, unsigned int keybits, const unsigned char **key1, unsigned int *key1bits, const unsigned char **key2, unsigned int *key2bits) { const unsigned int half_keybits = keybits / 2; const unsigned int half_keybytes = half_keybits / 8; switch (keybits) { case 256: break; case 512: break; default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } *key1bits = half_keybits; *key2bits = half_keybits; *key1 = &key[0]; *key2 = &key[half_keybytes]; return 0; } int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *key1, *key2; unsigned int key1bits, key2bits; ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, &key2, &key2bits); if (ret != 0) { return ret; } /* Set the tweak key. Always set tweak key for the encryption mode. */ ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits); if (ret != 0) { return ret; } /* Set crypt key for encryption. */ return mbedtls_aes_setkey_enc(&ctx->crypt, key1, key1bits); } int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *key1, *key2; unsigned int key1bits, key2bits; ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, &key2, &key2bits); if (ret != 0) { return ret; } /* Set the tweak key. Always set tweak key for encryption. */ ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits); if (ret != 0) { return ret; } /* Set crypt key for decryption. */ return mbedtls_aes_setkey_dec(&ctx->crypt, key1, key1bits); } #endif /* MBEDTLS_CIPHER_MODE_XTS */ #define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \ do \ { \ (X0) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y0)) ^ \ AES_FT1(MBEDTLS_BYTE_1(Y1)) ^ \ AES_FT2(MBEDTLS_BYTE_2(Y2)) ^ \ AES_FT3(MBEDTLS_BYTE_3(Y3)); \ \ (X1) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y1)) ^ \ AES_FT1(MBEDTLS_BYTE_1(Y2)) ^ \ AES_FT2(MBEDTLS_BYTE_2(Y3)) ^ \ AES_FT3(MBEDTLS_BYTE_3(Y0)); \ \ (X2) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y2)) ^ \ AES_FT1(MBEDTLS_BYTE_1(Y3)) ^ \ AES_FT2(MBEDTLS_BYTE_2(Y0)) ^ \ AES_FT3(MBEDTLS_BYTE_3(Y1)); \ \ (X3) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y3)) ^ \ AES_FT1(MBEDTLS_BYTE_1(Y0)) ^ \ AES_FT2(MBEDTLS_BYTE_2(Y1)) ^ \ AES_FT3(MBEDTLS_BYTE_3(Y2)); \ } while (0) #define AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \ do \ { \ (X0) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y0)) ^ \ AES_RT1(MBEDTLS_BYTE_1(Y3)) ^ \ AES_RT2(MBEDTLS_BYTE_2(Y2)) ^ \ AES_RT3(MBEDTLS_BYTE_3(Y1)); \ \ (X1) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y1)) ^ \ AES_RT1(MBEDTLS_BYTE_1(Y0)) ^ \ AES_RT2(MBEDTLS_BYTE_2(Y3)) ^ \ AES_RT3(MBEDTLS_BYTE_3(Y2)); \ \ (X2) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y2)) ^ \ AES_RT1(MBEDTLS_BYTE_1(Y1)) ^ \ AES_RT2(MBEDTLS_BYTE_2(Y0)) ^ \ AES_RT3(MBEDTLS_BYTE_3(Y3)); \ \ (X3) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y3)) ^ \ AES_RT1(MBEDTLS_BYTE_1(Y2)) ^ \ AES_RT2(MBEDTLS_BYTE_2(Y1)) ^ \ AES_RT3(MBEDTLS_BYTE_3(Y0)); \ } while (0) /* * AES-ECB block encryption */ #if !defined(MBEDTLS_AES_ENCRYPT_ALT) int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) { int i; uint32_t *RK = ctx->buf + ctx->rk_offset; struct { uint32_t X[4]; uint32_t Y[4]; } t; t.X[0] = MBEDTLS_GET_UINT32_LE(input, 0); t.X[0] ^= *RK++; t.X[1] = MBEDTLS_GET_UINT32_LE(input, 4); t.X[1] ^= *RK++; t.X[2] = MBEDTLS_GET_UINT32_LE(input, 8); t.X[2] ^= *RK++; t.X[3] = MBEDTLS_GET_UINT32_LE(input, 12); t.X[3] ^= *RK++; for (i = (ctx->nr >> 1) - 1; i > 0; i--) { AES_FROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]); AES_FROUND(t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3]); } AES_FROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]); t.X[0] = *RK++ ^ \ ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[0])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[1])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[2])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[3])] << 24); t.X[1] = *RK++ ^ \ ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[1])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[2])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[3])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[0])] << 24); t.X[2] = *RK++ ^ \ ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[2])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[3])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[0])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[1])] << 24); t.X[3] = *RK++ ^ \ ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[3])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[0])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[1])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[2])] << 24); MBEDTLS_PUT_UINT32_LE(t.X[0], output, 0); MBEDTLS_PUT_UINT32_LE(t.X[1], output, 4); MBEDTLS_PUT_UINT32_LE(t.X[2], output, 8); MBEDTLS_PUT_UINT32_LE(t.X[3], output, 12); mbedtls_platform_zeroize(&t, sizeof(t)); return 0; } #endif /* !MBEDTLS_AES_ENCRYPT_ALT */ /* * AES-ECB block decryption */ #if !defined(MBEDTLS_AES_DECRYPT_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) { int i; uint32_t *RK = ctx->buf + ctx->rk_offset; struct { uint32_t X[4]; uint32_t Y[4]; } t; t.X[0] = MBEDTLS_GET_UINT32_LE(input, 0); t.X[0] ^= *RK++; t.X[1] = MBEDTLS_GET_UINT32_LE(input, 4); t.X[1] ^= *RK++; t.X[2] = MBEDTLS_GET_UINT32_LE(input, 8); t.X[2] ^= *RK++; t.X[3] = MBEDTLS_GET_UINT32_LE(input, 12); t.X[3] ^= *RK++; for (i = (ctx->nr >> 1) - 1; i > 0; i--) { AES_RROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]); AES_RROUND(t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3]); } AES_RROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]); t.X[0] = *RK++ ^ \ ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[0])]) ^ ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[3])] << 8) ^ ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[2])] << 16) ^ ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[1])] << 24); t.X[1] = *RK++ ^ \ ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[1])]) ^ ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[0])] << 8) ^ ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[3])] << 16) ^ ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[2])] << 24); t.X[2] = *RK++ ^ \ ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[2])]) ^ ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[1])] << 8) ^ ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[0])] << 16) ^ ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[3])] << 24); t.X[3] = *RK++ ^ \ ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[3])]) ^ ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[2])] << 8) ^ ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[1])] << 16) ^ ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[0])] << 24); MBEDTLS_PUT_UINT32_LE(t.X[0], output, 0); MBEDTLS_PUT_UINT32_LE(t.X[1], output, 4); MBEDTLS_PUT_UINT32_LE(t.X[2], output, 8); MBEDTLS_PUT_UINT32_LE(t.X[3], output, 12); mbedtls_platform_zeroize(&t, sizeof(t)); return 0; } #endif /* !MBEDTLS_AES_DECRYPT_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /* VIA Padlock and our intrinsics-based implementation of AESNI require * the round keys to be aligned on a 16-byte boundary. We take care of this * before creating them, but the AES context may have moved (this can happen * if the library is called from a language with managed memory), and in later * calls it might have a different alignment with respect to 16-byte memory. * So we may need to realign. */ MBEDTLS_MAYBE_UNUSED static void aes_maybe_realign(mbedtls_aes_context *ctx) { unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf); if (new_offset != ctx->rk_offset) { memmove(ctx->buf + new_offset, // new address ctx->buf + ctx->rk_offset, // current address (ctx->nr + 1) * 16); // number of round keys * bytes per rk ctx->rk_offset = new_offset; } } /* * AES-ECB block encryption/decryption */ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } #if defined(MAY_NEED_TO_ALIGN) aes_maybe_realign(ctx); #endif #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { return mbedtls_aesni_crypt_ecb(ctx, mode, input, output); } #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { return mbedtls_aesce_crypt_ecb(ctx, mode, input, output); } #endif #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) if (aes_padlock_ace > 0) { return mbedtls_padlock_xcryptecb(ctx, mode, input, output); } #endif #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { return mbedtls_internal_aes_decrypt(ctx, input, output); } else #endif { return mbedtls_internal_aes_encrypt(ctx, input, output); } #endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * AES-CBC buffer encryption/decryption */ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char temp[16]; if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } /* Nothing to do if length is zero. */ if (length == 0) { return 0; } if (length % 16) { return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; } #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) if (aes_padlock_ace > 0) { if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) { return 0; } // If padlock data misaligned, we just fall back to // unaccelerated mode // } #endif const unsigned char *ivp = iv; if (mode == MBEDTLS_AES_DECRYPT) { while (length > 0) { memcpy(temp, input, 16); ret = mbedtls_aes_crypt_ecb(ctx, mode, input, output); if (ret != 0) { goto exit; } /* Avoid using the NEON implementation of mbedtls_xor. Because of the dependency on * the result for the next block in CBC, and the cost of transferring that data from * NEON registers, NEON is slower on aarch64. */ mbedtls_xor_no_simd(output, output, iv, 16); memcpy(iv, temp, 16); input += 16; output += 16; length -= 16; } } else { while (length > 0) { mbedtls_xor_no_simd(output, input, ivp, 16); ret = mbedtls_aes_crypt_ecb(ctx, mode, output, output); if (ret != 0) { goto exit; } ivp = output; input += 16; output += 16; length -= 16; } memcpy(iv, ivp, 16); } ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_XTS) typedef unsigned char mbedtls_be128[16]; /* * GF(2^128) multiplication function * * This function multiplies a field element by x in the polynomial field * representation. It uses 64-bit word operations to gain speed but compensates * for machine endianness and hence works correctly on both big and little * endian machines. */ #if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C) MBEDTLS_OPTIMIZE_FOR_PERFORMANCE #endif static inline void mbedtls_gf128mul_x_ble(unsigned char r[16], const unsigned char x[16]) { uint64_t a, b, ra, rb; a = MBEDTLS_GET_UINT64_LE(x, 0); b = MBEDTLS_GET_UINT64_LE(x, 8); ra = (a << 1) ^ 0x0087 >> (8 - ((b >> 63) << 3)); rb = (a >> 63) | (b << 1); MBEDTLS_PUT_UINT64_LE(ra, r, 0); MBEDTLS_PUT_UINT64_LE(rb, r, 8); } /* * AES-XTS buffer encryption/decryption * * Use of MBEDTLS_OPTIMIZE_FOR_PERFORMANCE here and for mbedtls_gf128mul_x_ble() * is a 3x performance improvement for gcc -Os, if we have hardware AES support. */ #if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C) MBEDTLS_OPTIMIZE_FOR_PERFORMANCE #endif int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t blocks = length / 16; size_t leftover = length % 16; unsigned char tweak[16]; unsigned char prev_tweak[16]; unsigned char tmp[16]; if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } /* Data units must be at least 16 bytes long. */ if (length < 16) { return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; } /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ if (length > (1 << 20) * 16) { return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; } /* Compute the tweak. */ ret = mbedtls_aes_crypt_ecb(&ctx->tweak, MBEDTLS_AES_ENCRYPT, data_unit, tweak); if (ret != 0) { return ret; } while (blocks--) { if (MBEDTLS_UNLIKELY(leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0)) { /* We are on the last block in a decrypt operation that has * leftover bytes, so we need to use the next tweak for this block, * and this tweak for the leftover bytes. Save the current tweak for * the leftovers and then update the current tweak for use on this, * the last full block. */ memcpy(prev_tweak, tweak, sizeof(tweak)); mbedtls_gf128mul_x_ble(tweak, tweak); } mbedtls_xor(tmp, input, tweak, 16); ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); if (ret != 0) { return ret; } mbedtls_xor(output, tmp, tweak, 16); /* Update the tweak for the next block. */ mbedtls_gf128mul_x_ble(tweak, tweak); output += 16; input += 16; } if (leftover) { /* If we are on the leftover bytes in a decrypt operation, we need to * use the previous tweak for these bytes (as saved in prev_tweak). */ unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; /* We are now on the final part of the data unit, which doesn't divide * evenly by 16. It's time for ciphertext stealing. */ size_t i; unsigned char *prev_output = output - 16; /* Copy ciphertext bytes from the previous block to our output for each * byte of ciphertext we won't steal. */ for (i = 0; i < leftover; i++) { output[i] = prev_output[i]; } /* Copy the remainder of the input for this final round. */ mbedtls_xor(tmp, input, t, leftover); /* Copy ciphertext bytes from the previous block for input in this * round. */ mbedtls_xor(tmp + i, prev_output + i, t + i, 16 - i); ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); if (ret != 0) { return ret; } /* Write the result back to the previous block, overriding the previous * output we copied. */ mbedtls_xor(prev_output, tmp, t, 16); } return 0; } #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * AES-CFB128 buffer encryption/decryption */ int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } n = *iv_off; if (n > 15) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } if (mode == MBEDTLS_AES_DECRYPT) { while (length--) { if (n == 0) { ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); if (ret != 0) { goto exit; } } c = *input++; *output++ = (unsigned char) (c ^ iv[n]); iv[n] = (unsigned char) c; n = (n + 1) & 0x0F; } } else { while (length--) { if (n == 0) { ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); if (ret != 0) { goto exit; } } iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++); n = (n + 1) & 0x0F; } } *iv_off = n; ret = 0; exit: return ret; } /* * AES-CFB8 buffer encryption/decryption */ int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char c; unsigned char ov[17]; if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } while (length--) { memcpy(ov, iv, 16); ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); if (ret != 0) { goto exit; } if (mode == MBEDTLS_AES_DECRYPT) { ov[16] = *input; } c = *output++ = (unsigned char) (iv[0] ^ *input++); if (mode == MBEDTLS_AES_ENCRYPT) { ov[16] = c; } memcpy(iv, ov + 1, 16); } ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) /* * AES-OFB (Output Feedback Mode) buffer encryption/decryption */ int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int ret = 0; size_t n; n = *iv_off; if (n > 15) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } while (length--) { if (n == 0) { ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); if (ret != 0) { goto exit; } } *output++ = *input++ ^ iv[n]; n = (n + 1) & 0x0F; } *iv_off = n; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * AES-CTR buffer encryption/decryption */ int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t offset = *nc_off; if (offset > 0x0F) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } for (size_t i = 0; i < length;) { size_t n = 16; if (offset == 0) { ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block); if (ret != 0) { goto exit; } mbedtls_ctr_increment_counter(nonce_counter); } else { n -= offset; } if (n > (length - i)) { n = (length - i); } mbedtls_xor(&output[i], &input[i], &stream_block[offset], n); // offset might be non-zero for the last block, but in that case, we don't use it again offset = 0; i += n; } // capture offset for future resumption *nc_off = (*nc_off + length) % 16; ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* !MBEDTLS_AES_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * AES test vectors from: * * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static const unsigned char aes_test_ecb_dec[][16] = { { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } #endif }; #endif static const unsigned char aes_test_ecb_enc[][16] = { { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } #endif }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const unsigned char aes_test_cbc_dec[][16] = { { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } #endif }; static const unsigned char aes_test_cbc_enc[][16] = { { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } #endif }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * AES-CFB128 test vectors from: * * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */ static const unsigned char aes_test_cfb128_key[][32] = { { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } #endif }; static const unsigned char aes_test_cfb128_iv[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; static const unsigned char aes_test_cfb128_pt[64] = { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }; static const unsigned char aes_test_cfb128_ct[][64] = { { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } #endif }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) /* * AES-OFB test vectors from: * * https://csrc.nist.gov/publications/detail/sp/800-38a/final */ static const unsigned char aes_test_ofb_key[][32] = { { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } #endif }; static const unsigned char aes_test_ofb_iv[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; static const unsigned char aes_test_ofb_pt[64] = { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }; static const unsigned char aes_test_ofb_ct[][64] = { { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } #endif }; #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * AES-CTR test vectors from: * * http://www.faqs.org/rfcs/rfc3686.html */ static const unsigned char aes_test_ctr_key[][16] = { { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } }; static const unsigned char aes_test_ctr_nonce_counter[][16] = { { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } }; static const unsigned char aes_test_ctr_pt[][48] = { { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23 } }; static const unsigned char aes_test_ctr_ct[][48] = { { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, 0x25, 0xB2, 0x07, 0x2F } }; static const int aes_test_ctr_len[3] = { 16, 32, 36 }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) /* * AES-XTS test vectors from: * * IEEE P1619/D16 Annex B * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) */ static const unsigned char aes_test_xts_key[][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, }; static const unsigned char aes_test_xts_pt32[][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, }; static const unsigned char aes_test_xts_ct32[][32] = { { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, }; static const unsigned char aes_test_xts_data_unit[][16] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; #endif /* MBEDTLS_CIPHER_MODE_XTS */ /* * Checkup routine */ int mbedtls_aes_self_test(int verbose) { int ret = 0, i, j, u, mode; unsigned int keybits; unsigned char key[32]; unsigned char buf[64]; const unsigned char *aes_tests; #if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ defined(MBEDTLS_CIPHER_MODE_OFB) unsigned char iv[16]; #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char prv[16]; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ defined(MBEDTLS_CIPHER_MODE_OFB) size_t offset; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) int len; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) unsigned char nonce_counter[16]; unsigned char stream_block[16]; #endif mbedtls_aes_context ctx; memset(key, 0, 32); mbedtls_aes_init(&ctx); if (verbose != 0) { #if defined(MBEDTLS_AES_ALT) mbedtls_printf(" AES note: alternative implementation.\n"); #else /* MBEDTLS_AES_ALT */ #if defined(MBEDTLS_AESNI_HAVE_CODE) #if MBEDTLS_AESNI_HAVE_CODE == 1 mbedtls_printf(" AES note: AESNI code present (assembly implementation).\n"); #elif MBEDTLS_AESNI_HAVE_CODE == 2 mbedtls_printf(" AES note: AESNI code present (intrinsics implementation).\n"); #else #error "Unrecognised value for MBEDTLS_AESNI_HAVE_CODE" #endif if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { mbedtls_printf(" AES note: using AESNI.\n"); } else #endif #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) { mbedtls_printf(" AES note: using VIA Padlock.\n"); } else #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { mbedtls_printf(" AES note: using AESCE.\n"); } else #endif { #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) mbedtls_printf(" AES note: built-in implementation.\n"); #endif } #endif /* MBEDTLS_AES_ALT */ } /* * ECB mode */ { static const int num_tests = sizeof(aes_test_ecb_enc) / sizeof(*aes_test_ecb_enc); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; keybits = 128 + u * 64; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-ECB-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { if (verbose != 0) { mbedtls_printf("skipped\n"); } continue; } #endif memset(buf, 0, 16); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); aes_tests = aes_test_ecb_dec[u]; } else #endif { ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); aes_tests = aes_test_ecb_enc[u]; } /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { mbedtls_printf("skipped\n"); continue; } else if (ret != 0) { goto exit; } for (j = 0; j < 10000; j++) { ret = mbedtls_aes_crypt_ecb(&ctx, mode, buf, buf); if (ret != 0) { goto exit; } } if (memcmp(buf, aes_tests, 16) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * CBC mode */ { static const int num_tests = sizeof(aes_test_cbc_dec) / sizeof(*aes_test_cbc_dec); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; keybits = 128 + u * 64; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-CBC-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memset(iv, 0, 16); memset(prv, 0, 16); memset(buf, 0, 16); if (mode == MBEDTLS_AES_DECRYPT) { ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); aes_tests = aes_test_cbc_dec[u]; } else { ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); aes_tests = aes_test_cbc_enc[u]; } /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { mbedtls_printf("skipped\n"); continue; } else if (ret != 0) { goto exit; } for (j = 0; j < 10000; j++) { if (mode == MBEDTLS_AES_ENCRYPT) { unsigned char tmp[16]; memcpy(tmp, prv, 16); memcpy(prv, buf, 16); memcpy(buf, tmp, 16); } ret = mbedtls_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf); if (ret != 0) { goto exit; } } if (memcmp(buf, aes_tests, 16) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * CFB128 mode */ { static const int num_tests = sizeof(aes_test_cfb128_key) / sizeof(*aes_test_cfb128_key); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; keybits = 128 + u * 64; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-CFB128-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memcpy(iv, aes_test_cfb128_iv, 16); memcpy(key, aes_test_cfb128_key[u], keybits / 8); offset = 0; ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { mbedtls_printf("skipped\n"); continue; } else if (ret != 0) { goto exit; } if (mode == MBEDTLS_AES_DECRYPT) { memcpy(buf, aes_test_cfb128_ct[u], 64); aes_tests = aes_test_cfb128_pt; } else { memcpy(buf, aes_test_cfb128_pt, 64); aes_tests = aes_test_cfb128_ct[u]; } ret = mbedtls_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf); if (ret != 0) { goto exit; } if (memcmp(buf, aes_tests, 64) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) /* * OFB mode */ { static const int num_tests = sizeof(aes_test_ofb_key) / sizeof(*aes_test_ofb_key); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; keybits = 128 + u * 64; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-OFB-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memcpy(iv, aes_test_ofb_iv, 16); memcpy(key, aes_test_ofb_key[u], keybits / 8); offset = 0; ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { mbedtls_printf("skipped\n"); continue; } else if (ret != 0) { goto exit; } if (mode == MBEDTLS_AES_DECRYPT) { memcpy(buf, aes_test_ofb_ct[u], 64); aes_tests = aes_test_ofb_pt; } else { memcpy(buf, aes_test_ofb_pt, 64); aes_tests = aes_test_ofb_ct[u]; } ret = mbedtls_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf); if (ret != 0) { goto exit; } if (memcmp(buf, aes_tests, 64) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } } #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * CTR mode */ { static const int num_tests = sizeof(aes_test_ctr_key) / sizeof(*aes_test_ctr_key); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-CTR-128 (%s): ", (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16); memcpy(key, aes_test_ctr_key[u], 16); offset = 0; if ((ret = mbedtls_aes_setkey_enc(&ctx, key, 128)) != 0) { goto exit; } len = aes_test_ctr_len[u]; if (mode == MBEDTLS_AES_DECRYPT) { memcpy(buf, aes_test_ctr_ct[u], len); aes_tests = aes_test_ctr_pt[u]; } else { memcpy(buf, aes_test_ctr_pt[u], len); aes_tests = aes_test_ctr_ct[u]; } ret = mbedtls_aes_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block, buf, buf); if (ret != 0) { goto exit; } if (memcmp(buf, aes_tests, len) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } } if (verbose != 0) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) /* * XTS mode */ { static const int num_tests = sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); mbedtls_aes_xts_context ctx_xts; mbedtls_aes_xts_init(&ctx_xts); for (i = 0; i < num_tests << 1; i++) { const unsigned char *data_unit; u = i >> 1; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-XTS-128 (%s): ", (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memset(key, 0, sizeof(key)); memcpy(key, aes_test_xts_key[u], 32); data_unit = aes_test_xts_data_unit[u]; len = sizeof(*aes_test_xts_ct32); if (mode == MBEDTLS_AES_DECRYPT) { ret = mbedtls_aes_xts_setkey_dec(&ctx_xts, key, 256); if (ret != 0) { goto exit; } memcpy(buf, aes_test_xts_ct32[u], len); aes_tests = aes_test_xts_pt32[u]; } else { ret = mbedtls_aes_xts_setkey_enc(&ctx_xts, key, 256); if (ret != 0) { goto exit; } memcpy(buf, aes_test_xts_pt32[u], len); aes_tests = aes_test_xts_ct32[u]; } ret = mbedtls_aes_crypt_xts(&ctx_xts, mode, len, data_unit, buf, buf); if (ret != 0) { goto exit; } if (memcmp(buf, aes_tests, len) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } mbedtls_aes_xts_free(&ctx_xts); } #endif /* MBEDTLS_CIPHER_MODE_XTS */ ret = 0; exit: if (ret != 0 && verbose != 0) { mbedtls_printf("failed\n"); } mbedtls_aes_free(&ctx); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_AES_C */ webfakes/src/mbedtls/library/chacha20.c0000644000176200001440000004101014740737024017447 0ustar liggesusers/** * \file chacha20.c * * \brief ChaCha20 cipher. * * \author Daniel King * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_CHACHA20_C) #include "mbedtls/chacha20.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_CHACHA20_ALT) #define ROTL32(value, amount) \ ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount)))) #define CHACHA20_CTR_INDEX (12U) #define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U) /** * \brief ChaCha20 quarter round operation. * * The quarter round is defined as follows (from RFC 7539): * 1. a += b; d ^= a; d <<<= 16; * 2. c += d; b ^= c; b <<<= 12; * 3. a += b; d ^= a; d <<<= 8; * 4. c += d; b ^= c; b <<<= 7; * * \param state ChaCha20 state to modify. * \param a The index of 'a' in the state. * \param b The index of 'b' in the state. * \param c The index of 'c' in the state. * \param d The index of 'd' in the state. */ static inline void chacha20_quarter_round(uint32_t state[16], size_t a, size_t b, size_t c, size_t d) { /* a += b; d ^= a; d <<<= 16; */ state[a] += state[b]; state[d] ^= state[a]; state[d] = ROTL32(state[d], 16); /* c += d; b ^= c; b <<<= 12 */ state[c] += state[d]; state[b] ^= state[c]; state[b] = ROTL32(state[b], 12); /* a += b; d ^= a; d <<<= 8; */ state[a] += state[b]; state[d] ^= state[a]; state[d] = ROTL32(state[d], 8); /* c += d; b ^= c; b <<<= 7; */ state[c] += state[d]; state[b] ^= state[c]; state[b] = ROTL32(state[b], 7); } /** * \brief Perform the ChaCha20 inner block operation. * * This function performs two rounds: the column round and the * diagonal round. * * \param state The ChaCha20 state to update. */ static void chacha20_inner_block(uint32_t state[16]) { chacha20_quarter_round(state, 0, 4, 8, 12); chacha20_quarter_round(state, 1, 5, 9, 13); chacha20_quarter_round(state, 2, 6, 10, 14); chacha20_quarter_round(state, 3, 7, 11, 15); chacha20_quarter_round(state, 0, 5, 10, 15); chacha20_quarter_round(state, 1, 6, 11, 12); chacha20_quarter_round(state, 2, 7, 8, 13); chacha20_quarter_round(state, 3, 4, 9, 14); } /** * \brief Generates a keystream block. * * \param initial_state The initial ChaCha20 state (key, nonce, counter). * \param keystream Generated keystream bytes are written to this buffer. */ static void chacha20_block(const uint32_t initial_state[16], unsigned char keystream[64]) { uint32_t working_state[16]; size_t i; memcpy(working_state, initial_state, CHACHA20_BLOCK_SIZE_BYTES); for (i = 0U; i < 10U; i++) { chacha20_inner_block(working_state); } working_state[0] += initial_state[0]; working_state[1] += initial_state[1]; working_state[2] += initial_state[2]; working_state[3] += initial_state[3]; working_state[4] += initial_state[4]; working_state[5] += initial_state[5]; working_state[6] += initial_state[6]; working_state[7] += initial_state[7]; working_state[8] += initial_state[8]; working_state[9] += initial_state[9]; working_state[10] += initial_state[10]; working_state[11] += initial_state[11]; working_state[12] += initial_state[12]; working_state[13] += initial_state[13]; working_state[14] += initial_state[14]; working_state[15] += initial_state[15]; for (i = 0U; i < 16; i++) { size_t offset = i * 4U; MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset); } mbedtls_platform_zeroize(working_state, sizeof(working_state)); } void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx) { mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state)); mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8)); /* Initially, there's no keystream bytes available */ ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; } void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx) { if (ctx != NULL) { mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context)); } } int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx, const unsigned char key[32]) { /* ChaCha20 constants - the string "expand 32-byte k" */ ctx->state[0] = 0x61707865; ctx->state[1] = 0x3320646e; ctx->state[2] = 0x79622d32; ctx->state[3] = 0x6b206574; /* Set key */ ctx->state[4] = MBEDTLS_GET_UINT32_LE(key, 0); ctx->state[5] = MBEDTLS_GET_UINT32_LE(key, 4); ctx->state[6] = MBEDTLS_GET_UINT32_LE(key, 8); ctx->state[7] = MBEDTLS_GET_UINT32_LE(key, 12); ctx->state[8] = MBEDTLS_GET_UINT32_LE(key, 16); ctx->state[9] = MBEDTLS_GET_UINT32_LE(key, 20); ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24); ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28); return 0; } int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx, const unsigned char nonce[12], uint32_t counter) { /* Counter */ ctx->state[12] = counter; /* Nonce */ ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0); ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4); ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8); mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8)); /* Initially, there's no keystream bytes available */ ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; return 0; } int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx, size_t size, const unsigned char *input, unsigned char *output) { size_t offset = 0U; /* Use leftover keystream bytes, if available */ while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) { output[offset] = input[offset] ^ ctx->keystream8[ctx->keystream_bytes_used]; ctx->keystream_bytes_used++; offset++; size--; } /* Process full blocks */ while (size >= CHACHA20_BLOCK_SIZE_BYTES) { /* Generate new keystream block and increment counter */ chacha20_block(ctx->state, ctx->keystream8); ctx->state[CHACHA20_CTR_INDEX]++; mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U); offset += CHACHA20_BLOCK_SIZE_BYTES; size -= CHACHA20_BLOCK_SIZE_BYTES; } /* Last (partial) block */ if (size > 0U) { /* Generate new keystream block and increment counter */ chacha20_block(ctx->state, ctx->keystream8); ctx->state[CHACHA20_CTR_INDEX]++; mbedtls_xor(output + offset, input + offset, ctx->keystream8, size); ctx->keystream_bytes_used = size; } return 0; } int mbedtls_chacha20_crypt(const unsigned char key[32], const unsigned char nonce[12], uint32_t counter, size_t data_len, const unsigned char *input, unsigned char *output) { mbedtls_chacha20_context ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_chacha20_init(&ctx); ret = mbedtls_chacha20_setkey(&ctx, key); if (ret != 0) { goto cleanup; } ret = mbedtls_chacha20_starts(&ctx, nonce, counter); if (ret != 0) { goto cleanup; } ret = mbedtls_chacha20_update(&ctx, data_len, input, output); cleanup: mbedtls_chacha20_free(&ctx); return ret; } #endif /* !MBEDTLS_CHACHA20_ALT */ #if defined(MBEDTLS_SELF_TEST) static const unsigned char test_keys[2][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }; static const unsigned char test_nonces[2][12] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } }; static const uint32_t test_counters[2] = { 0U, 1U }; static const unsigned char test_input[2][375] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f } }; static const unsigned char test_output[2][375] = { { 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 }, { 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 } }; static const size_t test_lengths[2] = { 64U, 375U }; /* Make sure no other definition is already present. */ #undef ASSERT #define ASSERT(cond, args) \ do \ { \ if (!(cond)) \ { \ if (verbose != 0) \ mbedtls_printf args; \ \ return -1; \ } \ } \ while (0) int mbedtls_chacha20_self_test(int verbose) { unsigned char output[381]; unsigned i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; for (i = 0U; i < 2U; i++) { if (verbose != 0) { mbedtls_printf(" ChaCha20 test %u ", i); } ret = mbedtls_chacha20_crypt(test_keys[i], test_nonces[i], test_counters[i], test_lengths[i], test_input[i], output); ASSERT(0 == ret, ("error code: %i\n", ret)); ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]), ("failed (output)\n")); if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* !MBEDTLS_CHACHA20_C */ webfakes/src/mbedtls/library/alignment.h0000644000176200001440000006424514740737024020100 0ustar liggesusers/** * \file alignment.h * * \brief Utility code for dealing with unaligned memory accesses */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_LIBRARY_ALIGNMENT_H #define MBEDTLS_LIBRARY_ALIGNMENT_H #include #include #include /* * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory * accesses are known to be efficient. * * All functions defined here will behave correctly regardless, but might be less * efficient when this is not defined. */ #if defined(__ARM_FEATURE_UNALIGNED) \ || defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \ || defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) /* * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9 * (and later versions) for Arm v7 and later; all x86 platforms should have * efficient unaligned access. * * https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment * specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached * device memory). */ #define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS #endif #if defined(__IAR_SYSTEMS_ICC__) && \ (defined(MBEDTLS_ARCH_IS_ARM64) || defined(MBEDTLS_ARCH_IS_ARM32) \ || defined(__ICCRX__) || defined(__ICCRL78__) || defined(__ICCRISCV__)) #pragma language=save #pragma language=extended #define MBEDTLS_POP_IAR_LANGUAGE_PRAGMA /* IAR recommend this technique for accessing unaligned data in * https://www.iar.com/knowledge/support/technical-notes/compiler/accessing-unaligned-data * This results in a single load / store instruction (if unaligned access is supported). * According to that document, this is only supported on certain architectures. */ #define UINT_UNALIGNED typedef uint16_t __packed mbedtls_uint16_unaligned_t; typedef uint32_t __packed mbedtls_uint32_unaligned_t; typedef uint64_t __packed mbedtls_uint64_unaligned_t; #elif defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 40504) && \ ((MBEDTLS_GCC_VERSION < 60300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS))) /* * gcc may generate a branch to memcpy for calls like `memcpy(dest, src, 4)` rather than * generating some LDR or LDRB instructions (similar for stores). * * This is architecture dependent: x86-64 seems fine even with old gcc; 32-bit Arm * is affected. To keep it simple, we enable for all architectures. * * For versions of gcc < 5.4.0 this issue always happens. * For gcc < 6.3.0, this issue happens at -O0 * For all versions, this issue happens iff unaligned access is not supported. * * For gcc 4.x, this implementation will generate byte-by-byte loads even if unaligned access is * supported, which is correct but not optimal. * * For performance (and code size, in some cases), we want to avoid the branch and just generate * some inline load/store instructions since the access is small and constant-size. * * The manual states: * "The packed attribute specifies that a variable or structure field should have the smallest * possible alignment—one byte for a variable" * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Variable-Attributes.html * * Previous implementations used __attribute__((__aligned__(1)), but had issues with a gcc bug: * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662 * * Tested with several versions of GCC from 4.5.0 up to 13.2.0 * We don't enable for older than 4.5.0 as this has not been tested. */ #define UINT_UNALIGNED_STRUCT typedef struct { uint16_t x; } __attribute__((packed)) mbedtls_uint16_unaligned_t; typedef struct { uint32_t x; } __attribute__((packed)) mbedtls_uint32_unaligned_t; typedef struct { uint64_t x; } __attribute__((packed)) mbedtls_uint64_unaligned_t; #endif /* * We try to force mbedtls_(get|put)_unaligned_uintXX to be always inline, because this results * in code that is both smaller and faster. IAR and gcc both benefit from this when optimising * for size. */ /** * Read the unsigned 16 bits integer from the given address, which need not * be aligned. * * \param p pointer to 2 bytes of data * \return Data at the given address */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline uint16_t mbedtls_get_unaligned_uint16(const void *p) { uint16_t r; #if defined(UINT_UNALIGNED) mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; r = *p16; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; r = p16->x; #else memcpy(&r, p, sizeof(r)); #endif return r; } /** * Write the unsigned 16 bits integer to the given address, which need not * be aligned. * * \param p pointer to 2 bytes of data * \param x data to write */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x) { #if defined(UINT_UNALIGNED) mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; *p16 = x; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; p16->x = x; #else memcpy(p, &x, sizeof(x)); #endif } /** * Read the unsigned 32 bits integer from the given address, which need not * be aligned. * * \param p pointer to 4 bytes of data * \return Data at the given address */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline uint32_t mbedtls_get_unaligned_uint32(const void *p) { uint32_t r; #if defined(UINT_UNALIGNED) mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; r = *p32; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; r = p32->x; #else memcpy(&r, p, sizeof(r)); #endif return r; } /** * Write the unsigned 32 bits integer to the given address, which need not * be aligned. * * \param p pointer to 4 bytes of data * \param x data to write */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x) { #if defined(UINT_UNALIGNED) mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; *p32 = x; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; p32->x = x; #else memcpy(p, &x, sizeof(x)); #endif } /** * Read the unsigned 64 bits integer from the given address, which need not * be aligned. * * \param p pointer to 8 bytes of data * \return Data at the given address */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline uint64_t mbedtls_get_unaligned_uint64(const void *p) { uint64_t r; #if defined(UINT_UNALIGNED) mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; r = *p64; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; r = p64->x; #else memcpy(&r, p, sizeof(r)); #endif return r; } /** * Write the unsigned 64 bits integer to the given address, which need not * be aligned. * * \param p pointer to 8 bytes of data * \param x data to write */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x) { #if defined(UINT_UNALIGNED) mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; *p64 = x; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; p64->x = x; #else memcpy(p, &x, sizeof(x)); #endif } #if defined(MBEDTLS_POP_IAR_LANGUAGE_PRAGMA) #pragma language=restore #endif /** Byte Reading Macros * * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th * byte from x, where byte 0 is the least significant byte. */ #define MBEDTLS_BYTE_0(x) ((uint8_t) ((x) & 0xff)) #define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff)) #define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff)) #define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff)) #define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff)) #define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff)) #define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff)) #define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff)) /* * Detect GCC built-in byteswap routines */ #if defined(__GNUC__) && defined(__GNUC_PREREQ) #if __GNUC_PREREQ(4, 8) #define MBEDTLS_BSWAP16 __builtin_bswap16 #endif /* __GNUC_PREREQ(4,8) */ #if __GNUC_PREREQ(4, 3) #define MBEDTLS_BSWAP32 __builtin_bswap32 #define MBEDTLS_BSWAP64 __builtin_bswap64 #endif /* __GNUC_PREREQ(4,3) */ #endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */ /* * Detect Clang built-in byteswap routines */ #if defined(__clang__) && defined(__has_builtin) #if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16) #define MBEDTLS_BSWAP16 __builtin_bswap16 #endif /* __has_builtin(__builtin_bswap16) */ #if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32) #define MBEDTLS_BSWAP32 __builtin_bswap32 #endif /* __has_builtin(__builtin_bswap32) */ #if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64) #define MBEDTLS_BSWAP64 __builtin_bswap64 #endif /* __has_builtin(__builtin_bswap64) */ #endif /* defined(__clang__) && defined(__has_builtin) */ /* * Detect MSVC built-in byteswap routines */ #if defined(_MSC_VER) #if !defined(MBEDTLS_BSWAP16) #define MBEDTLS_BSWAP16 _byteswap_ushort #endif #if !defined(MBEDTLS_BSWAP32) #define MBEDTLS_BSWAP32 _byteswap_ulong #endif #if !defined(MBEDTLS_BSWAP64) #define MBEDTLS_BSWAP64 _byteswap_uint64 #endif #endif /* defined(_MSC_VER) */ /* Detect armcc built-in byteswap routine */ #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32) #if defined(__ARM_ACLE) /* ARM Compiler 6 - earlier versions don't need a header */ #include #endif #define MBEDTLS_BSWAP32 __rev #endif /* Detect IAR built-in byteswap routine */ #if defined(__IAR_SYSTEMS_ICC__) #if defined(__ARM_ACLE) #include #define MBEDTLS_BSWAP16(x) ((uint16_t) __rev16((uint32_t) (x))) #define MBEDTLS_BSWAP32 __rev #define MBEDTLS_BSWAP64 __revll #endif #endif /* * Where compiler built-ins are not present, fall back to C code that the * compiler may be able to detect and transform into the relevant bswap or * similar instruction. */ #if !defined(MBEDTLS_BSWAP16) static inline uint16_t mbedtls_bswap16(uint16_t x) { return (x & 0x00ff) << 8 | (x & 0xff00) >> 8; } #define MBEDTLS_BSWAP16 mbedtls_bswap16 #endif /* !defined(MBEDTLS_BSWAP16) */ #if !defined(MBEDTLS_BSWAP32) static inline uint32_t mbedtls_bswap32(uint32_t x) { return (x & 0x000000ff) << 24 | (x & 0x0000ff00) << 8 | (x & 0x00ff0000) >> 8 | (x & 0xff000000) >> 24; } #define MBEDTLS_BSWAP32 mbedtls_bswap32 #endif /* !defined(MBEDTLS_BSWAP32) */ #if !defined(MBEDTLS_BSWAP64) static inline uint64_t mbedtls_bswap64(uint64_t x) { return (x & 0x00000000000000ffULL) << 56 | (x & 0x000000000000ff00ULL) << 40 | (x & 0x0000000000ff0000ULL) << 24 | (x & 0x00000000ff000000ULL) << 8 | (x & 0x000000ff00000000ULL) >> 8 | (x & 0x0000ff0000000000ULL) >> 24 | (x & 0x00ff000000000000ULL) >> 40 | (x & 0xff00000000000000ULL) >> 56; } #define MBEDTLS_BSWAP64 mbedtls_bswap64 #endif /* !defined(MBEDTLS_BSWAP64) */ #if !defined(__BYTE_ORDER__) #if defined(__LITTLE_ENDIAN__) /* IAR defines __xxx_ENDIAN__, but not __BYTE_ORDER__ */ #define MBEDTLS_IS_BIG_ENDIAN 0 #elif defined(__BIG_ENDIAN__) #define MBEDTLS_IS_BIG_ENDIAN 1 #else static const uint16_t mbedtls_byte_order_detector = { 0x100 }; #define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01) #endif #else #if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__) #define MBEDTLS_IS_BIG_ENDIAN 1 #else #define MBEDTLS_IS_BIG_ENDIAN 0 #endif #endif /* !defined(__BYTE_ORDER__) */ /** * Get the unsigned 32 bits integer corresponding to four bytes in * big-endian order (MSB first). * * \param data Base address of the memory to get the four bytes from. * \param offset Offset from \p data of the first and most significant * byte of the four bytes to build the 32 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT32_BE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? mbedtls_get_unaligned_uint32((data) + (offset)) \ : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ ) /** * Put in memory a 32 bits unsigned integer in big-endian order. * * \param n 32 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 32 * bits unsigned integer in. * \param offset Offset from \p data where to put the most significant * byte of the 32 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT32_BE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \ } \ else \ { \ mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ } \ } /** * Get the unsigned 32 bits integer corresponding to four bytes in * little-endian order (LSB first). * * \param data Base address of the memory to get the four bytes from. * \param offset Offset from \p data of the first and least significant * byte of the four bytes to build the 32 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT32_LE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ : mbedtls_get_unaligned_uint32((data) + (offset)) \ ) /** * Put in memory a 32 bits unsigned integer in little-endian order. * * \param n 32 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 32 * bits unsigned integer in. * \param offset Offset from \p data where to put the least significant * byte of the 32 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT32_LE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ } \ else \ { \ mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \ } \ } /** * Get the unsigned 16 bits integer corresponding to two bytes in * little-endian order (LSB first). * * \param data Base address of the memory to get the two bytes from. * \param offset Offset from \p data of the first and least significant * byte of the two bytes to build the 16 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT16_LE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ : mbedtls_get_unaligned_uint16((data) + (offset)) \ ) /** * Put in memory a 16 bits unsigned integer in little-endian order. * * \param n 16 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 16 * bits unsigned integer in. * \param offset Offset from \p data where to put the least significant * byte of the 16 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT16_LE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ } \ else \ { \ mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ } \ } /** * Get the unsigned 16 bits integer corresponding to two bytes in * big-endian order (MSB first). * * \param data Base address of the memory to get the two bytes from. * \param offset Offset from \p data of the first and most significant * byte of the two bytes to build the 16 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT16_BE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? mbedtls_get_unaligned_uint16((data) + (offset)) \ : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ ) /** * Put in memory a 16 bits unsigned integer in big-endian order. * * \param n 16 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 16 * bits unsigned integer in. * \param offset Offset from \p data where to put the most significant * byte of the 16 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT16_BE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ } \ else \ { \ mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ } \ } /** * Get the unsigned 24 bits integer corresponding to three bytes in * big-endian order (MSB first). * * \param data Base address of the memory to get the three bytes from. * \param offset Offset from \p data of the first and most significant * byte of the three bytes to build the 24 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT24_BE(data, offset) \ ( \ ((uint32_t) (data)[(offset)] << 16) \ | ((uint32_t) (data)[(offset) + 1] << 8) \ | ((uint32_t) (data)[(offset) + 2]) \ ) /** * Put in memory a 24 bits unsigned integer in big-endian order. * * \param n 24 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 24 * bits unsigned integer in. * \param offset Offset from \p data where to put the most significant * byte of the 24 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT24_BE(n, data, offset) \ { \ (data)[(offset)] = MBEDTLS_BYTE_2(n); \ (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ (data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \ } /** * Get the unsigned 24 bits integer corresponding to three bytes in * little-endian order (LSB first). * * \param data Base address of the memory to get the three bytes from. * \param offset Offset from \p data of the first and least significant * byte of the three bytes to build the 24 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT24_LE(data, offset) \ ( \ ((uint32_t) (data)[(offset)]) \ | ((uint32_t) (data)[(offset) + 1] << 8) \ | ((uint32_t) (data)[(offset) + 2] << 16) \ ) /** * Put in memory a 24 bits unsigned integer in little-endian order. * * \param n 24 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 24 * bits unsigned integer in. * \param offset Offset from \p data where to put the least significant * byte of the 24 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT24_LE(n, data, offset) \ { \ (data)[(offset)] = MBEDTLS_BYTE_0(n); \ (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \ } /** * Get the unsigned 64 bits integer corresponding to eight bytes in * big-endian order (MSB first). * * \param data Base address of the memory to get the eight bytes from. * \param offset Offset from \p data of the first and most significant * byte of the eight bytes to build the 64 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT64_BE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? mbedtls_get_unaligned_uint64((data) + (offset)) \ : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ ) /** * Put in memory a 64 bits unsigned integer in big-endian order. * * \param n 64 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 64 * bits unsigned integer in. * \param offset Offset from \p data where to put the most significant * byte of the 64 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT64_BE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ } \ else \ { \ mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ } \ } /** * Get the unsigned 64 bits integer corresponding to eight bytes in * little-endian order (LSB first). * * \param data Base address of the memory to get the eight bytes from. * \param offset Offset from \p data of the first and least significant * byte of the eight bytes to build the 64 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT64_LE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ : mbedtls_get_unaligned_uint64((data) + (offset)) \ ) /** * Put in memory a 64 bits unsigned integer in little-endian order. * * \param n 64 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 64 * bits unsigned integer in. * \param offset Offset from \p data where to put the least significant * byte of the 64 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT64_LE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ } \ else \ { \ mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ } \ } #endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */ webfakes/src/mbedtls/library/mps_reader.h0000644000176200001440000004113614740737024020235 0ustar liggesusers/* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** * \file mps_reader.h * * \brief This file defines reader objects, which together with their * sibling writer objects form the basis for the communication * between the various layers of the Mbed TLS messaging stack, * as well as the communication between the messaging stack and * the (D)TLS handshake protocol implementation. * * Readers provide a means of transferring incoming data from * a 'producer' providing it in chunks of arbitrary size, to * a 'consumer' which fetches and processes it in chunks of * again arbitrary, and potentially different, size. * * Readers can thus be seen as datagram-to-stream converters, * and they abstract away the following two tasks from the user: * 1. The pointer arithmetic of stepping through a producer- * provided chunk in smaller chunks. * 2. The merging of incoming data chunks in case the * consumer requests data in larger chunks than what the * producer provides. * * The basic abstract flow of operation is the following: * - Initially, the reader is in 'producing mode'. * - The producer hands an incoming data buffer to the reader, * moving it from 'producing' to 'consuming' mode. * - The consumer subsequently fetches and processes the buffer * content. Once that's done -- or partially done and a consumer's * request can't be fulfilled -- the producer revokes the reader's * access to the incoming data buffer, putting the reader back to * producing mode. * - The producer subsequently gathers more incoming data and hands * it to the reader until it switches back to consuming mode * if enough data is available for the last consumer request to * be satisfiable. * - Repeat the above. * * The abstract states of the reader from the producer's and * consumer's perspective are as follows: * * - From the perspective of the consumer, the state of the * reader consists of the following: * - A byte stream representing (concatenation of) the data * received through calls to mbedtls_mps_reader_get(), * - A marker within that byte stream indicating which data * can be considered processed, and hence need not be retained, * when the reader is passed back to the producer via * mbedtls_mps_reader_reclaim(). * The marker is set via mbedtls_mps_reader_commit() * which places it at the end of the current byte stream. * The consumer need not be aware of the distinction between consumer * and producer mode, because it only interfaces with the reader * when the latter is in consuming mode. * * - From the perspective of the producer, the reader's state is one of: * - Attached: The reader is in consuming mode. * - Unset: No incoming data buffer is currently managed by the reader, * and all previously handed incoming data buffers have been * fully processed. More data needs to be fed into the reader * via mbedtls_mps_reader_feed(). * * - Accumulating: No incoming data buffer is currently managed by the * reader, but some data from the previous incoming data * buffer hasn't been processed yet and is internally * held back. * The Attached state belongs to consuming mode, while the Unset and * Accumulating states belong to producing mode. * * Transitioning from the Unset or Accumulating state to Attached is * done via successful calls to mbedtls_mps_reader_feed(), while * transitioning from Attached to either Unset or Accumulating (depending * on what has been processed) is done via mbedtls_mps_reader_reclaim(). * * The following diagram depicts the producer-state progression: * * +------------------+ reclaim * | Unset +<-------------------------------------+ get * +--------|---------+ | +------+ * | | | | * | | | | * | feed +---------+---+--+ | * +--------------------------------------> <---+ * | Attached | * +--------------------------------------> <---+ * | feed, enough data available +---------+---+--+ | * | to serve previous consumer request | | | * | | | | * +--------+---------+ | +------+ * +----> Accumulating |<-------------------------------------+ commit * | +---+--------------+ reclaim, previous read request * | | couldn't be fulfilled * | | * +--------+ * feed, need more data to serve * previous consumer request * | * | * producing mode | consuming mode * | * */ #ifndef MBEDTLS_READER_H #define MBEDTLS_READER_H #include #include "mps_common.h" #include "mps_error.h" struct mbedtls_mps_reader; typedef struct mbedtls_mps_reader mbedtls_mps_reader; /* * Structure definitions */ struct mbedtls_mps_reader { unsigned char *frag; /*!< The fragment of incoming data managed by * the reader; it is provided to the reader * through mbedtls_mps_reader_feed(). The reader * does not own the fragment and does not * perform any allocation operations on it, * but does have read and write access to it. * * The reader is in consuming mode if * and only if \c frag is not \c NULL. */ mbedtls_mps_stored_size_t frag_len; /*!< The length of the current fragment. * Must be 0 if \c frag == \c NULL. */ mbedtls_mps_stored_size_t commit; /*!< The offset of the last commit, relative * to the first byte in the fragment, if * no accumulator is present. If an accumulator * is present, it is viewed as a prefix to the * current fragment, and this variable contains * an offset from the beginning of the accumulator. * * This is only used when the reader is in * consuming mode, i.e. \c frag != \c NULL; * otherwise, its value is \c 0. */ mbedtls_mps_stored_size_t end; /*!< The offset of the end of the last chunk * passed to the user through a call to * mbedtls_mps_reader_get(), relative to the first * byte in the fragment, if no accumulator is * present. If an accumulator is present, it is * viewed as a prefix to the current fragment, and * this variable contains an offset from the * beginning of the accumulator. * * This is only used when the reader is in * consuming mode, i.e. \c frag != \c NULL; * otherwise, its value is \c 0. */ mbedtls_mps_stored_size_t pending; /*!< The amount of incoming data missing on the * last call to mbedtls_mps_reader_get(). * In particular, it is \c 0 if the last call * was successful. * If a reader is reclaimed after an * unsuccessful call to mbedtls_mps_reader_get(), * this variable is used to have the reader * remember how much data should be accumulated * so that the call to mbedtls_mps_reader_get() * succeeds next time. * This is only used when the reader is in * consuming mode, i.e. \c frag != \c NULL; * otherwise, its value is \c 0. */ /* The accumulator is only needed if we need to be able to pause * the reader. A few bytes could be saved by moving this to a * separate struct and using a pointer here. */ unsigned char *acc; /*!< The accumulator is used to gather incoming * data if a read-request via mbedtls_mps_reader_get() * cannot be served from the current fragment. */ mbedtls_mps_stored_size_t acc_len; /*!< The total size of the accumulator. */ mbedtls_mps_stored_size_t acc_available; /*!< The number of bytes currently gathered in * the accumulator. This is both used in * producing and in consuming mode: * While producing, it is increased until * it reaches the value of \c acc_remaining below. * While consuming, it is used to judge if a * get request can be served from the * accumulator or not. * Must not be larger than \c acc_len. */ union { mbedtls_mps_stored_size_t acc_remaining; /*!< This indicates the amount of data still * to be gathered in the accumulator. It is * only used in producing mode. * Must be at most acc_len - acc_available. */ mbedtls_mps_stored_size_t frag_offset; /*!< If an accumulator is present and in use, this * field indicates the offset of the current * fragment from the beginning of the * accumulator. If no accumulator is present * or the accumulator is not in use, this is \c 0. * It is only used in consuming mode. * Must not be larger than \c acc_available. */ } acc_share; }; /* * API organization: * A reader object is usually prepared and maintained * by some lower layer and passed for usage to an upper * layer, and the API naturally splits according to which * layer is supposed to use the respective functions. */ /* * Maintenance API (Lower layer) */ /** * \brief Initialize a reader object * * \param reader The reader to be initialized. * \param acc The buffer to be used as a temporary accumulator * in case get requests through mbedtls_mps_reader_get() * exceed the buffer provided by mbedtls_mps_reader_feed(). * This buffer is owned by the caller and exclusive use * for reading and writing is given to the reader for the * duration of the reader's lifetime. It is thus the caller's * responsibility to maintain (and not touch) the buffer for * the lifetime of the reader, and to properly zeroize and * free the memory after the reader has been destroyed. * \param acc_len The size in Bytes of \p acc. * * \return \c 0 on success. * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure. */ int mbedtls_mps_reader_init(mbedtls_mps_reader *reader, unsigned char *acc, mbedtls_mps_size_t acc_len); /** * \brief Free a reader object * * \param reader The reader to be freed. * * \return \c 0 on success. * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure. */ int mbedtls_mps_reader_free(mbedtls_mps_reader *reader); /** * \brief Pass chunk of data for the reader to manage. * * \param reader The reader context to use. The reader must be * in producing mode. * \param buf The buffer to be managed by the reader. * \param buflen The size in Bytes of \p buffer. * * \return \c 0 on success. In this case, the reader will be * moved to consuming mode and obtains read access * of \p buf until mbedtls_mps_reader_reclaim() * is called. It is the responsibility of the caller * to ensure that the \p buf persists and is not changed * between successful calls to mbedtls_mps_reader_feed() * and mbedtls_mps_reader_reclaim(). * \return \c MBEDTLS_ERR_MPS_READER_NEED_MORE if more input data is * required to fulfill a previous request to mbedtls_mps_reader_get(). * In this case, the reader remains in producing mode and * takes no ownership of the provided buffer (an internal copy * is made instead). * \return Another negative \c MBEDTLS_ERR_READER_XXX error code on * different kinds of failures. */ int mbedtls_mps_reader_feed(mbedtls_mps_reader *reader, unsigned char *buf, mbedtls_mps_size_t buflen); /** * \brief Reclaim reader's access to the current input buffer. * * \param reader The reader context to use. The reader must be * in consuming mode. * \param paused If not \c NULL, the integer at address \p paused will be * modified to indicate whether the reader has been paused * (value \c 1) or not (value \c 0). Pausing happens if there * is uncommitted data and a previous request to * mbedtls_mps_reader_get() has exceeded the bounds of the * input buffer. * * \return \c 0 on success. * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure. */ int mbedtls_mps_reader_reclaim(mbedtls_mps_reader *reader, int *paused); /* * Usage API (Upper layer) */ /** * \brief Request data from the reader. * * \param reader The reader context to use. The reader must * be in consuming mode. * \param desired The desired amount of data to be read, in Bytes. * \param buffer The address to store the buffer pointer in. * This must not be \c NULL. * \param buflen The address to store the actual buffer * length in, or \c NULL. * * \return \c 0 on success. In this case, \c *buf holds the * address of a buffer of size \c *buflen * (if \c buflen != \c NULL) or \c desired * (if \c buflen == \c NULL). The user has read access * to the buffer and guarantee of stability of the data * until the next call to mbedtls_mps_reader_reclaim(). * \return #MBEDTLS_ERR_MPS_READER_OUT_OF_DATA if there is not enough * data available to serve the get request. In this case, the * reader remains intact and in consuming mode, and the consumer * should retry the call after a successful cycle of * mbedtls_mps_reader_reclaim() and mbedtls_mps_reader_feed(). * If, after such a cycle, the consumer requests a different * amount of data, the result is implementation-defined; * progress is guaranteed only if the same amount of data * is requested after a mbedtls_mps_reader_reclaim() and * mbedtls_mps_reader_feed() cycle. * \return Another negative \c MBEDTLS_ERR_READER_XXX error * code for different kinds of failure. * * \note Passing \c NULL as \p buflen is a convenient way to * indicate that fragmentation is not tolerated. * It's functionally equivalent to passing a valid * address as buflen and checking \c *buflen == \c desired * afterwards. */ int mbedtls_mps_reader_get(mbedtls_mps_reader *reader, mbedtls_mps_size_t desired, unsigned char **buffer, mbedtls_mps_size_t *buflen); /** * \brief Mark data obtained from mbedtls_mps_reader_get() as processed. * * This call indicates that all data received from prior calls to * mbedtls_mps_reader_get() has been or will have been * processed when mbedtls_mps_reader_reclaim() is called, * and thus need not be backed up. * * This function has no user observable effect until * mbedtls_mps_reader_reclaim() is called. In particular, * buffers received from mbedtls_mps_reader_get() remain * valid until mbedtls_mps_reader_reclaim() is called. * * \param reader The reader context to use. * * \return \c 0 on success. * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure. * */ int mbedtls_mps_reader_commit(mbedtls_mps_reader *reader); #endif /* MBEDTLS_READER_H */ webfakes/src/mbedtls/library/base64_internal.h0000644000176200001440000000217314740737024021072 0ustar liggesusers/** * \file base64_internal.h * * \brief RFC 1521 base64 encoding/decoding: interfaces for invasive testing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BASE64_INTERNAL #define MBEDTLS_BASE64_INTERNAL #include "common.h" #if defined(MBEDTLS_TEST_HOOKS) /** Given a value in the range 0..63, return the corresponding Base64 digit. * * The implementation assumes that letters are consecutive (e.g. ASCII * but not EBCDIC). * * \param value A value in the range 0..63. * * \return A base64 digit converted from \p value. */ unsigned char mbedtls_ct_base64_enc_char(unsigned char value); /** Given a Base64 digit, return its value. * * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'), * return -1. * * The implementation assumes that letters are consecutive (e.g. ASCII * but not EBCDIC). * * \param c A base64 digit. * * \return The value of the base64 digit \p c. */ signed char mbedtls_ct_base64_dec_value(unsigned char c); #endif /* MBEDTLS_TEST_HOOKS */ #endif /* MBEDTLS_BASE64_INTERNAL */ webfakes/src/mbedtls/library/version.c0000644000176200001440000000120614740737024017566 0ustar liggesusers/* * Version information * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_VERSION_C) #include "mbedtls/version.h" #include unsigned int mbedtls_version_get_number(void) { return MBEDTLS_VERSION_NUMBER; } void mbedtls_version_get_string(char *string) { memcpy(string, MBEDTLS_VERSION_STRING, sizeof(MBEDTLS_VERSION_STRING)); } void mbedtls_version_get_string_full(char *string) { memcpy(string, MBEDTLS_VERSION_STRING_FULL, sizeof(MBEDTLS_VERSION_STRING_FULL)); } #endif /* MBEDTLS_VERSION_C */ webfakes/src/mbedtls/library/psa_crypto_hash.c0000644000176200001440000003530214740737024021273 0ustar liggesusers/* * PSA hashing layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa_crypto_core.h" #include "psa_crypto_hash.h" #include #include #if defined(MBEDTLS_PSA_BUILTIN_HASH) psa_status_t mbedtls_psa_hash_abort( mbedtls_psa_hash_operation_t *operation) { switch (operation->alg) { case 0: /* The object has (apparently) been initialized but it is not * in use. It's ok to call abort on such an object, and there's * nothing to do. */ break; #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_free(&operation->ctx.md5); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_free(&operation->ctx.ripemd160); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_free(&operation->ctx.sha1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_free(&operation->ctx.sha256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_free(&operation->ctx.sha256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_free(&operation->ctx.sha512); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_free(&operation->ctx.sha512); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) mbedtls_sha3_free(&operation->ctx.sha3); break; #endif default: return PSA_ERROR_BAD_STATE; } operation->alg = 0; return PSA_SUCCESS; } psa_status_t mbedtls_psa_hash_setup( mbedtls_psa_hash_operation_t *operation, psa_algorithm_t alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* A context must be freshly initialized before it can be set up. */ if (operation->alg != 0) { return PSA_ERROR_BAD_STATE; } switch (alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_init(&operation->ctx.md5); ret = mbedtls_md5_starts(&operation->ctx.md5); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_init(&operation->ctx.ripemd160); ret = mbedtls_ripemd160_starts(&operation->ctx.ripemd160); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_init(&operation->ctx.sha1); ret = mbedtls_sha1_starts(&operation->ctx.sha1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_init(&operation->ctx.sha256); ret = mbedtls_sha256_starts(&operation->ctx.sha256, 1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_init(&operation->ctx.sha256); ret = mbedtls_sha256_starts(&operation->ctx.sha256, 0); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_init(&operation->ctx.sha512); ret = mbedtls_sha512_starts(&operation->ctx.sha512, 1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_init(&operation->ctx.sha512); ret = mbedtls_sha512_starts(&operation->ctx.sha512, 0); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: mbedtls_sha3_init(&operation->ctx.sha3); ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_224); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: mbedtls_sha3_init(&operation->ctx.sha3); ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: mbedtls_sha3_init(&operation->ctx.sha3); ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_384); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: mbedtls_sha3_init(&operation->ctx.sha3); ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_512); break; #endif default: return PSA_ALG_IS_HASH(alg) ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT; } if (ret == 0) { operation->alg = alg; } else { mbedtls_psa_hash_abort(operation); } return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_hash_clone( const mbedtls_psa_hash_operation_t *source_operation, mbedtls_psa_hash_operation_t *target_operation) { switch (source_operation->alg) { case 0: return PSA_ERROR_BAD_STATE; #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_clone(&target_operation->ctx.md5, &source_operation->ctx.md5); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_clone(&target_operation->ctx.ripemd160, &source_operation->ctx.ripemd160); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_clone(&target_operation->ctx.sha1, &source_operation->ctx.sha1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_clone(&target_operation->ctx.sha256, &source_operation->ctx.sha256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_clone(&target_operation->ctx.sha256, &source_operation->ctx.sha256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_clone(&target_operation->ctx.sha512, &source_operation->ctx.sha512); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_clone(&target_operation->ctx.sha512, &source_operation->ctx.sha512); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) mbedtls_sha3_clone(&target_operation->ctx.sha3, &source_operation->ctx.sha3); break; #endif default: (void) source_operation; (void) target_operation; return PSA_ERROR_NOT_SUPPORTED; } target_operation->alg = source_operation->alg; return PSA_SUCCESS; } psa_status_t mbedtls_psa_hash_update( mbedtls_psa_hash_operation_t *operation, const uint8_t *input, size_t input_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (operation->alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: ret = mbedtls_md5_update(&operation->ctx.md5, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: ret = mbedtls_ripemd160_update(&operation->ctx.ripemd160, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: ret = mbedtls_sha1_update(&operation->ctx.sha1, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: ret = mbedtls_sha256_update(&operation->ctx.sha256, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: ret = mbedtls_sha256_update(&operation->ctx.sha256, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: ret = mbedtls_sha512_update(&operation->ctx.sha512, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: ret = mbedtls_sha512_update(&operation->ctx.sha512, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) ret = mbedtls_sha3_update(&operation->ctx.sha3, input, input_length); break; #endif default: (void) input; (void) input_length; return PSA_ERROR_BAD_STATE; } return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_hash_finish( mbedtls_psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length) { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t actual_hash_length = PSA_HASH_LENGTH(operation->alg); /* Fill the output buffer with something that isn't a valid hash * (barring an attack on the hash and deliberately-crafted input), * in case the caller doesn't check the return status properly. */ *hash_length = hash_size; /* If hash_size is 0 then hash may be NULL and then the * call to memset would have undefined behavior. */ if (hash_size != 0) { memset(hash, '!', hash_size); } if (hash_size < actual_hash_length) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } switch (operation->alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: ret = mbedtls_md5_finish(&operation->ctx.md5, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: ret = mbedtls_ripemd160_finish(&operation->ctx.ripemd160, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: ret = mbedtls_sha1_finish(&operation->ctx.sha1, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) ret = mbedtls_sha3_finish(&operation->ctx.sha3, hash, hash_size); break; #endif default: (void) hash; return PSA_ERROR_BAD_STATE; } status = mbedtls_to_psa_error(ret); exit: if (status == PSA_SUCCESS) { *hash_length = actual_hash_length; } return status; } psa_status_t mbedtls_psa_hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length) { mbedtls_psa_hash_operation_t operation = MBEDTLS_PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; *hash_length = hash_size; status = mbedtls_psa_hash_setup(&operation, alg); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_hash_update(&operation, input, input_length); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_hash_finish(&operation, hash, hash_size, hash_length); if (status != PSA_SUCCESS) { goto exit; } exit: abort_status = mbedtls_psa_hash_abort(&operation); if (status == PSA_SUCCESS) { return abort_status; } else { return status; } } #endif /* MBEDTLS_PSA_BUILTIN_HASH */ #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/bignum_mod_raw_invasive.h0000644000176200001440000000200514740737024023001 0ustar liggesusers/** * \file bignum_mod_raw_invasive.h * * \brief Function declarations for invasive functions of Low-level * modular bignum. */ /** * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H #define MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H #include "common.h" #include "mbedtls/bignum.h" #include "bignum_mod.h" #if defined(MBEDTLS_TEST_HOOKS) /** Convert the result of a quasi-reduction to its canonical representative. * * \param[in,out] X The address of the MPI to be converted. Must have the * same number of limbs as \p N. The input value must * be in range 0 <= X < 2N. * \param[in] N The address of the modulus. */ MBEDTLS_STATIC_TESTABLE void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); #endif /* MBEDTLS_TEST_HOOKS */ #endif /* MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H */ webfakes/src/mbedtls/library/x509_crt.c0000644000176200001440000031276114740737024017471 0ustar liggesusers/* * X.509 certificate parsing and verification * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. * * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf * * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf */ #include "common.h" #if defined(MBEDTLS_X509_CRT_PARSE_C) #include "mbedtls/x509_crt.h" #include "x509_internal.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "psa_util_internal.h" #include "mbedtls/psa_util.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ #include "pk_internal.h" #include "mbedtls/platform.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #if defined(MBEDTLS_HAVE_TIME) #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #else #include #endif #endif #if defined(MBEDTLS_FS_IO) #include #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) #include #include #if defined(__MBED__) #include #else #include #endif /* __MBED__ */ #include #endif /* !_WIN32 || EFIX64 || EFI32 */ #endif /* * Item in a verification chain: cert and flags for it */ typedef struct { mbedtls_x509_crt *crt; uint32_t flags; } x509_crt_verify_chain_item; /* * Max size of verification chain: end-entity + intermediates + trusted root */ #define X509_MAX_VERIFY_CHAIN_SIZE (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2) /* Default profile. Do not remove items unless there are serious security * concerns. */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = { /* Hashes from SHA-256 and above. Note that this selection * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), 0xFFFFFFF, /* Any PK alg */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Curves at or above 128-bit security level. Note that this selection * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | 0, #else /* MBEDTLS_PK_HAVE_ECC_KEYS */ 0, #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 2048, }; /* Next-generation profile. Currently identical to the default, but may * be tightened at any time. */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = { /* Hashes from SHA-256 and above. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), 0xFFFFFFF, /* Any PK alg */ #if defined(MBEDTLS_ECP_C) /* Curves at or above 128-bit security level. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256K1), #else 0, #endif 2048, }; /* * NSA Suite B Profile */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = { /* Only SHA-256 and 384 */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384), /* Only ECDSA */ MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) | MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY), #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Only NIST P-256 and P-384 */ MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1), #else /* MBEDTLS_PK_HAVE_ECC_KEYS */ 0, #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 0, }; /* * Empty / all-forbidden profile */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none = { 0, 0, 0, (uint32_t) -1, }; /* * Check md_alg against profile * Return 0 if md_alg is acceptable for this profile, -1 otherwise */ static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, mbedtls_md_type_t md_alg) { if (md_alg == MBEDTLS_MD_NONE) { return -1; } if ((profile->allowed_mds & MBEDTLS_X509_ID_FLAG(md_alg)) != 0) { return 0; } return -1; } /* * Check pk_alg against profile * Return 0 if pk_alg is acceptable for this profile, -1 otherwise */ static int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, mbedtls_pk_type_t pk_alg) { if (pk_alg == MBEDTLS_PK_NONE) { return -1; } if ((profile->allowed_pks & MBEDTLS_X509_ID_FLAG(pk_alg)) != 0) { return 0; } return -1; } /* * Check key against profile * Return 0 if pk is acceptable for this profile, -1 otherwise */ static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile, const mbedtls_pk_context *pk) { const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(pk); #if defined(MBEDTLS_RSA_C) if (pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) { if (mbedtls_pk_get_bitlen(pk) >= profile->rsa_min_bitlen) { return 0; } return -1; } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_alg == MBEDTLS_PK_ECDSA || pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { const mbedtls_ecp_group_id gid = mbedtls_pk_get_ec_group_id(pk); if (gid == MBEDTLS_ECP_DP_NONE) { return -1; } if ((profile->allowed_curves & MBEDTLS_X509_ID_FLAG(gid)) != 0) { return 0; } return -1; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ return -1; } /* * Like memcmp, but case-insensitive and always returns -1 if different */ static int x509_memcasecmp(const void *s1, const void *s2, size_t len) { size_t i; unsigned char diff; const unsigned char *n1 = s1, *n2 = s2; for (i = 0; i < len; i++) { diff = n1[i] ^ n2[i]; if (diff == 0) { continue; } if (diff == 32 && ((n1[i] >= 'a' && n1[i] <= 'z') || (n1[i] >= 'A' && n1[i] <= 'Z'))) { continue; } return -1; } return 0; } /* * Return 0 if name matches wildcard, -1 otherwise */ static int x509_check_wildcard(const char *cn, const mbedtls_x509_buf *name) { size_t i; size_t cn_idx = 0, cn_len = strlen(cn); /* We can't have a match if there is no wildcard to match */ if (name->len < 3 || name->p[0] != '*' || name->p[1] != '.') { return -1; } for (i = 0; i < cn_len; ++i) { if (cn[i] == '.') { cn_idx = i; break; } } if (cn_idx == 0) { return -1; } if (cn_len - cn_idx == name->len - 1 && x509_memcasecmp(name->p + 1, cn + cn_idx, name->len - 1) == 0) { return 0; } return -1; } /* * Compare two X.509 strings, case-insensitive, and allowing for some encoding * variations (but not all). * * Return 0 if equal, -1 otherwise. */ static int x509_string_cmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b) { if (a->tag == b->tag && a->len == b->len && memcmp(a->p, b->p, b->len) == 0) { return 0; } if ((a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && (b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && a->len == b->len && x509_memcasecmp(a->p, b->p, b->len) == 0) { return 0; } return -1; } /* * Compare two X.509 Names (aka rdnSequence). * * See RFC 5280 section 7.1, though we don't implement the whole algorithm: * we sometimes return unequal when the full algorithm would return equal, * but never the other way. (In particular, we don't do Unicode normalisation * or space folding.) * * Return 0 if equal, -1 otherwise. */ static int x509_name_cmp(const mbedtls_x509_name *a, const mbedtls_x509_name *b) { /* Avoid recursion, it might not be optimised by the compiler */ while (a != NULL || b != NULL) { if (a == NULL || b == NULL) { return -1; } /* type */ if (a->oid.tag != b->oid.tag || a->oid.len != b->oid.len || memcmp(a->oid.p, b->oid.p, b->oid.len) != 0) { return -1; } /* value */ if (x509_string_cmp(&a->val, &b->val) != 0) { return -1; } /* structure of the list of sets */ if (a->next_merged != b->next_merged) { return -1; } a = a->next; b = b->next; } /* a == NULL == b */ return 0; } /* * Reset (init or clear) a verify_chain */ static void x509_crt_verify_chain_reset( mbedtls_x509_crt_verify_chain *ver_chain) { size_t i; for (i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++) { ver_chain->items[i].crt = NULL; ver_chain->items[i].flags = (uint32_t) -1; } ver_chain->len = 0; #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) ver_chain->trust_ca_cb_result = NULL; #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ static int x509_get_version(unsigned char **p, const unsigned char *end, int *ver) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { *ver = 0; return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } end = *p + len; if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret); } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } */ static int x509_get_dates(unsigned char **p, const unsigned char *end, mbedtls_x509_time *from, mbedtls_x509_time *to) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); } end = *p + len; if ((ret = mbedtls_x509_get_time(p, end, from)) != 0) { return ret; } if ((ret = mbedtls_x509_get_time(p, end, to)) != 0) { return ret; } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * X.509 v2/v3 unique identifier (not parsed) */ static int x509_get_uid(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *uid, int n) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (*p == end) { return 0; } uid->tag = **p; if ((ret = mbedtls_asn1_get_tag(p, end, &uid->len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } uid->p = *p; *p += uid->len; return 0; } static int x509_get_basic_constraints(unsigned char **p, const unsigned char *end, int *ca_istrue, int *max_pathlen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* * BasicConstraints ::= SEQUENCE { * cA BOOLEAN DEFAULT FALSE, * pathLenConstraint INTEGER (0..MAX) OPTIONAL } */ *ca_istrue = 0; /* DEFAULT FALSE */ *max_pathlen = 0; /* endless */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p == end) { return 0; } if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { ret = mbedtls_asn1_get_int(p, end, ca_istrue); } if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*ca_istrue != 0) { *ca_istrue = 1; } } if (*p == end) { return 0; } if ((ret = mbedtls_asn1_get_int(p, end, max_pathlen)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer * overflow, which is an undefined behavior. */ if (*max_pathlen == INT_MAX) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH); } (*max_pathlen)++; return 0; } /* * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId * * KeyPurposeId ::= OBJECT IDENTIFIER */ static int x509_get_ext_key_usage(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *ext_key_usage) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Sequence length must be >= 1 */ if (ext_key_usage->buf.p == NULL) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH); } return 0; } /* * SubjectKeyIdentifier ::= KeyIdentifier * * KeyIdentifier ::= OCTET STRING */ static int x509_get_subject_key_id(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *subject_key_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0u; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } subject_key_id->len = len; subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING; subject_key_id->p = *p; *p += len; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * AuthorityKeyIdentifier ::= SEQUENCE { * keyIdentifier [0] KeyIdentifier OPTIONAL, * authorityCertIssuer [1] GeneralNames OPTIONAL, * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } * * KeyIdentifier ::= OCTET STRING */ static int x509_get_authority_key_id(unsigned char **p, unsigned char *end, mbedtls_x509_authority *authority_key_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0u; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC); /* KeyIdentifier is an OPTIONAL field */ if (ret == 0) { authority_key_id->keyIdentifier.len = len; authority_key_id->keyIdentifier.p = *p; /* Setting tag of the keyIdentfier intentionally to 0x04. * Although the .keyIdentfier field is CONTEXT_SPECIFIC ([0] OPTIONAL), * its tag with the content is the payload of on OCTET STRING primitive */ authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; *p += len; } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p < end) { /* Getting authorityCertIssuer using the required specific class tag [1] */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1)) != 0) { /* authorityCertIssuer and authorityCertSerialNumber MUST both be present or both be absent. At this point we expect to have both. */ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* "end" also includes the CertSerialNumber field so "len" shall be used */ ret = mbedtls_x509_get_subject_alt_name_ext(p, (*p+len), &authority_key_id->authorityCertIssuer); if (ret != 0) { return ret; } /* Getting authorityCertSerialNumber using the required specific class tag [2] */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } authority_key_id->authorityCertSerialNumber.len = len; authority_key_id->authorityCertSerialNumber.p = *p; authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_INTEGER; *p += len; } if (*p != end) { return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } return 0; } /* * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } * * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } * * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation * * PolicyInformation ::= SEQUENCE { * policyIdentifier CertPolicyId, * policyQualifiers SEQUENCE SIZE (1..MAX) OF * PolicyQualifierInfo OPTIONAL } * * CertPolicyId ::= OBJECT IDENTIFIER * * PolicyQualifierInfo ::= SEQUENCE { * policyQualifierId PolicyQualifierId, * qualifier ANY DEFINED BY policyQualifierId } * * -- policyQualifierIds for Internet policy qualifiers * * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } * * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) * * Qualifier ::= CHOICE { * cPSuri CPSuri, * userNotice UserNotice } * * CPSuri ::= IA5String * * UserNotice ::= SEQUENCE { * noticeRef NoticeReference OPTIONAL, * explicitText DisplayText OPTIONAL } * * NoticeReference ::= SEQUENCE { * organization DisplayText, * noticeNumbers SEQUENCE OF INTEGER } * * DisplayText ::= CHOICE { * ia5String IA5String (SIZE (1..200)), * visibleString VisibleString (SIZE (1..200)), * bmpString BMPString (SIZE (1..200)), * utf8String UTF8String (SIZE (1..200)) } * * NOTE: we only parse and use anyPolicy without qualifiers at this point * as defined in RFC 5280. */ static int x509_get_certificate_policies(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *certificate_policies) { int ret, parse_ret = 0; size_t len; mbedtls_asn1_buf *buf; mbedtls_asn1_sequence *cur = certificate_policies; /* Get main sequence tag */ ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * Cannot be an empty sequence. */ if (len == 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } while (*p < end) { mbedtls_x509_buf policy_oid; const unsigned char *policy_end; /* * Get the policy sequence */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } policy_end = *p + len; if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } policy_oid.tag = MBEDTLS_ASN1_OID; policy_oid.len = len; policy_oid.p = *p; /* * Only AnyPolicy is currently supported when enforcing policy. */ if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_POLICY, &policy_oid) != 0) { /* * Set the parsing return code but continue parsing, in case this * extension is critical. */ parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } /* Allocate and assign next pointer */ if (cur->buf.p != NULL) { if (cur->next != NULL) { return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; } cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); if (cur->next == NULL) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_ALLOC_FAILED); } cur = cur->next; } buf = &(cur->buf); buf->tag = policy_oid.tag; buf->p = policy_oid.p; buf->len = policy_oid.len; *p += len; /* * If there is an optional qualifier, then *p < policy_end * Check the Qualifier len to verify it doesn't exceed policy_end. */ if (*p < policy_end) { if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* * Skip the optional policy qualifiers. */ *p += len; } if (*p != policy_end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } /* Set final sequence entry's next pointer to NULL */ cur->next = NULL; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return parse_ret; } /* * X.509 v3 extensions * */ static int x509_get_crt_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_crt *crt, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet; if (*p == end) { return 0; } if ((ret = mbedtls_x509_get_ext(p, end, &crt->v3_ext, 3)) != 0) { return ret; } end = crt->v3_ext.p + crt->v3_ext.len; while (*p < end) { /* * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING } */ mbedtls_x509_buf extn_oid = { 0, 0, NULL }; int is_critical = 0; /* DEFAULT FALSE */ int ext_type = 0; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_ext_data = *p + len; /* Get extension ID */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } extn_oid.tag = MBEDTLS_ASN1_OID; extn_oid.p = *p; *p += extn_oid.len; /* Get optional critical */ if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Data should be octet string type */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } start_ext_octet = *p; end_ext_octet = *p + len; if (end_ext_octet != end_ext_data) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * Detect supported extensions */ ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); if (ret != 0) { /* Give the callback (if any) a chance to handle the extension */ if (cb != NULL) { ret = cb(p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet); if (ret != 0 && is_critical) { return ret; } *p = end_ext_octet; continue; } /* No parser found, skip extension */ *p = end_ext_octet; if (is_critical) { /* Data is marked as critical: fail */ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } continue; } /* Forbid repeated extensions */ if ((crt->ext_types & ext_type) != 0) { return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; } crt->ext_types |= ext_type; switch (ext_type) { case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: /* Parse basic constraints */ if ((ret = x509_get_basic_constraints(p, end_ext_octet, &crt->ca_istrue, &crt->max_pathlen)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_KEY_USAGE: /* Parse key usage */ if ((ret = mbedtls_x509_get_key_usage(p, end_ext_octet, &crt->key_usage)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: /* Parse extended key usage */ if ((ret = x509_get_ext_key_usage(p, end_ext_octet, &crt->ext_key_usage)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER: /* Parse subject key identifier */ if ((ret = x509_get_subject_key_id(p, end_ext_data, &crt->subject_key_id)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER: /* Parse authority key identifier */ if ((ret = x509_get_authority_key_id(p, end_ext_octet, &crt->authority_key_id)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: /* Parse subject alt name * SubjectAltName ::= GeneralNames */ if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet, &crt->subject_alt_names)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_NS_CERT_TYPE: /* Parse netscape certificate type */ if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_octet, &crt->ns_cert_type)) != 0) { return ret; } break; case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES: /* Parse certificate policies type */ if ((ret = x509_get_certificate_policies(p, end_ext_octet, &crt->certificate_policies)) != 0) { /* Give the callback (if any) a chance to handle the extension * if it contains unsupported policies */ if (ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL && cb(p_ctx, crt, &extn_oid, is_critical, start_ext_octet, end_ext_octet) == 0) { break; } if (is_critical) { return ret; } else /* * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we * cannot interpret or enforce the policy. However, it is up to * the user to choose how to enforce the policies, * unless the extension is critical. */ if (ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { return ret; } } break; default: /* * If this is a non-critical extension, which the oid layer * supports, but there isn't an x509 parser for it, * skip the extension. */ if (is_critical) { return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } else { *p = end_ext_octet; } } } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse and fill a single X.509 certificate in DER format */ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, const unsigned char *buf, size_t buflen, int make_copy, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *p, *end, *crt_end; mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; memset(&sig_params1, 0, sizeof(mbedtls_x509_buf)); memset(&sig_params2, 0, sizeof(mbedtls_x509_buf)); memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf)); /* * Check for valid input */ if (crt == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } /* Use the original buffer until we figure out actual length. */ p = (unsigned char *) buf; len = buflen; end = p + len; /* * Certificate ::= SEQUENCE { * tbsCertificate TBSCertificate, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERR_X509_INVALID_FORMAT; } end = crt_end = p + len; crt->raw.len = (size_t) (crt_end - buf); if (make_copy != 0) { /* Create and populate a new buffer for the raw field. */ crt->raw.p = p = mbedtls_calloc(1, crt->raw.len); if (crt->raw.p == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } memcpy(crt->raw.p, buf, crt->raw.len); crt->own_buffer = 1; p += crt->raw.len - len; end = crt_end = p + len; } else { crt->raw.p = (unsigned char *) buf; crt->own_buffer = 0; } /* * TBSCertificate ::= SEQUENCE { */ crt->tbs.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } end = p + len; crt->tbs.len = (size_t) (end - crt->tbs.p); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } * * CertificateSerialNumber ::= INTEGER * * signature AlgorithmIdentifier */ if ((ret = x509_get_version(&p, end, &crt->version)) != 0 || (ret = mbedtls_x509_get_serial(&p, end, &crt->serial)) != 0 || (ret = mbedtls_x509_get_alg(&p, end, &crt->sig_oid, &sig_params1)) != 0) { mbedtls_x509_crt_free(crt); return ret; } if (crt->version < 0 || crt->version > 2) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERR_X509_UNKNOWN_VERSION; } crt->version++; if ((ret = mbedtls_x509_get_sig_alg(&crt->sig_oid, &sig_params1, &crt->sig_md, &crt->sig_pk, &crt->sig_opts)) != 0) { mbedtls_x509_crt_free(crt); return ret; } /* * issuer Name */ crt->issuer_raw.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if ((ret = mbedtls_x509_get_name(&p, p + len, &crt->issuer)) != 0) { mbedtls_x509_crt_free(crt); return ret; } crt->issuer_raw.len = (size_t) (p - crt->issuer_raw.p); /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } * */ if ((ret = x509_get_dates(&p, end, &crt->valid_from, &crt->valid_to)) != 0) { mbedtls_x509_crt_free(crt); return ret; } /* * subject Name */ crt->subject_raw.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if (len && (ret = mbedtls_x509_get_name(&p, p + len, &crt->subject)) != 0) { mbedtls_x509_crt_free(crt); return ret; } crt->subject_raw.len = (size_t) (p - crt->subject_raw.p); /* * SubjectPublicKeyInfo */ crt->pk_raw.p = p; if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &crt->pk)) != 0) { mbedtls_x509_crt_free(crt); return ret; } crt->pk_raw.len = (size_t) (p - crt->pk_raw.p); /* * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * extensions [3] EXPLICIT Extensions OPTIONAL * -- If present, version shall be v3 */ if (crt->version == 2 || crt->version == 3) { ret = x509_get_uid(&p, end, &crt->issuer_id, 1); if (ret != 0) { mbedtls_x509_crt_free(crt); return ret; } } if (crt->version == 2 || crt->version == 3) { ret = x509_get_uid(&p, end, &crt->subject_id, 2); if (ret != 0) { mbedtls_x509_crt_free(crt); return ret; } } if (crt->version == 3) { ret = x509_get_crt_ext(&p, end, crt, cb, p_ctx); if (ret != 0) { mbedtls_x509_crt_free(crt); return ret; } } if (p != end) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } end = crt_end; /* * } * -- end of TBSCertificate * * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) { mbedtls_x509_crt_free(crt); return ret; } if (crt->sig_oid.len != sig_oid2.len || memcmp(crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len) != 0 || sig_params1.tag != sig_params2.tag || sig_params1.len != sig_params2.len || (sig_params1.len != 0 && memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERR_X509_SIG_MISMATCH; } if ((ret = mbedtls_x509_get_sig(&p, end, &crt->sig)) != 0) { mbedtls_x509_crt_free(crt); return ret; } if (p != end) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse one X.509 certificate in DER format from a buffer and add them to a * chained list */ static int mbedtls_x509_crt_parse_der_internal(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen, int make_copy, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *crt = chain, *prev = NULL; /* * Check for valid input */ if (crt == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } while (crt->version != 0 && crt->next != NULL) { prev = crt; crt = crt->next; } /* * Add new certificate on the end of the chain if needed. */ if (crt->version != 0 && crt->next == NULL) { crt->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); if (crt->next == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } prev = crt; mbedtls_x509_crt_init(crt->next); crt = crt->next; } ret = x509_crt_parse_der_core(crt, buf, buflen, make_copy, cb, p_ctx); if (ret != 0) { if (prev) { prev->next = NULL; } if (crt != chain) { mbedtls_free(crt); } return ret; } return 0; } int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen) { return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 0, NULL, NULL); } int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen, int make_copy, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx) { return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, make_copy, cb, p_ctx); } int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen) { return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 1, NULL, NULL); } /* * Parse one or more PEM certificates from a buffer and add them to the chained * list */ int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen) { #if defined(MBEDTLS_PEM_PARSE_C) int success = 0, first_error = 0, total_failed = 0; int buf_format = MBEDTLS_X509_FORMAT_DER; #endif /* * Check for valid input */ if (chain == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } /* * Determine buffer content. Buffer contains either one DER certificate or * one or more PEM certificates. */ #if defined(MBEDTLS_PEM_PARSE_C) if (buflen != 0 && buf[buflen - 1] == '\0' && strstr((const char *) buf, "-----BEGIN CERTIFICATE-----") != NULL) { buf_format = MBEDTLS_X509_FORMAT_PEM; } if (buf_format == MBEDTLS_X509_FORMAT_DER) { return mbedtls_x509_crt_parse_der(chain, buf, buflen); } #else return mbedtls_x509_crt_parse_der(chain, buf, buflen); #endif #if defined(MBEDTLS_PEM_PARSE_C) if (buf_format == MBEDTLS_X509_FORMAT_PEM) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_pem_context pem; /* 1 rather than 0 since the terminating NULL byte is counted in */ while (buflen > 1) { size_t use_len; mbedtls_pem_init(&pem); /* If we get there, we know the string is null-terminated */ ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----", buf, NULL, 0, &use_len); if (ret == 0) { /* * Was PEM encoded */ buflen -= use_len; buf += use_len; } else if (ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA) { return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { mbedtls_pem_free(&pem); /* * PEM header and footer were found */ buflen -= use_len; buf += use_len; if (first_error == 0) { first_error = ret; } total_failed++; continue; } else { break; } ret = mbedtls_x509_crt_parse_der(chain, pem.buf, pem.buflen); mbedtls_pem_free(&pem); if (ret != 0) { /* * Quit parsing on a memory error */ if (ret == MBEDTLS_ERR_X509_ALLOC_FAILED) { return ret; } if (first_error == 0) { first_error = ret; } total_failed++; continue; } success = 1; } } if (success) { return total_failed; } else if (first_error) { return first_error; } else { return MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT; } #endif /* MBEDTLS_PEM_PARSE_C */ } #if defined(MBEDTLS_FS_IO) /* * Load one or more certificates and add them to the chained list */ int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_x509_crt_parse(chain, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path) { int ret = 0; #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) int w_ret; WCHAR szDir[MAX_PATH]; char filename[MAX_PATH]; char *p; size_t len = strlen(path); WIN32_FIND_DATAW file_data; HANDLE hFind; if (len > MAX_PATH - 3) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } memset(szDir, 0, sizeof(szDir)); memset(filename, 0, MAX_PATH); memcpy(filename, path, len); filename[len++] = '\\'; p = filename + len; filename[len++] = '*'; /* * Note this function uses the code page CP_ACP which is the system default * ANSI codepage. The input string is always described in BYTES and the * output length is described in WCHARs. */ w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir, MAX_PATH - 3); if (w_ret == 0) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } hFind = FindFirstFileW(szDir, &file_data); if (hFind == INVALID_HANDLE_VALUE) { return MBEDTLS_ERR_X509_FILE_IO_ERROR; } len = MAX_PATH - len; do { memset(p, 0, len); if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { continue; } w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName, -1, p, (int) len, NULL, NULL); if (w_ret == 0) { ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; goto cleanup; } w_ret = mbedtls_x509_crt_parse_file(chain, filename); if (w_ret < 0) { ret++; } else { ret += w_ret; } } while (FindNextFileW(hFind, &file_data) != 0); if (GetLastError() != ERROR_NO_MORE_FILES) { ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; } cleanup: FindClose(hFind); #else /* _WIN32 */ int t_ret; int snp_ret; struct stat sb; struct dirent *entry; char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; DIR *dir = opendir(path); if (dir == NULL) { return MBEDTLS_ERR_X509_FILE_IO_ERROR; } #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&mbedtls_threading_readdir_mutex)) != 0) { closedir(dir); return ret; } #endif /* MBEDTLS_THREADING_C */ memset(&sb, 0, sizeof(sb)); while ((entry = readdir(dir)) != NULL) { snp_ret = mbedtls_snprintf(entry_name, sizeof(entry_name), "%s/%s", path, entry->d_name); if (snp_ret < 0 || (size_t) snp_ret >= sizeof(entry_name)) { ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; goto cleanup; } else if (stat(entry_name, &sb) == -1) { if (errno == ENOENT) { /* Broken symbolic link - ignore this entry. stat(2) will return this error for either (a) a dangling symlink or (b) a missing file. Given that we have just obtained the filename from readdir, assume that it does exist and therefore treat this as a dangling symlink. */ continue; } else { /* Some other file error; report the error. */ ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; goto cleanup; } } if (!S_ISREG(sb.st_mode)) { continue; } // Ignore parse errors // t_ret = mbedtls_x509_crt_parse_file(chain, entry_name); if (t_ret < 0) { ret++; } else { ret += t_ret; } } cleanup: closedir(dir); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&mbedtls_threading_readdir_mutex) != 0) { ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif /* MBEDTLS_THREADING_C */ #endif /* _WIN32 */ return ret; } #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) #define PRINT_ITEM(i) \ do { \ ret = mbedtls_snprintf(p, n, "%s" i, sep); \ MBEDTLS_X509_SAFE_SNPRINTF; \ sep = ", "; \ } while (0) #define CERT_TYPE(type, name) \ do { \ if (ns_cert_type & (type)) { \ PRINT_ITEM(name); \ } \ } while (0) #define KEY_USAGE(code, name) \ do { \ if (key_usage & (code)) { \ PRINT_ITEM(name); \ } \ } while (0) static int x509_info_ext_key_usage(char **buf, size_t *size, const mbedtls_x509_sequence *extended_key_usage) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const char *desc; size_t n = *size; char *p = *buf; const mbedtls_x509_sequence *cur = extended_key_usage; const char *sep = ""; while (cur != NULL) { if (mbedtls_oid_get_extended_key_usage(&cur->buf, &desc) != 0) { desc = "???"; } ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); MBEDTLS_X509_SAFE_SNPRINTF; sep = ", "; cur = cur->next; } *size = n; *buf = p; return 0; } static int x509_info_cert_policies(char **buf, size_t *size, const mbedtls_x509_sequence *certificate_policies) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const char *desc; size_t n = *size; char *p = *buf; const mbedtls_x509_sequence *cur = certificate_policies; const char *sep = ""; while (cur != NULL) { if (mbedtls_oid_get_certificate_policies(&cur->buf, &desc) != 0) { desc = "???"; } ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); MBEDTLS_X509_SAFE_SNPRINTF; sep = ", "; cur = cur->next; } *size = n; *buf = p; return 0; } /* * Return an informational string about the certificate. */ #define BEFORE_COLON 18 #define BC "18" int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crt *crt) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; char *p; char key_size_str[BEFORE_COLON]; p = buf; n = size; if (NULL == crt) { ret = mbedtls_snprintf(p, n, "\nCertificate is uninitialised!\n"); MBEDTLS_X509_SAFE_SNPRINTF; return (int) (size - n); } ret = mbedtls_snprintf(p, n, "%scert. version : %d\n", prefix, crt->version); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "%sserial number : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_serial_gets(p, n, &crt->serial); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sissuer name : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &crt->issuer); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &crt->subject); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sissued on : " \ "%04d-%02d-%02d %02d:%02d:%02d", prefix, crt->valid_from.year, crt->valid_from.mon, crt->valid_from.day, crt->valid_from.hour, crt->valid_from.min, crt->valid_from.sec); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sexpires on : " \ "%04d-%02d-%02d %02d:%02d:%02d", prefix, crt->valid_to.year, crt->valid_to.mon, crt->valid_to.day, crt->valid_to.hour, crt->valid_to.min, crt->valid_to.sec); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_sig_alg_gets(p, n, &crt->sig_oid, crt->sig_pk, crt->sig_md, crt->sig_opts); MBEDTLS_X509_SAFE_SNPRINTF; /* Key size */ if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON, mbedtls_pk_get_name(&crt->pk))) != 0) { return ret; } ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, (int) mbedtls_pk_get_bitlen(&crt->pk)); MBEDTLS_X509_SAFE_SNPRINTF; /* * Optional extensions */ if (crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) { ret = mbedtls_snprintf(p, n, "\n%sbasic constraints : CA=%s", prefix, crt->ca_istrue ? "true" : "false"); MBEDTLS_X509_SAFE_SNPRINTF; if (crt->max_pathlen > 0) { ret = mbedtls_snprintf(p, n, ", max_pathlen=%d", crt->max_pathlen - 1); MBEDTLS_X509_SAFE_SNPRINTF; } } if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n, &crt->subject_alt_names, prefix)) != 0) { return ret; } } if (crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) { ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) { return ret; } } if (crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) { ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_key_usage(&p, &n, crt->key_usage)) != 0) { return ret; } } if (crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) { ret = mbedtls_snprintf(p, n, "\n%sext key usage : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = x509_info_ext_key_usage(&p, &n, &crt->ext_key_usage)) != 0) { return ret; } } if (crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES) { ret = mbedtls_snprintf(p, n, "\n%scertificate policies : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = x509_info_cert_policies(&p, &n, &crt->certificate_policies)) != 0) { return ret; } } ret = mbedtls_snprintf(p, n, "\n"); MBEDTLS_X509_SAFE_SNPRINTF; return (int) (size - n); } struct x509_crt_verify_string { int code; const char *string; }; #define X509_CRT_ERROR_INFO(err, err_str, info) { err, info }, static const struct x509_crt_verify_string x509_crt_verify_strings[] = { MBEDTLS_X509_CRT_ERROR_INFO_LIST { 0, NULL } }; #undef X509_CRT_ERROR_INFO int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, uint32_t flags) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const struct x509_crt_verify_string *cur; char *p = buf; size_t n = size; for (cur = x509_crt_verify_strings; cur->string != NULL; cur++) { if ((flags & cur->code) == 0) { continue; } ret = mbedtls_snprintf(p, n, "%s%s\n", prefix, cur->string); MBEDTLS_X509_SAFE_SNPRINTF; flags ^= cur->code; } if (flags != 0) { ret = mbedtls_snprintf(p, n, "%sUnknown reason " "(this should not happen)\n", prefix); MBEDTLS_X509_SAFE_SNPRINTF; } return (int) (size - n); } #endif /* MBEDTLS_X509_REMOVE_INFO */ int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, unsigned int usage) { unsigned int usage_must, usage_may; unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY | MBEDTLS_X509_KU_DECIPHER_ONLY; if ((crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) == 0) { return 0; } usage_must = usage & ~may_mask; if (((crt->key_usage & ~may_mask) & usage_must) != usage_must) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } usage_may = usage & may_mask; if (((crt->key_usage & may_mask) | usage_may) != usage_may) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } return 0; } int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, const char *usage_oid, size_t usage_len) { const mbedtls_x509_sequence *cur; /* Extension is not mandatory, absent means no restriction */ if ((crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) == 0) { return 0; } /* * Look for the requested usage (or wildcard ANY) in our list */ for (cur = &crt->ext_key_usage; cur != NULL; cur = cur->next) { const mbedtls_x509_buf *cur_oid = &cur->buf; if (cur_oid->len == usage_len && memcmp(cur_oid->p, usage_oid, usage_len) == 0) { return 0; } if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid) == 0) { return 0; } } return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } #if defined(MBEDTLS_X509_CRL_PARSE_C) /* * Return 1 if the certificate is revoked, or 0 otherwise. */ int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl) { const mbedtls_x509_crl_entry *cur = &crl->entry; while (cur != NULL && cur->serial.len != 0) { if (crt->serial.len == cur->serial.len && memcmp(crt->serial.p, cur->serial.p, crt->serial.len) == 0) { return 1; } cur = cur->next; } return 0; } /* * Check that the given certificate is not revoked according to the CRL. * Skip validation if no CRL for the given CA is present. */ static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, mbedtls_x509_crl *crl_list, const mbedtls_x509_crt_profile *profile, const mbedtls_x509_time *now) { int flags = 0; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t psa_algorithm; #else const mbedtls_md_info_t *md_info; #endif /* MBEDTLS_USE_PSA_CRYPTO */ size_t hash_length; if (ca == NULL) { return flags; } while (crl_list != NULL) { if (crl_list->version == 0 || x509_name_cmp(&crl_list->issuer, &ca->subject) != 0) { crl_list = crl_list->next; continue; } /* * Check if the CA is configured to sign CRLs */ if (mbedtls_x509_crt_check_key_usage(ca, MBEDTLS_X509_KU_CRL_SIGN) != 0) { flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } /* * Check if CRL is correctly signed by the trusted CA */ if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) { flags |= MBEDTLS_X509_BADCRL_BAD_MD; } if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) { flags |= MBEDTLS_X509_BADCRL_BAD_PK; } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm = mbedtls_md_psa_alg_from_type(crl_list->sig_md); if (psa_hash_compute(psa_algorithm, crl_list->tbs.p, crl_list->tbs.len, hash, sizeof(hash), &hash_length) != PSA_SUCCESS) { /* Note: this can't happen except after an internal error */ flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } #else md_info = mbedtls_md_info_from_type(crl_list->sig_md); hash_length = mbedtls_md_get_size(md_info); if (mbedtls_md(md_info, crl_list->tbs.p, crl_list->tbs.len, hash) != 0) { /* Note: this can't happen except after an internal error */ flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (x509_profile_check_key(profile, &ca->pk) != 0) { flags |= MBEDTLS_X509_BADCERT_BAD_KEY; } if (mbedtls_pk_verify_ext(crl_list->sig_pk, crl_list->sig_opts, &ca->pk, crl_list->sig_md, hash, hash_length, crl_list->sig.p, crl_list->sig.len) != 0) { flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } #if defined(MBEDTLS_HAVE_TIME_DATE) /* * Check for validity of CRL (Do not drop out) */ if (mbedtls_x509_time_cmp(&crl_list->next_update, now) < 0) { flags |= MBEDTLS_X509_BADCRL_EXPIRED; } if (mbedtls_x509_time_cmp(&crl_list->this_update, now) > 0) { flags |= MBEDTLS_X509_BADCRL_FUTURE; } #else ((void) now); #endif /* * Check if certificate is revoked */ if (mbedtls_x509_crt_is_revoked(crt, crl_list)) { flags |= MBEDTLS_X509_BADCERT_REVOKED; break; } crl_list = crl_list->next; } return flags; } #endif /* MBEDTLS_X509_CRL_PARSE_C */ /* * Check the signature of a certificate by its parent */ static int x509_crt_check_signature(const mbedtls_x509_crt *child, mbedtls_x509_crt *parent, mbedtls_x509_crt_restart_ctx *rs_ctx) { size_t hash_len; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; #if !defined(MBEDTLS_USE_PSA_CRYPTO) const mbedtls_md_info_t *md_info; md_info = mbedtls_md_info_from_type(child->sig_md); hash_len = mbedtls_md_get_size(md_info); /* Note: hash errors can happen only after an internal error */ if (mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash) != 0) { return -1; } #else psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(child->sig_md); psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_hash_compute(hash_alg, child->tbs.p, child->tbs.len, hash, sizeof(hash), &hash_len); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Skip expensive computation on obvious mismatch */ if (!mbedtls_pk_can_do(&parent->pk, child->sig_pk)) { return -1; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA) { return mbedtls_pk_verify_restartable(&parent->pk, child->sig_md, hash, hash_len, child->sig.p, child->sig.len, &rs_ctx->pk); } #else (void) rs_ctx; #endif return mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent->pk, child->sig_md, hash, hash_len, child->sig.p, child->sig.len); } /* * Check if 'parent' is a suitable parent (signing CA) for 'child'. * Return 0 if yes, -1 if not. * * top means parent is a locally-trusted certificate */ static int x509_crt_check_parent(const mbedtls_x509_crt *child, const mbedtls_x509_crt *parent, int top) { int need_ca_bit; /* Parent must be the issuer */ if (x509_name_cmp(&child->issuer, &parent->subject) != 0) { return -1; } /* Parent must have the basicConstraints CA bit set as a general rule */ need_ca_bit = 1; /* Exception: v1/v2 certificates that are locally trusted. */ if (top && parent->version < 3) { need_ca_bit = 0; } if (need_ca_bit && !parent->ca_istrue) { return -1; } if (need_ca_bit && mbedtls_x509_crt_check_key_usage(parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) { return -1; } return 0; } /* * Find a suitable parent for child in candidates, or return NULL. * * Here suitable is defined as: * 1. subject name matches child's issuer * 2. if necessary, the CA bit is set and key usage allows signing certs * 3. for trusted roots, the signature is correct * (for intermediates, the signature is checked and the result reported) * 4. pathlen constraints are satisfied * * If there's a suitable candidate which is also time-valid, return the first * such. Otherwise, return the first suitable candidate (or NULL if there is * none). * * The rationale for this rule is that someone could have a list of trusted * roots with two versions on the same root with different validity periods. * (At least one user reported having such a list and wanted it to just work.) * The reason we don't just require time-validity is that generally there is * only one version, and if it's expired we want the flags to state that * rather than NOT_TRUSTED, as would be the case if we required it here. * * The rationale for rule 3 (signature for trusted roots) is that users might * have two versions of the same CA with different keys in their list, and the * way we select the correct one is by checking the signature (as we don't * rely on key identifier extensions). (This is one way users might choose to * handle key rollover, another relies on self-issued certs, see [SIRO].) * * Arguments: * - [in] child: certificate for which we're looking for a parent * - [in] candidates: chained list of potential parents * - [out] r_parent: parent found (or NULL) * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top * of the chain, 0 otherwise * - [in] path_cnt: number of intermediates seen so far * - [in] self_cnt: number of self-signed intermediates seen so far * (will never be greater than path_cnt) * - [in-out] rs_ctx: context for restarting operations * * Return value: * - 0 on success * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise */ static int x509_crt_find_parent_in( mbedtls_x509_crt *child, mbedtls_x509_crt *candidates, mbedtls_x509_crt **r_parent, int *r_signature_is_good, int top, unsigned path_cnt, unsigned self_cnt, mbedtls_x509_crt_restart_ctx *rs_ctx, const mbedtls_x509_time *now) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *parent, *fallback_parent; int signature_is_good = 0, fallback_signature_is_good; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* did we have something in progress? */ if (rs_ctx != NULL && rs_ctx->parent != NULL) { /* restore saved state */ parent = rs_ctx->parent; fallback_parent = rs_ctx->fallback_parent; fallback_signature_is_good = rs_ctx->fallback_signature_is_good; /* clear saved state */ rs_ctx->parent = NULL; rs_ctx->fallback_parent = NULL; rs_ctx->fallback_signature_is_good = 0; /* resume where we left */ goto check_signature; } #endif fallback_parent = NULL; fallback_signature_is_good = 0; for (parent = candidates; parent != NULL; parent = parent->next) { /* basic parenting skills (name, CA bit, key usage) */ if (x509_crt_check_parent(child, parent, top) != 0) { continue; } /* +1 because stored max_pathlen is 1 higher that the actual value */ if (parent->max_pathlen > 0 && (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt) { continue; } /* Signature */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) check_signature: #endif ret = x509_crt_check_signature(child, parent, rs_ctx); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { /* save state */ rs_ctx->parent = parent; rs_ctx->fallback_parent = fallback_parent; rs_ctx->fallback_signature_is_good = fallback_signature_is_good; return ret; } #else (void) ret; #endif signature_is_good = ret == 0; if (top && !signature_is_good) { continue; } #if defined(MBEDTLS_HAVE_TIME_DATE) /* optional time check */ if (mbedtls_x509_time_cmp(&parent->valid_to, now) < 0 || /* past */ mbedtls_x509_time_cmp(&parent->valid_from, now) > 0) { /* future */ if (fallback_parent == NULL) { fallback_parent = parent; fallback_signature_is_good = signature_is_good; } continue; } #else ((void) now); #endif *r_parent = parent; *r_signature_is_good = signature_is_good; break; } if (parent == NULL) { *r_parent = fallback_parent; *r_signature_is_good = fallback_signature_is_good; } return 0; } /* * Find a parent in trusted CAs or the provided chain, or return NULL. * * Searches in trusted CAs first, and return the first suitable parent found * (see find_parent_in() for definition of suitable). * * Arguments: * - [in] child: certificate for which we're looking for a parent, followed * by a chain of possible intermediates * - [in] trust_ca: list of locally trusted certificates * - [out] parent: parent found (or NULL) * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) * - [in] self_cnt: number of self-signed certs in the chain so far * (will always be no greater than path_cnt) * - [in-out] rs_ctx: context for restarting operations * * Return value: * - 0 on success * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise */ static int x509_crt_find_parent( mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, mbedtls_x509_crt **parent, int *parent_is_trusted, int *signature_is_good, unsigned path_cnt, unsigned self_cnt, mbedtls_x509_crt_restart_ctx *rs_ctx, const mbedtls_x509_time *now) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *search_list; *parent_is_trusted = 1; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* restore then clear saved state if we have some stored */ if (rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) { *parent_is_trusted = rs_ctx->parent_is_trusted; rs_ctx->parent_is_trusted = -1; } #endif while (1) { search_list = *parent_is_trusted ? trust_ca : child->next; ret = x509_crt_find_parent_in(child, search_list, parent, signature_is_good, *parent_is_trusted, path_cnt, self_cnt, rs_ctx, now); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { /* save state */ rs_ctx->parent_is_trusted = *parent_is_trusted; return ret; } #else (void) ret; #endif /* stop here if found or already in second iteration */ if (*parent != NULL || *parent_is_trusted == 0) { break; } /* prepare second iteration */ *parent_is_trusted = 0; } /* extra precaution against mistakes in the caller */ if (*parent == NULL) { *parent_is_trusted = 0; *signature_is_good = 0; } return 0; } /* * Check if an end-entity certificate is locally trusted * * Currently we require such certificates to be self-signed (actually only * check for self-issued as self-signatures are not checked) */ static int x509_crt_check_ee_locally_trusted( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca) { mbedtls_x509_crt *cur; /* must be self-issued */ if (x509_name_cmp(&crt->issuer, &crt->subject) != 0) { return -1; } /* look for an exact match with trusted cert */ for (cur = trust_ca; cur != NULL; cur = cur->next) { if (crt->raw.len == cur->raw.len && memcmp(crt->raw.p, cur->raw.p, crt->raw.len) == 0) { return 0; } } /* too bad */ return -1; } /* * Build and verify a certificate chain * * Given a peer-provided list of certificates EE, C1, ..., Cn and * a list of trusted certs R1, ... Rp, try to build and verify a chain * EE, Ci1, ... Ciq [, Rj] * such that every cert in the chain is a child of the next one, * jumping to a trusted root as early as possible. * * Verify that chain and return it with flags for all issues found. * * Special cases: * - EE == Rj -> return a one-element list containing it * - EE, Ci1, ..., Ciq cannot be continued with a trusted root * -> return that chain with NOT_TRUSTED set on Ciq * * Tests for (aspects of) this function should include at least: * - trusted EE * - EE -> trusted root * - EE -> intermediate CA -> trusted root * - if relevant: EE untrusted * - if relevant: EE -> intermediate, untrusted * with the aspect under test checked at each relevant level (EE, int, root). * For some aspects longer chains are required, but usually length 2 is * enough (but length 1 is not in general). * * Arguments: * - [in] crt: the cert list EE, C1, ..., Cn * - [in] trust_ca: the trusted list R1, ..., Rp * - [in] ca_crl, profile: as in verify_with_profile() * - [out] ver_chain: the built and verified chain * Only valid when return value is 0, may contain garbage otherwise! * Restart note: need not be the same when calling again to resume. * - [in-out] rs_ctx: context for restarting operations * * Return value: * - non-zero if the chain could not be fully built and examined * - 0 is the chain was successfully built and examined, * even if it was found to be invalid */ static int x509_crt_verify_chain( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, mbedtls_x509_crt_verify_chain *ver_chain, mbedtls_x509_crt_restart_ctx *rs_ctx) { /* Don't initialize any of those variables here, so that the compiler can * catch potential issues with jumping ahead when restarting */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t *flags; mbedtls_x509_crt_verify_chain_item *cur; mbedtls_x509_crt *child; mbedtls_x509_crt *parent; int parent_is_trusted; int child_is_trusted; int signature_is_good; unsigned self_cnt; mbedtls_x509_crt *cur_trust_ca = NULL; mbedtls_x509_time now; #if defined(MBEDTLS_HAVE_TIME_DATE) if (mbedtls_x509_time_gmtime(mbedtls_time(NULL), &now) != 0) { return MBEDTLS_ERR_X509_FATAL_ERROR; } #endif #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* resume if we had an operation in progress */ if (rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent) { /* restore saved state */ *ver_chain = rs_ctx->ver_chain; /* struct copy */ self_cnt = rs_ctx->self_cnt; /* restore derived state */ cur = &ver_chain->items[ver_chain->len - 1]; child = cur->crt; flags = &cur->flags; goto find_parent; } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ child = crt; self_cnt = 0; parent_is_trusted = 0; child_is_trusted = 0; while (1) { /* Add certificate to the verification chain */ cur = &ver_chain->items[ver_chain->len]; cur->crt = child; cur->flags = 0; ver_chain->len++; flags = &cur->flags; #if defined(MBEDTLS_HAVE_TIME_DATE) /* Check time-validity (all certificates) */ if (mbedtls_x509_time_cmp(&child->valid_to, &now) < 0) { *flags |= MBEDTLS_X509_BADCERT_EXPIRED; } if (mbedtls_x509_time_cmp(&child->valid_from, &now) > 0) { *flags |= MBEDTLS_X509_BADCERT_FUTURE; } #endif /* Stop here for trusted roots (but not for trusted EE certs) */ if (child_is_trusted) { return 0; } /* Check signature algorithm: MD & PK algs */ if (x509_profile_check_md_alg(profile, child->sig_md) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_MD; } if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_PK; } /* Special case: EE certs that are locally trusted */ if (ver_chain->len == 1 && x509_crt_check_ee_locally_trusted(child, trust_ca) == 0) { return 0; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) find_parent: #endif /* Obtain list of potential trusted signers from CA callback, * or use statically provided list. */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) if (f_ca_cb != NULL) { mbedtls_x509_crt_free(ver_chain->trust_ca_cb_result); mbedtls_free(ver_chain->trust_ca_cb_result); ver_chain->trust_ca_cb_result = NULL; ret = f_ca_cb(p_ca_cb, child, &ver_chain->trust_ca_cb_result); if (ret != 0) { return MBEDTLS_ERR_X509_FATAL_ERROR; } cur_trust_ca = ver_chain->trust_ca_cb_result; } else #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ { ((void) f_ca_cb); ((void) p_ca_cb); cur_trust_ca = trust_ca; } /* Look for a parent in trusted CAs or up the chain */ ret = x509_crt_find_parent(child, cur_trust_ca, &parent, &parent_is_trusted, &signature_is_good, ver_chain->len - 1, self_cnt, rs_ctx, &now); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { /* save state */ rs_ctx->in_progress = x509_crt_rs_find_parent; rs_ctx->self_cnt = self_cnt; rs_ctx->ver_chain = *ver_chain; /* struct copy */ return ret; } #else (void) ret; #endif /* No parent? We're done here */ if (parent == NULL) { *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; return 0; } /* Count intermediate self-issued (not necessarily self-signed) certs. * These can occur with some strategies for key rollover, see [SIRO], * and should be excluded from max_pathlen checks. */ if (ver_chain->len != 1 && x509_name_cmp(&child->issuer, &child->subject) == 0) { self_cnt++; } /* path_cnt is 0 for the first intermediate CA, * and if parent is trusted it's not an intermediate CA */ if (!parent_is_trusted && ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA) { /* return immediately to avoid overflow the chain array */ return MBEDTLS_ERR_X509_FATAL_ERROR; } /* signature was checked while searching parent */ if (!signature_is_good) { *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; } /* check size of signing key */ if (x509_profile_check_key(profile, &parent->pk) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; } #if defined(MBEDTLS_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the given crt */ *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile, &now); #else (void) ca_crl; #endif /* prepare for next iteration */ child = parent; parent = NULL; child_is_trusted = parent_is_trusted; signature_is_good = 0; } } #ifdef _WIN32 #ifdef _MSC_VER #pragma comment(lib, "ws2_32.lib") #include #include #elif (defined(__MINGW32__) || defined(__MINGW64__)) && _WIN32_WINNT >= 0x0600 #include #include #else /* inet_pton() is not supported, fallback to software version */ #define MBEDTLS_TEST_SW_INET_PTON #endif #elif defined(__sun) /* Solaris requires -lsocket -lnsl for inet_pton() */ #elif defined(__has_include) #if __has_include() #include #endif #if __has_include() #include #endif #endif /* Use whether or not AF_INET6 is defined to indicate whether or not to use * the platform inet_pton() or a local implementation (below). The local * implementation may be used even in cases where the platform provides * inet_pton(), e.g. when there are different includes required and/or the * platform implementation requires dependencies on additional libraries. * Specifically, Windows requires custom includes and additional link * dependencies, and Solaris requires additional link dependencies. * Also, as a coarse heuristic, use the local implementation if the compiler * does not support __has_include(), or if the definition of AF_INET6 is not * provided by headers included (or not) via __has_include() above. * MBEDTLS_TEST_SW_INET_PTON is a bypass define to force testing of this code //no-check-names * despite having a platform that has inet_pton. */ #if !defined(AF_INET6) || defined(MBEDTLS_TEST_SW_INET_PTON) //no-check-names /* Definition located further below to possibly reduce compiler inlining */ static int x509_inet_pton_ipv4(const char *src, void *dst); #define li_cton(c, n) \ (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0)) static int x509_inet_pton_ipv6(const char *src, void *dst) { const unsigned char *p = (const unsigned char *) src; int nonzero_groups = 0, num_digits, zero_group_start = -1; uint16_t addr[8]; do { /* note: allows excess leading 0's, e.g. 1:0002:3:... */ uint16_t group = num_digits = 0; for (uint8_t digit; num_digits < 4; num_digits++) { if (li_cton(*p, digit) == 0) { break; } group = (group << 4) | digit; p++; } if (num_digits != 0) { MBEDTLS_PUT_UINT16_BE(group, addr, nonzero_groups); nonzero_groups++; if (*p == '\0') { break; } else if (*p == '.') { /* Don't accept IPv4 too early or late */ if ((nonzero_groups == 0 && zero_group_start == -1) || nonzero_groups >= 7) { break; } /* Walk back to prior ':', then parse as IPv4-mapped */ int steps = 4; do { p--; steps--; } while (*p != ':' && steps > 0); if (*p != ':') { break; } p++; nonzero_groups--; if (x509_inet_pton_ipv4((const char *) p, addr + nonzero_groups) != 0) { break; } nonzero_groups += 2; p = (const unsigned char *) ""; break; } else if (*p != ':') { return -1; } } else { /* Don't accept a second zero group or an invalid delimiter */ if (zero_group_start != -1 || *p != ':') { return -1; } zero_group_start = nonzero_groups; /* Accept a zero group at start, but it has to be a double colon */ if (zero_group_start == 0 && *++p != ':') { return -1; } if (p[1] == '\0') { ++p; break; } } ++p; } while (nonzero_groups < 8); if (*p != '\0') { return -1; } if (zero_group_start != -1) { if (nonzero_groups > 6) { return -1; } int zero_groups = 8 - nonzero_groups; int groups_after_zero = nonzero_groups - zero_group_start; /* Move the non-zero part to after the zeroes */ if (groups_after_zero) { memmove(addr + zero_group_start + zero_groups, addr + zero_group_start, groups_after_zero * sizeof(*addr)); } memset(addr + zero_group_start, 0, zero_groups * sizeof(*addr)); } else { if (nonzero_groups != 8) { return -1; } } memcpy(dst, addr, sizeof(addr)); return 0; } static int x509_inet_pton_ipv4(const char *src, void *dst) { const unsigned char *p = (const unsigned char *) src; uint8_t *res = (uint8_t *) dst; uint8_t digit, num_digits = 0; uint8_t num_octets = 0; uint16_t octet; do { octet = num_digits = 0; do { digit = *p - '0'; if (digit > 9) { break; } /* Don't allow leading zeroes. These might mean octal format, * which this implementation does not support. */ if (octet == 0 && num_digits > 0) { return -1; } octet = octet * 10 + digit; num_digits++; p++; } while (num_digits < 3); if (octet >= 256 || num_digits > 3 || num_digits == 0) { return -1; } *res++ = (uint8_t) octet; num_octets++; } while (num_octets < 4 && *p++ == '.'); return num_octets == 4 && *p == '\0' ? 0 : -1; } #else static int x509_inet_pton_ipv6(const char *src, void *dst) { return inet_pton(AF_INET6, src, dst) == 1 ? 0 : -1; } static int x509_inet_pton_ipv4(const char *src, void *dst) { return inet_pton(AF_INET, src, dst) == 1 ? 0 : -1; } #endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst) { return strchr(cn, ':') == NULL ? x509_inet_pton_ipv4(cn, dst) == 0 ? 4 : 0 : x509_inet_pton_ipv6(cn, dst) == 0 ? 16 : 0; } /* * Check for CN match */ static int x509_crt_check_cn(const mbedtls_x509_buf *name, const char *cn, size_t cn_len) { /* try exact match */ if (name->len == cn_len && x509_memcasecmp(cn, name->p, cn_len) == 0) { return 0; } /* try wildcard match */ if (x509_check_wildcard(cn, name) == 0) { return 0; } return -1; } static int x509_crt_check_san_ip(const mbedtls_x509_sequence *san, const char *cn, size_t cn_len) { uint32_t ip[4]; cn_len = mbedtls_x509_crt_parse_cn_inet_pton(cn, ip); if (cn_len == 0) { return -1; } for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { const unsigned char san_type = (unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK; if (san_type == MBEDTLS_X509_SAN_IP_ADDRESS && cur->buf.len == cn_len && memcmp(cur->buf.p, ip, cn_len) == 0) { return 0; } } return -1; } static int x509_crt_check_san_uri(const mbedtls_x509_sequence *san, const char *cn, size_t cn_len) { for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { const unsigned char san_type = (unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK; if (san_type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER && cur->buf.len == cn_len && memcmp(cur->buf.p, cn, cn_len) == 0) { return 0; } } return -1; } /* * Check for SAN match, see RFC 5280 Section 4.2.1.6 */ static int x509_crt_check_san(const mbedtls_x509_sequence *san, const char *cn, size_t cn_len) { int san_ip = 0; int san_uri = 0; /* Prioritize DNS name over other subtypes due to popularity */ for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { switch ((unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) { case MBEDTLS_X509_SAN_DNS_NAME: if (x509_crt_check_cn(&cur->buf, cn, cn_len) == 0) { return 0; } break; case MBEDTLS_X509_SAN_IP_ADDRESS: san_ip = 1; break; case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: san_uri = 1; break; /* (We may handle other types here later.) */ default: /* Unrecognized type */ break; } } if (san_ip) { if (x509_crt_check_san_ip(san, cn, cn_len) == 0) { return 0; } } if (san_uri) { if (x509_crt_check_san_uri(san, cn, cn_len) == 0) { return 0; } } return -1; } /* * Verify the requested CN - only call this if cn is not NULL! */ static void x509_crt_verify_name(const mbedtls_x509_crt *crt, const char *cn, uint32_t *flags) { const mbedtls_x509_name *name; size_t cn_len = strlen(cn); if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { if (x509_crt_check_san(&crt->subject_alt_names, cn, cn_len) == 0) { return; } } else { for (name = &crt->subject; name != NULL; name = name->next) { if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 && x509_crt_check_cn(&name->val, cn, cn_len) == 0) { return; } } } *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; } /* * Merge the flags for all certs in the chain, after calling callback */ static int x509_crt_merge_flags_with_cb( uint32_t *flags, const mbedtls_x509_crt_verify_chain *ver_chain, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned i; uint32_t cur_flags; const mbedtls_x509_crt_verify_chain_item *cur; for (i = ver_chain->len; i != 0; --i) { cur = &ver_chain->items[i-1]; cur_flags = cur->flags; if (NULL != f_vrfy) { if ((ret = f_vrfy(p_vrfy, cur->crt, (int) i-1, &cur_flags)) != 0) { return ret; } } *flags |= cur_flags; } return 0; } /* * Verify the certificate validity, with profile, restartable version * * This function: * - checks the requested CN (if any) * - checks the type and size of the EE cert's key, * as that isn't done as part of chain building/verification currently * - builds and verifies the chain * - then calls the callback and merges the flags * * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb` * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the * verification routine to search for trusted signers, and CRLs will * be disabled. Otherwise, `trust_ca` will be used as the static list * of trusted signers, and `ca_crl` will be use as the static list * of CRLs. */ static int x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_pk_type_t pk_type; mbedtls_x509_crt_verify_chain ver_chain; uint32_t ee_flags; *flags = 0; ee_flags = 0; x509_crt_verify_chain_reset(&ver_chain); if (profile == NULL) { ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; goto exit; } /* check name if requested */ if (cn != NULL) { x509_crt_verify_name(crt, cn, &ee_flags); } /* Check the type and size of the key */ pk_type = mbedtls_pk_get_type(&crt->pk); if (x509_profile_check_pk_alg(profile, pk_type) != 0) { ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; } if (x509_profile_check_key(profile, &crt->pk) != 0) { ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; } /* Check the chain */ ret = x509_crt_verify_chain(crt, trust_ca, ca_crl, f_ca_cb, p_ca_cb, profile, &ver_chain, rs_ctx); if (ret != 0) { goto exit; } /* Merge end-entity flags */ ver_chain.items[0].flags |= ee_flags; /* Build final flags, calling callback on the way if any */ ret = x509_crt_merge_flags_with_cb(flags, &ver_chain, f_vrfy, p_vrfy); exit: #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) mbedtls_x509_crt_free(ver_chain.trust_ca_cb_result); mbedtls_free(ver_chain.trust_ca_cb_result); ver_chain.trust_ca_cb_result = NULL; #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { mbedtls_x509_crt_restart_free(rs_ctx); } #endif /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by * the SSL module for authmode optional, but non-zero return from the * callback means a fatal error so it shouldn't be ignored */ if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { ret = MBEDTLS_ERR_X509_FATAL_ERROR; } if (ret != 0) { *flags = (uint32_t) -1; return ret; } if (*flags != 0) { return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED; } return 0; } /* * Verify the certificate validity (default profile, not restartable) */ int mbedtls_x509_crt_verify(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, NULL, NULL, &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy, NULL); } /* * Verify the certificate validity (user-chosen profile, not restartable) */ int mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, NULL, NULL, profile, cn, flags, f_vrfy, p_vrfy, NULL); } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /* * Verify the certificate validity (user-chosen profile, CA callback, * not restartable). */ int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { return x509_crt_verify_restartable_ca_cb(crt, NULL, NULL, f_ca_cb, p_ca_cb, profile, cn, flags, f_vrfy, p_vrfy, NULL); } #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ int mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx) { return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, NULL, NULL, profile, cn, flags, f_vrfy, p_vrfy, rs_ctx); } /* * Initialize a certificate chain */ void mbedtls_x509_crt_init(mbedtls_x509_crt *crt) { memset(crt, 0, sizeof(mbedtls_x509_crt)); } /* * Unallocate all certificate data */ void mbedtls_x509_crt_free(mbedtls_x509_crt *crt) { mbedtls_x509_crt *cert_cur = crt; mbedtls_x509_crt *cert_prv; while (cert_cur != NULL) { mbedtls_pk_free(&cert_cur->pk); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_free(cert_cur->sig_opts); #endif mbedtls_asn1_free_named_data_list_shallow(cert_cur->issuer.next); mbedtls_asn1_free_named_data_list_shallow(cert_cur->subject.next); mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next); mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next); mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next); mbedtls_asn1_sequence_free(cert_cur->authority_key_id.authorityCertIssuer.next); if (cert_cur->raw.p != NULL && cert_cur->own_buffer) { mbedtls_zeroize_and_free(cert_cur->raw.p, cert_cur->raw.len); } cert_prv = cert_cur; cert_cur = cert_cur->next; mbedtls_platform_zeroize(cert_prv, sizeof(mbedtls_x509_crt)); if (cert_prv != crt) { mbedtls_free(cert_prv); } } } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* * Initialize a restart context */ void mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx) { mbedtls_pk_restart_init(&ctx->pk); ctx->parent = NULL; ctx->fallback_parent = NULL; ctx->fallback_signature_is_good = 0; ctx->parent_is_trusted = -1; ctx->in_progress = x509_crt_rs_none; ctx->self_cnt = 0; x509_crt_verify_chain_reset(&ctx->ver_chain); } /* * Free the components of a restart context */ void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_pk_restart_free(&ctx->pk); mbedtls_x509_crt_restart_init(ctx); } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ int mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt) { if ((crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) != 0) { return crt->MBEDTLS_PRIVATE(ca_istrue); } return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ webfakes/src/mbedtls/library/psa_crypto_its.h0000644000176200001440000001456414740737024021163 0ustar liggesusers/** \file psa_crypto_its.h * \brief Interface of trusted storage that crypto is built on. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ITS_H #define PSA_CRYPTO_ITS_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** \brief Flags used when creating a data entry */ typedef uint32_t psa_storage_create_flags_t; /** \brief A type for UIDs used for identifying data */ typedef uint64_t psa_storage_uid_t; #define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ #define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ /** * \brief A container for metadata associated with a specific uid */ struct psa_storage_info_t { uint32_t size; /**< The size of the data associated with a uid **/ psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ }; /** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ #define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) #define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ #define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ /** * \brief create a new or modify an existing uid/value pair * * \param[in] uid the identifier for the data * \param[in] data_length The size in bytes of the data in `p_data` * \param[in] p_data A buffer containing the data * \param[in] create_flags The flags that the data will be stored with * * \return A status indicating the success/failure of the operation * * \retval #PSA_SUCCESS The operation completed successfully * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_FLAG_WRITE_ONCE * \retval #PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid * \retval #PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`) * is invalid, for example is `NULL` or references memory the caller cannot access */ psa_status_t psa_its_set(psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags); /** * \brief Retrieve the value associated with a provided uid * * \param[in] uid The uid value * \param[in] data_offset The starting offset of the data requested * \param[in] data_length the amount of data requested (and the minimum allocated size of the `p_data` buffer) * \param[out] p_data The buffer where the data will be placed upon successful completion * \param[out] p_data_length The amount of data returned in the p_data buffer * * * \return A status indicating the success/failure of the operation * * \retval #PSA_SUCCESS The operation completed successfully * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) * \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`) * is invalid. For example is `NULL` or references memory the caller cannot access. * In addition, this can also happen if an invalid offset was provided. */ psa_status_t psa_its_get(psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data, size_t *p_data_length); /** * \brief Retrieve the metadata about the provided uid * * \param[in] uid The uid value * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata * * \return A status indicating the success/failure of the operation * * \retval #PSA_SUCCESS The operation completed successfully * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage * \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`) * is invalid, for example is `NULL` or references memory the caller cannot access */ psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info); /** * \brief Remove the provided key and its associated data from the storage * * \param[in] uid The uid value * * \return A status indicating the success/failure of the operation * * \retval #PSA_SUCCESS The operation completed successfully * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_FLAG_WRITE_ONCE * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) */ psa_status_t psa_its_remove(psa_storage_uid_t uid); #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_ITS_H */ webfakes/src/mbedtls/library/dhm.c0000644000176200001440000004653714740737024016671 0ustar liggesusers/* * Diffie-Hellman-Merkle key exchange * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this implementation * of the Diffie-Hellman-Merkle algorithm: * * [1] Handbook of Applied Cryptography - 1997, Chapter 12 * Menezes, van Oorschot and Vanstone * */ #include "common.h" #if defined(MBEDTLS_DHM_C) #include "mbedtls/dhm.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #endif #include "mbedtls/platform.h" #if !defined(MBEDTLS_DHM_ALT) /* * helper to validate the mbedtls_mpi size and import it */ static int dhm_read_bignum(mbedtls_mpi *X, unsigned char **p, const unsigned char *end) { int ret, n; if (end - *p < 2) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } n = MBEDTLS_GET_UINT16_BE(*p, 0); (*p) += 2; if ((size_t) (end - *p) < (size_t) n) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret); } (*p) += n; return 0; } /* * Verify sanity of parameter with regards to P * * Parameter should be: 2 <= public_param <= P - 2 * * This means that we need to return an error if * public_param < 2 or public_param > P-2 * * For more information on the attack, see: * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 */ static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P) { mbedtls_mpi U; int ret = 0; mbedtls_mpi_init(&U); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2)); if (mbedtls_mpi_cmp_int(param, 2) < 0 || mbedtls_mpi_cmp_mpi(param, &U) > 0) { ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } cleanup: mbedtls_mpi_free(&U); return ret; } void mbedtls_dhm_init(mbedtls_dhm_context *ctx) { memset(ctx, 0, sizeof(mbedtls_dhm_context)); } size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx) { return mbedtls_mpi_bitlen(&ctx->P); } size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx) { return mbedtls_mpi_size(&ctx->P); } int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx, mbedtls_dhm_parameter param, mbedtls_mpi *dest) { const mbedtls_mpi *src = NULL; switch (param) { case MBEDTLS_DHM_PARAM_P: src = &ctx->P; break; case MBEDTLS_DHM_PARAM_G: src = &ctx->G; break; case MBEDTLS_DHM_PARAM_X: src = &ctx->X; break; case MBEDTLS_DHM_PARAM_GX: src = &ctx->GX; break; case MBEDTLS_DHM_PARAM_GY: src = &ctx->GY; break; case MBEDTLS_DHM_PARAM_K: src = &ctx->K; break; default: return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } return mbedtls_mpi_copy(dest, src); } /* * Parse the ServerKeyExchange parameters */ int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx, unsigned char **p, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 || (ret = dhm_read_bignum(&ctx->G, p, end)) != 0 || (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) { return ret; } if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) { return ret; } return 0; } /* * Pick a random R in the range [2, M-2] for blinding or key generation. */ static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1)); cleanup: return ret; } static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = 0; if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if (x_size < 0) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) { MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng)); } else { /* Generate X as large as possible ( <= P - 2 ) */ ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng); if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED; } if (ret != 0) { return ret; } } /* * Calculate GX = G^X mod P */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X, &ctx->P, &ctx->RP)); if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) { return ret; } cleanup: return ret; } /* * Setup and write the ServerKeyExchange parameters */ int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; size_t n1, n2, n3; unsigned char *p; ret = dhm_make_common(ctx, x_size, f_rng, p_rng); if (ret != 0) { goto cleanup; } /* * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are * not required". We omit leading zeros for compactness. */ #define DHM_MPI_EXPORT(X, n) \ do { \ MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X), \ p + 2, \ (n))); \ *p++ = MBEDTLS_BYTE_1(n); \ *p++ = MBEDTLS_BYTE_0(n); \ p += (n); \ } while (0) n1 = mbedtls_mpi_size(&ctx->P); n2 = mbedtls_mpi_size(&ctx->G); n3 = mbedtls_mpi_size(&ctx->GX); p = output; DHM_MPI_EXPORT(&ctx->P, n1); DHM_MPI_EXPORT(&ctx->G, n2); DHM_MPI_EXPORT(&ctx->GX, n3); *olen = (size_t) (p - output); cleanup: if (ret != 0 && ret > -128) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret); } return ret; } /* * Set prime modulus and generator */ int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx, const mbedtls_mpi *P, const mbedtls_mpi *G) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 || (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret); } return 0; } /* * Import the peer's public value G^Y */ int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret); } return 0; } /* * Create own private value X and export G^X */ int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } ret = dhm_make_common(ctx, x_size, f_rng, p_rng); if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) { return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED; } if (ret != 0) { goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen)); cleanup: if (ret != 0 && ret > -128) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret); } return ret; } /* * Use the blinding method and optimisation suggested in section 10 of: * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer * Berlin Heidelberg, 1996. p. 104-113. */ static int dhm_update_blinding(mbedtls_dhm_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; mbedtls_mpi R; mbedtls_mpi_init(&R); /* * Don't use any blinding the first time a particular X is used, * but remember it to use blinding next time. */ if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1)); return 0; } /* * Ok, we need blinding. Can we re-use existing values? * If yes, just update them by squaring them. */ if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P)); return 0; } /* * We need to generate blinding values from scratch */ /* Vi = random( 2, P-2 ) */ MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng)); /* Vf = Vi^-X mod P * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod), * then elevate to the Xth power. */ MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP)); cleanup: mbedtls_mpi_free(&R); return ret; } /* * Derive and export the shared secret (G^Y)^X mod P */ int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx, unsigned char *output, size_t output_size, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi GYb; if (f_rng == NULL) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if (output_size < mbedtls_dhm_get_len(ctx)) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) { return ret; } mbedtls_mpi_init(&GYb); /* Blind peer's value */ MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P)); /* Do modular exponentiation */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X, &ctx->P, &ctx->RP)); /* Unblind secret value */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P)); /* Output the secret without any leading zero byte. This is mandatory * for TLS per RFC 5246 §8.1.2. */ *olen = mbedtls_mpi_size(&ctx->K); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen)); cleanup: mbedtls_mpi_free(&GYb); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret); } return 0; } /* * Free the components of a DHM key */ void mbedtls_dhm_free(mbedtls_dhm_context *ctx) { if (ctx == NULL) { return; } mbedtls_mpi_free(&ctx->pX); mbedtls_mpi_free(&ctx->Vf); mbedtls_mpi_free(&ctx->Vi); mbedtls_mpi_free(&ctx->RP); mbedtls_mpi_free(&ctx->K); mbedtls_mpi_free(&ctx->GY); mbedtls_mpi_free(&ctx->GX); mbedtls_mpi_free(&ctx->X); mbedtls_mpi_free(&ctx->G); mbedtls_mpi_free(&ctx->P); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context)); } #if defined(MBEDTLS_ASN1_PARSE_C) /* * Parse DHM parameters */ int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *p, *end; #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_context pem; #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init(&pem); /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN DH PARAMETERS-----", "-----END DH PARAMETERS-----", dhmin, NULL, 0, &dhminlen); } if (ret == 0) { /* * Was PEM encoded */ dhminlen = pem.buflen; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { goto exit; } p = (ret == 0) ? pem.buf : (unsigned char *) dhmin; #else p = (unsigned char *) dhmin; #endif /* MBEDTLS_PEM_PARSE_C */ end = p + dhminlen; /* * DHParams ::= SEQUENCE { * prime INTEGER, -- P * generator INTEGER, -- g * privateValueLength INTEGER OPTIONAL * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret); goto exit; } end = p + len; if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 || (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret); goto exit; } if (p != end) { /* This might be the optional privateValueLength. * If so, we can cleanly discard it */ mbedtls_mpi rec; mbedtls_mpi_init(&rec); ret = mbedtls_asn1_get_mpi(&p, end, &rec); mbedtls_mpi_free(&rec); if (ret != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret); goto exit; } if (p != end) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); goto exit; } } ret = 0; exit: #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_free(&pem); #endif if (ret != 0) { mbedtls_dhm_free(dhm); } return ret; } #if defined(MBEDTLS_FS_IO) /* * Load all data from a file into a given buffer. * * The file is expected to contain either PEM or DER encoded data. * A terminating null byte is always appended. It is included in the announced * length only if the data looks like it is PEM encoded. */ static int load_file(const char *path, unsigned char **buf, size_t *n) { FILE *f; long size; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_DHM_FILE_IO_ERROR; } /* The data loaded here is public, so don't bother disabling buffering. */ fseek(f, 0, SEEK_END); if ((size = ftell(f)) == -1) { fclose(f); return MBEDTLS_ERR_DHM_FILE_IO_ERROR; } fseek(f, 0, SEEK_SET); *n = (size_t) size; if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { fclose(f); return MBEDTLS_ERR_DHM_ALLOC_FAILED; } if (fread(*buf, 1, *n, f) != *n) { fclose(f); mbedtls_zeroize_and_free(*buf, *n + 1); return MBEDTLS_ERR_DHM_FILE_IO_ERROR; } fclose(f); (*buf)[*n] = '\0'; if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { ++*n; } return 0; } /* * Load and parse DHM parameters */ int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_dhm_parse_dhm(dhm, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_ASN1_PARSE_C */ #endif /* MBEDTLS_DHM_ALT */ #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PEM_PARSE_C) static const char mbedtls_test_dhm_params[] = "-----BEGIN DH PARAMETERS-----\r\n" "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" "-----END DH PARAMETERS-----\r\n"; #else /* MBEDTLS_PEM_PARSE_C */ static const char mbedtls_test_dhm_params[] = { 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44, 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d, 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3, 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1, 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18, 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a, 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1, 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6, 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64, 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8, 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f, 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 }; #endif /* MBEDTLS_PEM_PARSE_C */ static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params); /* * Checkup routine */ int mbedtls_dhm_self_test(int verbose) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_dhm_context dhm; mbedtls_dhm_init(&dhm); if (verbose != 0) { mbedtls_printf(" DHM parameter load: "); } if ((ret = mbedtls_dhm_parse_dhm(&dhm, (const unsigned char *) mbedtls_test_dhm_params, mbedtls_test_dhm_params_len)) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n\n"); } exit: mbedtls_dhm_free(&dhm); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_DHM_C */ webfakes/src/mbedtls/library/psa_crypto_aead.c0000644000176200001440000005442614740737024021252 0ustar liggesusers/* * PSA AEAD entry points */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include "psa_crypto_aead.h" #include "psa_crypto_core.h" #include "psa_crypto_cipher.h" #include #include "mbedtls/platform.h" #include "mbedtls/ccm.h" #include "mbedtls/chachapoly.h" #include "mbedtls/cipher.h" #include "mbedtls/gcm.h" #include "mbedtls/error.h" static psa_status_t psa_aead_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_cipher_id_t cipher_id; mbedtls_cipher_mode_t mode; size_t key_bits = attributes->bits; (void) key_buffer_size; status = mbedtls_cipher_values_from_psa(alg, attributes->type, &key_bits, &mode, &cipher_id); if (status != PSA_SUCCESS) { return status; } switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): operation->alg = PSA_ALG_CCM; /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. * The call to mbedtls_ccm_encrypt_and_tag or * mbedtls_ccm_auth_decrypt will validate the tag length. */ if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { return PSA_ERROR_INVALID_ARGUMENT; } mbedtls_ccm_init(&operation->ctx.ccm); status = mbedtls_to_psa_error( mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id, key_buffer, (unsigned int) key_bits)); if (status != PSA_SUCCESS) { return status; } break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): operation->alg = PSA_ALG_GCM; /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. * The call to mbedtls_gcm_crypt_and_tag or * mbedtls_gcm_auth_decrypt will validate the tag length. */ if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { return PSA_ERROR_INVALID_ARGUMENT; } mbedtls_gcm_init(&operation->ctx.gcm); status = mbedtls_to_psa_error( mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id, key_buffer, (unsigned int) key_bits)); if (status != PSA_SUCCESS) { return status; } break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): operation->alg = PSA_ALG_CHACHA20_POLY1305; /* We only support the default tag length. */ if (alg != PSA_ALG_CHACHA20_POLY1305) { return PSA_ERROR_NOT_SUPPORTED; } mbedtls_chachapoly_init(&operation->ctx.chachapoly); status = mbedtls_to_psa_error( mbedtls_chachapoly_setkey(&operation->ctx.chachapoly, key_buffer)); if (status != PSA_SUCCESS) { return status; } break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ default: (void) status; (void) key_buffer; return PSA_ERROR_NOT_SUPPORTED; } operation->key_type = psa_get_key_type(attributes); operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); return PSA_SUCCESS; } psa_status_t mbedtls_psa_aead_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; uint8_t *tag; status = psa_aead_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } /* For all currently supported modes, the tag is at the end of the * ciphertext. */ if (ciphertext_size < (plaintext_length + operation.tag_length)) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } tag = ciphertext + plaintext_length; #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation.alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm, plaintext_length, nonce, nonce_length, additional_data, additional_data_length, plaintext, ciphertext, tag, operation.tag_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation.alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm, MBEDTLS_GCM_ENCRYPT, plaintext_length, nonce, nonce_length, additional_data, additional_data_length, plaintext, ciphertext, operation.tag_length, tag)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { if (operation.tag_length != 16) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = mbedtls_to_psa_error( mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly, plaintext_length, nonce, additional_data, additional_data_length, plaintext, ciphertext, tag)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) tag; (void) nonce; (void) nonce_length; (void) additional_data; (void) additional_data_length; (void) plaintext; return PSA_ERROR_NOT_SUPPORTED; } if (status == PSA_SUCCESS) { *ciphertext_length = plaintext_length + operation.tag_length; } exit: mbedtls_psa_aead_abort(&operation); return status; } /* Locate the tag in a ciphertext buffer containing the encrypted data * followed by the tag. Return the length of the part preceding the tag in * *plaintext_length. This is the size of the plaintext in modes where * the encrypted data has the same size as the plaintext, such as * CCM and GCM. */ static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length, const uint8_t *ciphertext, size_t ciphertext_length, size_t plaintext_size, const uint8_t **p_tag) { size_t payload_length; if (tag_length > ciphertext_length) { return PSA_ERROR_INVALID_ARGUMENT; } payload_length = ciphertext_length - tag_length; if (payload_length > plaintext_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } *p_tag = ciphertext + payload_length; return PSA_SUCCESS; } psa_status_t mbedtls_psa_aead_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; const uint8_t *tag = NULL; status = psa_aead_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } status = psa_aead_unpadded_locate_tag(operation.tag_length, ciphertext, ciphertext_length, plaintext_size, &tag); if (status != PSA_SUCCESS) { goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation.alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_auth_decrypt(&operation.ctx.ccm, ciphertext_length - operation.tag_length, nonce, nonce_length, additional_data, additional_data_length, ciphertext, plaintext, tag, operation.tag_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation.alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_auth_decrypt(&operation.ctx.gcm, ciphertext_length - operation.tag_length, nonce, nonce_length, additional_data, additional_data_length, tag, operation.tag_length, ciphertext, plaintext)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { if (operation.tag_length != 16) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = mbedtls_to_psa_error( mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly, ciphertext_length - operation.tag_length, nonce, additional_data, additional_data_length, tag, ciphertext, plaintext)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) nonce; (void) nonce_length; (void) additional_data; (void) additional_data_length; (void) plaintext; return PSA_ERROR_NOT_SUPPORTED; } if (status == PSA_SUCCESS) { *plaintext_length = ciphertext_length - operation.tag_length; } exit: mbedtls_psa_aead_abort(&operation); if (status == PSA_SUCCESS) { *plaintext_length = ciphertext_length - operation.tag_length; } return status; } /* Set the key and algorithm for a multipart authenticated encryption * operation. */ psa_status_t mbedtls_psa_aead_encrypt_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_aead_setup(operation, attributes, key_buffer, key_buffer_size, alg); if (status == PSA_SUCCESS) { operation->is_encrypt = 1; } return status; } /* Set the key and algorithm for a multipart authenticated decryption * operation. */ psa_status_t mbedtls_psa_aead_decrypt_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_aead_setup(operation, attributes, key_buffer, key_buffer_size, alg); if (status == PSA_SUCCESS) { operation->is_encrypt = 0; } return status; } /* Set a nonce for the multipart AEAD operation*/ psa_status_t mbedtls_psa_aead_set_nonce( mbedtls_psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation->alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_starts(&operation->ctx.gcm, operation->is_encrypt ? MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT, nonce, nonce_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_starts(&operation->ctx.ccm, operation->is_encrypt ? MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT, nonce, nonce_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to * allocate a buffer in the operation, copy the nonce to it and pad * it, so for now check the nonce is 12 bytes, as * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the * passed in buffer. */ if (nonce_length != 12) { return PSA_ERROR_INVALID_ARGUMENT; } status = mbedtls_to_psa_error( mbedtls_chachapoly_starts(&operation->ctx.chachapoly, nonce, operation->is_encrypt ? MBEDTLS_CHACHAPOLY_ENCRYPT : MBEDTLS_CHACHAPOLY_DECRYPT)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) operation; (void) nonce; (void) nonce_length; return PSA_ERROR_NOT_SUPPORTED; } return status; } /* Declare the lengths of the message and additional data for AEAD. */ psa_status_t mbedtls_psa_aead_set_lengths( mbedtls_psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { return mbedtls_to_psa_error( mbedtls_ccm_set_lengths(&operation->ctx.ccm, ad_length, plaintext_length, operation->tag_length)); } #else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ (void) operation; (void) ad_length; (void) plaintext_length; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ return PSA_SUCCESS; } /* Pass additional data to an active multipart AEAD operation. */ psa_status_t mbedtls_psa_aead_update_ad( mbedtls_psa_aead_operation_t *operation, const uint8_t *input, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation->alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { status = mbedtls_to_psa_error( mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly, input, input_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) operation; (void) input; (void) input_length; return PSA_ERROR_NOT_SUPPORTED; } return status; } /* Encrypt or decrypt a message fragment in an active multipart AEAD * operation.*/ psa_status_t mbedtls_psa_aead_update( mbedtls_psa_aead_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { size_t update_output_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; update_output_length = input_length; #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation->alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_update(&operation->ctx.gcm, input, input_length, output, output_size, &update_output_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { if (output_size < input_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = mbedtls_to_psa_error( mbedtls_ccm_update(&operation->ctx.ccm, input, input_length, output, output_size, &update_output_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { if (output_size < input_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = mbedtls_to_psa_error( mbedtls_chachapoly_update(&operation->ctx.chachapoly, input_length, input, output)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) operation; (void) input; (void) output; (void) output_size; return PSA_ERROR_NOT_SUPPORTED; } if (status == PSA_SUCCESS) { *output_length = update_output_length; } return status; } /* Finish encrypting a message in a multipart AEAD operation. */ psa_status_t mbedtls_psa_aead_finish( mbedtls_psa_aead_operation_t *operation, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag, size_t tag_size, size_t *tag_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t finish_output_size = 0; if (tag_size < operation->tag_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation->alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_finish(&operation->ctx.gcm, ciphertext, ciphertext_size, ciphertext_length, tag, operation->tag_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { /* tag must be big enough to store a tag of size passed into set * lengths. */ if (tag_size < operation->tag_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = mbedtls_to_psa_error( mbedtls_ccm_finish(&operation->ctx.ccm, tag, operation->tag_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { /* Belt and braces. Although the above tag_size check should have * already done this, if we later start supporting smaller tag sizes * for chachapoly, then passing a tag buffer smaller than 16 into here * could cause a buffer overflow, so better safe than sorry. */ if (tag_size < 16) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = mbedtls_to_psa_error( mbedtls_chachapoly_finish(&operation->ctx.chachapoly, tag)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) ciphertext; (void) ciphertext_size; (void) ciphertext_length; (void) tag; (void) tag_size; (void) tag_length; return PSA_ERROR_NOT_SUPPORTED; } if (status == PSA_SUCCESS) { /* This will be zero for all supported algorithms currently, but left * here for future support. */ *ciphertext_length = finish_output_size; *tag_length = operation->tag_length; } return status; } /* Abort an AEAD operation */ psa_status_t mbedtls_psa_aead_abort( mbedtls_psa_aead_operation_t *operation) { switch (operation->alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) case PSA_ALG_CCM: mbedtls_ccm_free(&operation->ctx.ccm); break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) case PSA_ALG_GCM: mbedtls_gcm_free(&operation->ctx.gcm); break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) case PSA_ALG_CHACHA20_POLY1305: mbedtls_chachapoly_free(&operation->ctx.chachapoly); break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ } operation->is_encrypt = 0; return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/hmac_drbg.c0000644000176200001440000004503714740737024020021 0ustar liggesusers/* * HMAC_DRBG implementation (NIST SP 800-90) * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The NIST SP 800-90A DRBGs are described in the following publication. * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf * References below are based on rev. 1 (January 2012). */ #include "common.h" #if defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_FS_IO) #include #endif #include "mbedtls/platform.h" /* * HMAC_DRBG context initialization */ void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx) { memset(ctx, 0, sizeof(mbedtls_hmac_drbg_context)); ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; } /* * HMAC_DRBG update, using optional additional data (10.1.2.2) */ int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t add_len) { size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info); unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1; unsigned char sep[1]; unsigned char K[MBEDTLS_MD_MAX_SIZE]; int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA; for (sep[0] = 0; sep[0] < rounds; sep[0]++) { /* Step 1 or 4 */ if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, ctx->V, md_len)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, sep, 1)) != 0) { goto exit; } if (rounds == 2) { if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, additional, add_len)) != 0) { goto exit; } } if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, K)) != 0) { goto exit; } /* Step 2 or 5 */ if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, K, md_len)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, ctx->V, md_len)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) { goto exit; } } exit: mbedtls_platform_zeroize(K, sizeof(K)); return ret; } /* * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) */ int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx, const mbedtls_md_info_t *md_info, const unsigned char *data, size_t data_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) { return ret; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif /* * Set initial working state. * Use the V memory location, which is currently all 0, to initialize the * MD context with an all-zero key. Then set V to its initial value. */ if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, mbedtls_md_get_size(md_info))) != 0) { return ret; } memset(ctx->V, 0x01, mbedtls_md_get_size(md_info)); if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) { return ret; } return 0; } /* * Internal function used both for seeding and reseeding the DRBG. * Comments starting with arabic numbers refer to section 10.1.2.4 * of SP800-90A, while roman numbers refer to section 9.2. */ static int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t len, int use_nonce) { unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; size_t seedlen = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; { size_t total_entropy_len; if (use_nonce == 0) { total_entropy_len = ctx->entropy_len; } else { total_entropy_len = ctx->entropy_len * 3 / 2; } /* III. Check input length */ if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT || total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) { return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; } } memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT); /* IV. Gather entropy_len bytes of entropy for the seed */ if ((ret = ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) != 0) { return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED; } seedlen += ctx->entropy_len; /* For initial seeding, allow adding of nonce generated * from the entropy source. See Sect 8.6.7 in SP800-90A. */ if (use_nonce) { /* Note: We don't merge the two calls to f_entropy() in order * to avoid requesting too much entropy from f_entropy() * at once. Specifically, if the underlying digest is not * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which * is larger than the maximum of 32 Bytes that our own * entropy source implementation can emit in a single * call in configurations disabling SHA-512. */ if ((ret = ctx->f_entropy(ctx->p_entropy, seed + seedlen, ctx->entropy_len / 2)) != 0) { return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED; } seedlen += ctx->entropy_len / 2; } /* 1. Concatenate entropy and additional data if any */ if (additional != NULL && len != 0) { memcpy(seed + seedlen, additional, len); seedlen += len; } /* 2. Update state */ if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) { goto exit; } /* 3. Reset reseed_counter */ ctx->reseed_counter = 1; exit: /* 4. Done */ mbedtls_platform_zeroize(seed, seedlen); return ret; } /* * HMAC_DRBG reseeding: 10.1.2.4 + 9.2 */ int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t len) { return hmac_drbg_reseed_core(ctx, additional, len, 0); } /* * HMAC_DRBG initialisation (10.1.2.3 + 9.1) * * The nonce is not passed as a separate parameter but extracted * from the entropy source as suggested in 8.6.7. */ int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx, const mbedtls_md_info_t *md_info, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t md_size; if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) { return ret; } /* The mutex is initialized iff the md context is set up. */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif md_size = mbedtls_md_get_size(md_info); /* * Set initial working state. * Use the V memory location, which is currently all 0, to initialize the * MD context with an all-zero key. Then set V to its initial value. */ if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) { return ret; } memset(ctx->V, 0x01, md_size); ctx->f_entropy = f_entropy; ctx->p_entropy = p_entropy; if (ctx->entropy_len == 0) { /* * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by * each hash function, then according to SP800-90A rev1 10.1 table 2, * min_entropy_len (in bits) is security_strength. * * (This also matches the sizes used in the NIST test vectors.) */ ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ 32; /* better (256+) -> 256 bits */ } if ((ret = hmac_drbg_reseed_core(ctx, custom, len, 1 /* add nonce */)) != 0) { return ret; } return 0; } /* * Set prediction resistance */ void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx, int resistance) { ctx->prediction_resistance = resistance; } /* * Set entropy length grabbed for seeding */ void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len) { ctx->entropy_len = len; } /* * Set reseed interval */ void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval) { ctx->reseed_interval = interval; } /* * HMAC_DRBG random function with optional additional data: * 10.1.2.5 (arabic) + 9.3 (Roman) */ int mbedtls_hmac_drbg_random_with_add(void *p_rng, unsigned char *output, size_t out_len, const unsigned char *additional, size_t add_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info); size_t left = out_len; unsigned char *out = output; /* II. Check request length */ if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) { return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG; } /* III. Check input length */ if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) { return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; } /* 1. (aka VII and IX) Check reseed counter and PR */ if (ctx->f_entropy != NULL && /* For no-reseeding instances */ (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || ctx->reseed_counter > ctx->reseed_interval)) { if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) { return ret; } add_len = 0; /* VII.4 */ } /* 2. Use additional data if any */ if (additional != NULL && add_len != 0) { if ((ret = mbedtls_hmac_drbg_update(ctx, additional, add_len)) != 0) { goto exit; } } /* 3, 4, 5. Generate bytes */ while (left != 0) { size_t use_len = left > md_len ? md_len : left; if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, ctx->V, md_len)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) { goto exit; } memcpy(out, ctx->V, use_len); out += use_len; left -= use_len; } /* 6. Update */ if ((ret = mbedtls_hmac_drbg_update(ctx, additional, add_len)) != 0) { goto exit; } /* 7. Update reseed counter */ ctx->reseed_counter++; exit: /* 8. Done */ return ret; } /* * HMAC_DRBG random function */ int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif ret = mbedtls_hmac_drbg_random_with_add(ctx, output, out_len, NULL, 0); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * This function resets HMAC_DRBG context to the state immediately * after initial call of mbedtls_hmac_drbg_init(). */ void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_THREADING_C) /* The mutex is initialized iff the md context is set up. */ if (ctx->md_ctx.md_info != NULL) { mbedtls_mutex_free(&ctx->mutex); } #endif mbedtls_md_free(&ctx->md_ctx); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context)); ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; } #if defined(MBEDTLS_FS_IO) int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; FILE *f; unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT]; if ((f = fopen(path, "wb")) == NULL) { return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) { goto exit; } if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) { ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; goto exit; } ret = 0; exit: fclose(f); mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path) { int ret = 0; FILE *f = NULL; size_t n; unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT]; unsigned char c; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); n = fread(buf, 1, sizeof(buf), f); if (fread(&c, 1, 1, f) != 0) { ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; goto exit; } if (n == 0 || ferror(f)) { ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; goto exit; } fclose(f); f = NULL; ret = mbedtls_hmac_drbg_update(ctx, buf, n); exit: mbedtls_platform_zeroize(buf, sizeof(buf)); if (f != NULL) { fclose(f); } if (ret != 0) { return ret; } return mbedtls_hmac_drbg_write_seed_file(ctx, path); } #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) #if !defined(MBEDTLS_MD_CAN_SHA1) /* Dummy checkup routine */ int mbedtls_hmac_drbg_self_test(int verbose) { (void) verbose; return 0; } #else #define OUTPUT_LEN 80 /* From a NIST PR=true test vector */ static const unsigned char entropy_pr[] = { 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; static const unsigned char result_pr[OUTPUT_LEN] = { 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; /* From a NIST PR=false test vector */ static const unsigned char entropy_nopr[] = { 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, 0xe9, 0x9d, 0xfe, 0xdf }; static const unsigned char result_nopr[OUTPUT_LEN] = { 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; /* "Entropy" from buffer */ static size_t test_offset; static int hmac_drbg_self_test_entropy(void *data, unsigned char *buf, size_t len) { const unsigned char *p = data; memcpy(buf, p + test_offset, len); test_offset += len; return 0; } #define CHK(c) if ((c) != 0) \ { \ if (verbose != 0) \ mbedtls_printf("failed\n"); \ return 1; \ } /* * Checkup routine for HMAC_DRBG with SHA-1 */ int mbedtls_hmac_drbg_self_test(int verbose) { mbedtls_hmac_drbg_context ctx; unsigned char buf[OUTPUT_LEN]; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); mbedtls_hmac_drbg_init(&ctx); /* * PR = True */ if (verbose != 0) { mbedtls_printf(" HMAC_DRBG (PR = True) : "); } test_offset = 0; CHK(mbedtls_hmac_drbg_seed(&ctx, md_info, hmac_drbg_self_test_entropy, (void *) entropy_pr, NULL, 0)); mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON); CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN)); CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN)); CHK(memcmp(buf, result_pr, OUTPUT_LEN)); mbedtls_hmac_drbg_free(&ctx); mbedtls_hmac_drbg_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } /* * PR = False */ if (verbose != 0) { mbedtls_printf(" HMAC_DRBG (PR = False) : "); } mbedtls_hmac_drbg_init(&ctx); test_offset = 0; CHK(mbedtls_hmac_drbg_seed(&ctx, md_info, hmac_drbg_self_test_entropy, (void *) entropy_nopr, NULL, 0)); CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0)); CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN)); CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN)); CHK(memcmp(buf, result_nopr, OUTPUT_LEN)); mbedtls_hmac_drbg_free(&ctx); mbedtls_hmac_drbg_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_HMAC_DRBG_C */ webfakes/src/mbedtls/library/psa_crypto_cipher.h0000644000176200001440000003633514740737024021636 0ustar liggesusers/* * PSA cipher driver entry points and associated auxiliary functions */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CIPHER_H #define PSA_CRYPTO_CIPHER_H #include #include /** Get Mbed TLS cipher information given the cipher algorithm PSA identifier * as well as the PSA type and size of the key to be used with the cipher * algorithm. * * \param[in] alg PSA cipher algorithm identifier * \param[in] key_type PSA key type * \param[in,out] key_bits Size of the key in bits. The value provided in input * might be updated if necessary. * \param[out] mode Mbed TLS cipher mode * \param[out] cipher_id Mbed TLS cipher algorithm identifier * * \return On success \c PSA_SUCCESS is returned and key_bits, mode and cipher_id * are properly updated. * \c PSA_ERROR_NOT_SUPPORTED is returned if the cipher algorithm is not * supported. */ psa_status_t mbedtls_cipher_values_from_psa(psa_algorithm_t alg, psa_key_type_t key_type, size_t *key_bits, mbedtls_cipher_mode_t *mode, mbedtls_cipher_id_t *cipher_id); #if defined(MBEDTLS_CIPHER_C) /** Get Mbed TLS cipher information given the cipher algorithm PSA identifier * as well as the PSA type and size of the key to be used with the cipher * algorithm. * * \param alg PSA cipher algorithm identifier * \param key_type PSA key type * \param key_bits Size of the key in bits * \param[out] cipher_id Mbed TLS cipher algorithm identifier * * \return The Mbed TLS cipher information of the cipher algorithm. * \c NULL if the PSA cipher algorithm is not supported. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits, mbedtls_cipher_id_t *cipher_id); #endif /* MBEDTLS_CIPHER_C */ /** * \brief Set the key for a multipart symmetric encryption operation. * * \note The signature of this function is that of a PSA driver * cipher_encrypt_setup entry point. This function behaves as a * cipher_encrypt_setup entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation The operation object to set up. It has been * initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_cipher_encrypt_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** * \brief Set the key for a multipart symmetric decryption operation. * * \note The signature of this function is that of a PSA driver * cipher_decrypt_setup entry point. This function behaves as a * cipher_decrypt_setup entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation The operation object to set up. It has been * initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_cipher_decrypt_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Set the IV for a symmetric encryption or decryption operation. * * This function sets the IV (initialization vector), nonce * or initial counter value for the encryption or decryption operation. * * \note The signature of this function is that of a PSA driver * cipher_set_iv entry point. This function behaves as a * cipher_set_iv entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Active cipher operation. * \param[in] iv Buffer containing the IV to use. * \param[in] iv_length Size of the IV in bytes. It is guaranteed by * the core to be less or equal to * PSA_CIPHER_IV_MAX_SIZE. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p iv is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_cipher_set_iv( mbedtls_psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length); /** Encrypt or decrypt a message fragment in an active cipher operation. * * \note The signature of this function is that of a PSA driver * cipher_update entry point. This function behaves as a * cipher_update entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Active cipher operation. * \param[in] input Buffer containing the message fragment to * encrypt or decrypt. * \param[in] input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param[in] output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_cipher_update( mbedtls_psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Finish encrypting or decrypting a message in a cipher operation. * * \note The signature of this function is that of a PSA driver * cipher_finish entry point. This function behaves as a * cipher_finish entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Active cipher operation. * \param[out] output Buffer where the output is to be written. * \param[in] output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * The total input size passed to this operation is not valid for * this particular algorithm. For example, the algorithm is a based * on block cipher and requires a whole number of blocks, but the * total input size is not a multiple of the block size. * \retval #PSA_ERROR_INVALID_PADDING * This is a decryption operation for an algorithm that includes * padding, and the ciphertext does not contain valid padding. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_cipher_finish( mbedtls_psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length); /** Abort a cipher operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation. * * \note The signature of this function is that of a PSA driver * cipher_abort entry point. This function behaves as a * cipher_abort entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Initialized cipher operation. * * \retval #PSA_SUCCESS \emptydescription */ psa_status_t mbedtls_psa_cipher_abort(mbedtls_psa_cipher_operation_t *operation); /** Encrypt a message using a symmetric cipher. * * \note The signature of this function is that of a PSA driver * cipher_encrypt entry point. This function behaves as a * cipher_encrypt entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param[in] iv Buffer containing the IV for encryption. The * IV has been generated by the core. * \param[in] iv_length Size of the \p iv in bytes. * \param[in] input Buffer containing the message to encrypt. * \param[in] input_length Size of the \p input buffer in bytes. * \param[in,out] output Buffer where the output is to be written. * \param[in] output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes that make up * the returned output. Initialized to zero * by the core. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size \p iv_length is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. * The total input size passed to this operation is not valid for * this particular algorithm. For example, the algorithm is a based * on block cipher and requires a whole number of blocks, but the * total input size is not a multiple of the block size. * \retval #PSA_ERROR_INVALID_PADDING * This is a decryption operation for an algorithm that includes * padding, and the ciphertext does not contain valid padding. */ psa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *iv, size_t iv_length, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Decrypt a message using a symmetric cipher. * * \note The signature of this function is that of a PSA driver * cipher_decrypt entry point. This function behaves as a * cipher_decrypt entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param[in] input Buffer containing the iv and the ciphertext. * \param[in] input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param[in] output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes that make up * the returned output. Initialized to zero * by the core. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p iv is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. * The total input size passed to this operation is not valid for * this particular algorithm. For example, the algorithm is a based * on block cipher and requires a whole number of blocks, but the * total input size is not a multiple of the block size. * \retval #PSA_ERROR_INVALID_PADDING * This is a decryption operation for an algorithm that includes * padding, and the ciphertext does not contain valid padding. */ psa_status_t mbedtls_psa_cipher_decrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); #endif /* PSA_CRYPTO_CIPHER_H */ webfakes/src/mbedtls/library/psa_crypto_random_impl.h0000644000176200001440000001004314740737024022651 0ustar liggesusers/** \file psa_crypto_random_impl.h * * \brief PSA crypto random generator implementation abstraction. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_RANDOM_IMPL_H #define PSA_CRYPTO_RANDOM_IMPL_H #include "psa_util_internal.h" #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t; #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #include "mbedtls/entropy.h" /* Choose a DRBG based on configuration and availability */ #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" #undef MBEDTLS_PSA_HMAC_DRBG_MD_TYPE #elif defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #if defined(MBEDTLS_MD_CAN_SHA512) && defined(MBEDTLS_MD_CAN_SHA256) #include #if SIZE_MAX > 0xffffffff /* Looks like a 64-bit system, so prefer SHA-512. */ #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512 #else /* Looks like a 32-bit system, so prefer SHA-256. */ #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 #endif #elif defined(MBEDTLS_MD_CAN_SHA512) #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512 #elif defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 #else #error "No hash algorithm available for HMAC_DBRG." #endif #else /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/ #error "No DRBG module available for the psa_crypto module." #endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/ /* The maximum number of bytes that mbedtls_psa_get_random() is expected to return. */ #if defined(MBEDTLS_CTR_DRBG_C) #define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST #elif defined(MBEDTLS_HMAC_DRBG_C) #define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST #endif #if defined(MBEDTLS_CTR_DRBG_C) typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t; #elif defined(MBEDTLS_HMAC_DRBG_C) typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t; #endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ typedef struct { void (* entropy_init)(mbedtls_entropy_context *ctx); void (* entropy_free)(mbedtls_entropy_context *ctx); mbedtls_entropy_context entropy; mbedtls_psa_drbg_context_t drbg; } mbedtls_psa_random_context_t; /** Initialize the PSA DRBG. * * \param p_rng Pointer to the Mbed TLS DRBG state. */ static inline void mbedtls_psa_drbg_init(mbedtls_psa_drbg_context_t *p_rng) { #if defined(MBEDTLS_CTR_DRBG_C) mbedtls_ctr_drbg_init(p_rng); #elif defined(MBEDTLS_HMAC_DRBG_C) mbedtls_hmac_drbg_init(p_rng); #endif } /** Deinitialize the PSA DRBG. * * \param p_rng Pointer to the Mbed TLS DRBG state. */ static inline void mbedtls_psa_drbg_free(mbedtls_psa_drbg_context_t *p_rng) { #if defined(MBEDTLS_CTR_DRBG_C) mbedtls_ctr_drbg_free(p_rng); #elif defined(MBEDTLS_HMAC_DRBG_C) mbedtls_hmac_drbg_free(p_rng); #endif } /** Seed the PSA DRBG. * * \param entropy An entropy context to read the seed from. * \param custom The personalization string. * This can be \c NULL, in which case the personalization * string is empty regardless of the value of \p len. * \param len The length of the personalization string. * * \return \c 0 on success. * \return An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure. */ static inline int mbedtls_psa_drbg_seed(mbedtls_psa_drbg_context_t *drbg_ctx, mbedtls_entropy_context *entropy, const unsigned char *custom, size_t len) { #if defined(MBEDTLS_CTR_DRBG_C) return mbedtls_ctr_drbg_seed(drbg_ctx, mbedtls_entropy_func, entropy, custom, len); #elif defined(MBEDTLS_HMAC_DRBG_C) const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE); return mbedtls_hmac_drbg_seed(drbg_ctx, md_info, mbedtls_entropy_func, entropy, custom, len); #endif } #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #endif /* PSA_CRYPTO_RANDOM_IMPL_H */ webfakes/src/mbedtls/library/ssl_tls13_server.c0000644000176200001440000037020414740737024021325 0ustar liggesusers/* * TLS 1.3 server-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "mbedtls/constant_time.h" #include "mbedtls/oid.h" #include "mbedtls/psa_util.h" #include "ssl_misc.h" #include "ssl_tls13_keys.h" #include "ssl_debug_helpers.h" static const mbedtls_ssl_ciphersuite_t *ssl_tls13_validate_peer_ciphersuite( mbedtls_ssl_context *ssl, unsigned int cipher_suite) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info; if (!mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) { return NULL; } ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, ssl->tls_version, ssl->tls_version) != 0)) { return NULL; } return ciphersuite_info; } static void ssl_tls13_select_ciphersuite( mbedtls_ssl_context *ssl, const unsigned char *cipher_suites, const unsigned char *cipher_suites_end, int psk_ciphersuite_id, psa_algorithm_t psk_hash_alg, const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info) { *selected_ciphersuite_info = NULL; /* * In a compliant ClientHello the byte-length of the list of ciphersuites * is even and this function relies on this fact. This should have been * checked in the main ClientHello parsing function. Double check here. */ if ((cipher_suites_end - cipher_suites) & 1) { return; } for (const unsigned char *p = cipher_suites; p < cipher_suites_end; p += 2) { /* * "cipher_suites_end - p is even" is an invariant of the loop. As * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and it * is thus safe to read two bytes. */ uint16_t id = MBEDTLS_GET_UINT16_BE(p, 0); const mbedtls_ssl_ciphersuite_t *info = ssl_tls13_validate_peer_ciphersuite(ssl, id); if (info == NULL) { continue; } /* * If a valid PSK ciphersuite identifier has been passed in, we want * an exact match. */ if (psk_ciphersuite_id != 0) { if (id != psk_ciphersuite_id) { continue; } } else if (psk_hash_alg != PSA_ALG_NONE) { if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac) != psk_hash_alg) { continue; } } *selected_ciphersuite_info = info; return; } MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%lx", (unsigned) psk_ciphersuite_id, (unsigned long) psk_hash_alg)); } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* From RFC 8446: * * enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode; * struct { * PskKeyExchangeMode ke_modes<1..255>; * } PskKeyExchangeModes; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_key_exchange_modes_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t ke_modes_len; int ke_modes = 0; /* Read ke_modes length (1 Byte) */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); ke_modes_len = *p++; /* Currently, there are only two PSK modes, so even without looking * at the content, something's wrong if the list has more than 2 items. */ if (ke_modes_len > 2) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ke_modes_len); while (ke_modes_len-- != 0) { switch (*p++) { case MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE: ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK KEX MODE")); break; case MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE: ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK_EPHEMERAL KEX MODE")); break; default: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } } ssl->handshake->tls13_kex_modes = ke_modes; return 0; } /* * Non-error return values of * ssl_tls13_offered_psks_check_identity_match_ticket() and * ssl_tls13_offered_psks_check_identity_match(). They are positive to * not collide with error codes that are negative. Zero * (SSL_TLS1_3_PSK_IDENTITY_MATCH) in case of success as it may be propagated * up by the callers of this function as a generic success condition. * * The return value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE means * that the pre-shared-key identity matches that of a ticket or an externally- * provisioned pre-shared-key. We have thus been able to retrieve the * attributes of the pre-shared-key but at least one of them does not meet * some criteria and the pre-shared-key cannot be used. For example, a ticket * is expired or its version is not TLS 1.3. Note eventually that the return * value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE does not have * anything to do with binder check. A binder check is done only when a * suitable pre-shared-key has been selected and only for that selected * pre-shared-key: if the binder check fails, we fail the handshake and we do * not try to find another pre-shared-key for which the binder check would * succeed as recommended by the specification. */ #define SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH 2 #define SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE 1 #define SSL_TLS1_3_PSK_IDENTITY_MATCH 0 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_offered_psks_check_identity_match_ticket( mbedtls_ssl_context *ssl, const unsigned char *identity, size_t identity_len, uint32_t obfuscated_ticket_age, mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *ticket_buffer; #if defined(MBEDTLS_HAVE_TIME) mbedtls_ms_time_t now; mbedtls_ms_time_t server_age; uint32_t client_age; mbedtls_ms_time_t age_diff; #endif ((void) obfuscated_ticket_age); MBEDTLS_SSL_DEBUG_MSG(2, ("=> check_identity_match_ticket")); /* Ticket parser is not configured, Skip */ if (ssl->conf->f_ticket_parse == NULL || identity_len == 0) { return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; } /* We create a copy of the encrypted ticket since the ticket parsing * function is allowed to use its input buffer as an output buffer * (in-place decryption). We do, however, need the original buffer for * computing the PSK binder value. */ ticket_buffer = mbedtls_calloc(1, identity_len); if (ticket_buffer == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ticket_buffer, identity, identity_len); ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket, session, ticket_buffer, identity_len); switch (ret) { case 0: ret = SSL_TLS1_3_PSK_IDENTITY_MATCH; break; case MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED: MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired")); ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE; break; case MBEDTLS_ERR_SSL_INVALID_MAC: MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic")); ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; break; default: MBEDTLS_SSL_DEBUG_RET(1, "ticket_parse", ret); ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; } /* We delete the temporary buffer */ mbedtls_free(ticket_buffer); if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) { goto exit; } /* * The identity matches that of a ticket. Now check that it has suitable * attributes and bet it will not be the case. */ ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE; if (session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) { MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3.")); goto exit; } #if defined(MBEDTLS_HAVE_TIME) now = mbedtls_ms_time(); if (now < session->ticket_creation_time) { MBEDTLS_SSL_DEBUG_MSG( 3, ("Invalid ticket creation time ( now = %" MBEDTLS_PRINTF_MS_TIME ", creation_time = %" MBEDTLS_PRINTF_MS_TIME " )", now, session->ticket_creation_time)); goto exit; } server_age = now - session->ticket_creation_time; /* RFC 8446 section 4.6.1 * * Servers MUST NOT use any value greater than 604800 seconds (7 days). * * RFC 8446 section 4.2.11.1 * * Clients MUST NOT attempt to use tickets which have ages greater than * the "ticket_lifetime" value which was provided with the ticket. * */ if (server_age > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME * 1000) { MBEDTLS_SSL_DEBUG_MSG( 3, ("Ticket age exceeds limitation ticket_age = %" MBEDTLS_PRINTF_MS_TIME, server_age)); goto exit; } /* RFC 8446 section 4.2.10 * * For PSKs provisioned via NewSessionTicket, a server MUST validate that * the ticket age for the selected PSK identity (computed by subtracting * ticket_age_add from PskIdentity.obfuscated_ticket_age modulo 2^32) is * within a small tolerance of the time since the ticket was issued. * * NOTE: The typical accuracy of an RTC crystal is ±100 to ±20 parts per * million (360 to 72 milliseconds per hour). Default tolerance * window is 6s, thus in the worst case clients and servers must * sync up their system time every 6000/360/2~=8 hours. */ client_age = obfuscated_ticket_age - session->ticket_age_add; age_diff = server_age - (mbedtls_ms_time_t) client_age; if (age_diff < -MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE || age_diff > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) { MBEDTLS_SSL_DEBUG_MSG( 3, ("Ticket age outside tolerance window ( diff = %" MBEDTLS_PRINTF_MS_TIME ")", age_diff)); goto exit; } #endif /* MBEDTLS_HAVE_TIME */ /* * All good, we have found a suitable ticket. */ ret = SSL_TLS1_3_PSK_IDENTITY_MATCH; exit: if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) { mbedtls_ssl_session_free(session); } MBEDTLS_SSL_DEBUG_MSG(2, ("<= check_identity_match_ticket")); return ret; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_offered_psks_check_identity_match( mbedtls_ssl_context *ssl, const unsigned char *identity, size_t identity_len, uint32_t obfuscated_ticket_age, int *psk_type, mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ((void) session); ((void) obfuscated_ticket_age); *psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL; MBEDTLS_SSL_DEBUG_BUF(4, "identity", identity, identity_len); #if defined(MBEDTLS_SSL_SESSION_TICKETS) ret = ssl_tls13_offered_psks_check_identity_match_ticket( ssl, identity, identity_len, obfuscated_ticket_age, session); if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH) { *psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION; ret = mbedtls_ssl_set_hs_psk(ssl, session->resumption_key, session->resumption_key_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(4, "Ticket-resumed PSK:", session->resumption_key, session->resumption_key_len); MBEDTLS_SSL_DEBUG_MSG(4, ("ticket: obfuscated_ticket_age: %u", (unsigned) obfuscated_ticket_age)); return SSL_TLS1_3_PSK_IDENTITY_MATCH; } else if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE) { return SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* Check identity with external configured function */ if (ssl->conf->f_psk != NULL) { if (ssl->conf->f_psk( ssl->conf->p_psk, ssl, identity, identity_len) == 0) { return SSL_TLS1_3_PSK_IDENTITY_MATCH; } return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; } MBEDTLS_SSL_DEBUG_BUF(5, "identity", identity, identity_len); /* Check identity with pre-configured psk */ if (ssl->conf->psk_identity != NULL && identity_len == ssl->conf->psk_identity_len && mbedtls_ct_memcmp(ssl->conf->psk_identity, identity, identity_len) == 0) { ret = mbedtls_ssl_set_hs_psk(ssl, ssl->conf->psk, ssl->conf->psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); return ret; } return SSL_TLS1_3_PSK_IDENTITY_MATCH; } return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; } /* * Non-error return values of ssl_tls13_offered_psks_check_binder_match(). * They are positive to not collide with error codes that are negative. Zero * (SSL_TLS1_3_BINDER_MATCH) in case of success as it may be propagated up * by the callers of this function as a generic success condition. */ #define SSL_TLS1_3_BINDER_DOES_NOT_MATCH 1 #define SSL_TLS1_3_BINDER_MATCH 0 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_offered_psks_check_binder_match( mbedtls_ssl_context *ssl, const unsigned char *binder, size_t binder_len, int psk_type, psa_algorithm_t psk_hash_alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char transcript[PSA_HASH_MAX_SIZE]; size_t transcript_len; unsigned char *psk; size_t psk_len; unsigned char server_computed_binder[PSA_HASH_MAX_SIZE]; if (binder_len != PSA_HASH_LENGTH(psk_hash_alg)) { return SSL_TLS1_3_BINDER_DOES_NOT_MATCH; } /* Get current state of handshake transcript. */ ret = mbedtls_ssl_get_handshake_transcript( ssl, mbedtls_md_type_from_psa_alg(psk_hash_alg), transcript, sizeof(transcript), &transcript_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_create_psk_binder(ssl, psk_hash_alg, psk, psk_len, psk_type, transcript, server_computed_binder); #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_free((void *) psk); #endif if (ret != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("PSK binder calculation failed.")); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( computed ): ", server_computed_binder, transcript_len); MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( received ): ", binder, binder_len); if (mbedtls_ct_memcmp(server_computed_binder, binder, PSA_HASH_LENGTH(psk_hash_alg)) == 0) { return SSL_TLS1_3_BINDER_MATCH; } mbedtls_platform_zeroize(server_computed_binder, sizeof(server_computed_binder)); return SSL_TLS1_3_BINDER_DOES_NOT_MATCH; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst, const mbedtls_ssl_session *src) { dst->ticket_age_add = src->ticket_age_add; dst->ticket_flags = src->ticket_flags; dst->resumption_key_len = src->resumption_key_len; if (src->resumption_key_len == 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(dst->resumption_key, src->resumption_key, src->resumption_key_len); #if defined(MBEDTLS_SSL_EARLY_DATA) dst->max_early_data_size = src->max_early_data_size; #if defined(MBEDTLS_SSL_ALPN) int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn); if (ret != 0) { return ret; } #endif /* MBEDTLS_SSL_ALPN */ #endif /* MBEDTLS_SSL_EARLY_DATA*/ return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ struct psk_attributes { int type; int key_exchange_mode; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; }; #define PSK_ATTRIBUTES_INIT { 0, 0, NULL } /* Parser for pre_shared_key extension in client hello * struct { * opaque identity<1..2^16-1>; * uint32 obfuscated_ticket_age; * } PskIdentity; * * opaque PskBinderEntry<32..255>; * * struct { * PskIdentity identities<7..2^16-1>; * PskBinderEntry binders<33..2^16-1>; * } OfferedPsks; * * struct { * select (Handshake.msg_type) { * case client_hello: OfferedPsks; * .... * }; * } PreSharedKeyExtension; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl, const unsigned char *pre_shared_key_ext, const unsigned char *pre_shared_key_ext_end, const unsigned char *ciphersuites, const unsigned char *ciphersuites_end, struct psk_attributes *psk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *identities = pre_shared_key_ext; const unsigned char *p_identity_len; size_t identities_len; const unsigned char *identities_end; const unsigned char *binders; const unsigned char *p_binder_len; size_t binders_len; const unsigned char *binders_end; int matched_identity = -1; int identity_id = -1; MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key extension", pre_shared_key_ext, pre_shared_key_ext_end - pre_shared_key_ext); /* identities_len 2 bytes * identities_data >= 7 bytes */ MBEDTLS_SSL_CHK_BUF_READ_PTR(identities, pre_shared_key_ext_end, 7 + 2); identities_len = MBEDTLS_GET_UINT16_BE(identities, 0); p_identity_len = identities + 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, pre_shared_key_ext_end, identities_len); identities_end = p_identity_len + identities_len; /* binders_len 2 bytes * binders >= 33 bytes */ binders = identities_end; MBEDTLS_SSL_CHK_BUF_READ_PTR(binders, pre_shared_key_ext_end, 33 + 2); binders_len = MBEDTLS_GET_UINT16_BE(binders, 0); p_binder_len = binders + 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, pre_shared_key_ext_end, binders_len); binders_end = p_binder_len + binders_len; ret = ssl->handshake->update_checksum(ssl, pre_shared_key_ext, identities_end - pre_shared_key_ext); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } while (p_identity_len < identities_end && p_binder_len < binders_end) { const unsigned char *identity; size_t identity_len; uint32_t obfuscated_ticket_age; const unsigned char *binder; size_t binder_len; int psk_ciphersuite_id; psa_algorithm_t psk_hash_alg; int allowed_key_exchange_modes; mbedtls_ssl_session session; mbedtls_ssl_session_init(&session); MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, identities_end, 2 + 1 + 4); identity_len = MBEDTLS_GET_UINT16_BE(p_identity_len, 0); identity = p_identity_len + 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(identity, identities_end, identity_len + 4); obfuscated_ticket_age = MBEDTLS_GET_UINT32_BE(identity, identity_len); p_identity_len += identity_len + 6; MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, binders_end, 1 + 32); binder_len = *p_binder_len; binder = p_binder_len + 1; MBEDTLS_SSL_CHK_BUF_READ_PTR(binder, binders_end, binder_len); p_binder_len += binder_len + 1; identity_id++; if (matched_identity != -1) { continue; } ret = ssl_tls13_offered_psks_check_identity_match( ssl, identity, identity_len, obfuscated_ticket_age, &psk->type, &session); if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) { continue; } MBEDTLS_SSL_DEBUG_MSG(4, ("found matched identity")); switch (psk->type) { case MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL: psk_ciphersuite_id = 0; psk_hash_alg = PSA_ALG_SHA_256; allowed_key_exchange_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; break; #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION: psk_ciphersuite_id = session.ciphersuite; psk_hash_alg = PSA_ALG_NONE; ssl->session_negotiate->ticket_flags = session.ticket_flags; allowed_key_exchange_modes = session.ticket_flags & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; break; #endif default: return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE; if ((allowed_key_exchange_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) && ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) { psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; } else if ((allowed_key_exchange_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) && ssl_tls13_key_exchange_is_psk_available(ssl)) { psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; } if (psk->key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE) { MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable PSK key exchange mode")); continue; } ssl_tls13_select_ciphersuite(ssl, ciphersuites, ciphersuites_end, psk_ciphersuite_id, psk_hash_alg, &psk->ciphersuite_info); if (psk->ciphersuite_info == NULL) { #if defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_session_free(&session); #endif /* * We consider finding a ciphersuite suitable for the PSK as part * of the validation of its binder. Thus if we do not find one, we * abort the handshake with a decrypt_error alert. */ MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ret = ssl_tls13_offered_psks_check_binder_match( ssl, binder, binder_len, psk->type, mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) psk->ciphersuite_info->mac)); if (ret != SSL_TLS1_3_BINDER_MATCH) { /* For security reasons, the handshake should be aborted when we * fail to validate a binder value. See RFC 8446 section 4.2.11.2 * and appendix E.6. */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_session_free(&session); #endif MBEDTLS_SSL_DEBUG_MSG(3, ("Invalid binder.")); MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_offered_psks_check_binder_match", ret); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return ret; } matched_identity = identity_id; #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (psk->type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { ret = ssl_tls13_session_copy_ticket(ssl->session_negotiate, &session); mbedtls_ssl_session_free(&session); if (ret != 0) { return ret; } } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ } if (p_identity_len != identities_end || p_binder_len != binders_end) { MBEDTLS_SSL_DEBUG_MSG(3, ("pre_shared_key extension decode error")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Update the handshake transcript with the binder list. */ ret = ssl->handshake->update_checksum( ssl, identities_end, (size_t) (binders_end - identities_end)); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } if (matched_identity == -1) { MBEDTLS_SSL_DEBUG_MSG(3, ("No usable PSK or ticket.")); return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; } ssl->handshake->selected_identity = (uint16_t) matched_identity; MBEDTLS_SSL_DEBUG_MSG(3, ("Pre shared key found")); return 0; } /* * struct { * select ( Handshake.msg_type ) { * .... * case server_hello: * uint16 selected_identity; * } * } PreSharedKeyExtension; */ static int ssl_tls13_write_server_pre_shared_key_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *olen) { unsigned char *p = (unsigned char *) buf; *olen = 0; int not_using_psk = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) not_using_psk = (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)); #else not_using_psk = (ssl->handshake->psk == NULL); #endif if (not_using_psk) { /* We shouldn't have called this extension writer unless we've * chosen to use a PSK. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding pre_shared_key extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, p, 0); MBEDTLS_PUT_UINT16_BE(2, p, 2); MBEDTLS_PUT_UINT16_BE(ssl->handshake->selected_identity, p, 4); *olen = 6; MBEDTLS_SSL_DEBUG_MSG(4, ("sent selected_identity: %u", ssl->handshake->selected_identity)); mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY); return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ /* From RFC 8446: * struct { * ProtocolVersion versions<2..254>; * } SupportedVersions; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t versions_len; const unsigned char *versions_end; uint16_t tls_version; int found_supported_version = 0; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); versions_len = p[0]; p += 1; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, versions_len); versions_end = p + versions_len; while (p < versions_end) { MBEDTLS_SSL_CHK_BUF_READ_PTR(p, versions_end, 2); tls_version = mbedtls_ssl_read_version(p, ssl->conf->transport); p += 2; if (MBEDTLS_SSL_VERSION_TLS1_3 == tls_version) { found_supported_version = 1; break; } if ((MBEDTLS_SSL_VERSION_TLS1_2 == tls_version) && mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) { found_supported_version = 1; break; } } if (!found_supported_version) { MBEDTLS_SSL_DEBUG_MSG(1, ("No supported version found.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } MBEDTLS_SSL_DEBUG_MSG(1, ("Negotiated version: [%04x]", (unsigned int) tls_version)); return (int) tls_version; } #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) /* * * From RFC 8446: * enum { * ... (0xFFFF) * } NamedGroup; * struct { * NamedGroup named_group_list<2..2^16-1>; * } NamedGroupList; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_supported_groups_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t named_group_list_len; const unsigned char *named_group_list_end; MBEDTLS_SSL_DEBUG_BUF(3, "supported_groups extension", p, end - buf); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); named_group_list_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, named_group_list_len); named_group_list_end = p + named_group_list_len; ssl->handshake->hrr_selected_group = 0; while (p < named_group_list_end) { uint16_t named_group; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, named_group_list_end, 2); named_group = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(2, ("got named group: %s(%04x)", mbedtls_ssl_named_group_to_str(named_group), named_group)); if (!mbedtls_ssl_named_group_is_offered(ssl, named_group) || !mbedtls_ssl_named_group_is_supported(named_group) || ssl->handshake->hrr_selected_group != 0) { continue; } MBEDTLS_SSL_DEBUG_MSG(2, ("add named group %s(%04x) into received list.", mbedtls_ssl_named_group_to_str(named_group), named_group)); ssl->handshake->hrr_selected_group = named_group; } return 0; } #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ #define SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH 1 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) /* * ssl_tls13_parse_key_shares_ext() verifies whether the information in the * extension is correct and stores the first acceptable key share and its * associated group. * * Possible return values are: * - 0: Successful processing of the client provided key share extension. * - SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH: The key shares provided by * the client does not match a group supported by the server. A * HelloRetryRequest will be needed. * - A negative value for fatal errors. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_key_shares_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char const *p = buf; unsigned char const *client_shares_end; size_t client_shares_len; /* From RFC 8446: * * struct { * KeyShareEntry client_shares<0..2^16-1>; * } KeyShareClientHello; * */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); client_shares_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, client_shares_len); ssl->handshake->offered_group_id = 0; client_shares_end = p + client_shares_len; /* We try to find a suitable key share entry and copy it to the * handshake context. Later, we have to find out whether we can do * something with the provided key share or whether we have to * dismiss it and send a HelloRetryRequest message. */ while (p < client_shares_end) { uint16_t group; size_t key_exchange_len; const unsigned char *key_exchange; /* * struct { * NamedGroup group; * opaque key_exchange<1..2^16-1>; * } KeyShareEntry; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, 4); group = MBEDTLS_GET_UINT16_BE(p, 0); key_exchange_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; key_exchange = p; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, key_exchange_len); p += key_exchange_len; /* Continue parsing even if we have already found a match, * for input validation purposes. */ if (!mbedtls_ssl_named_group_is_offered(ssl, group) || !mbedtls_ssl_named_group_is_supported(group) || ssl->handshake->offered_group_id != 0) { continue; } /* * ECDHE and FFDHE groups are supported */ if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) || mbedtls_ssl_tls13_named_group_is_ffdh(group)) { MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH/FFDH group: %s (%04x)", mbedtls_ssl_named_group_to_str(group), group)); ret = mbedtls_ssl_tls13_read_public_xxdhe_share( ssl, key_exchange - 2, key_exchange_len + 2); if (ret != 0) { return ret; } } else { MBEDTLS_SSL_DEBUG_MSG(4, ("Unrecognized NamedGroup %u", (unsigned) group)); continue; } ssl->handshake->offered_group_id = group; } if (ssl->handshake->offered_group_id == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("no matching key share")); return SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH; } return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_client_hello_has_exts(mbedtls_ssl_context *ssl, int exts_mask) { int masked = ssl->handshake->received_extensions & exts_mask; return masked == exts_mask; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange( mbedtls_ssl_context *ssl) { return ssl_tls13_client_hello_has_exts( ssl, MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | MBEDTLS_SSL_EXT_MASK(SIG_ALG)); } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_client_hello_has_exts_for_psk_key_exchange( mbedtls_ssl_context *ssl) { return ssl_tls13_client_hello_has_exts( ssl, MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)); } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange( mbedtls_ssl_context *ssl) { return ssl_tls13_client_hello_has_exts( ssl, MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)); } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) return mbedtls_ssl_conf_tls13_is_psk_enabled(ssl) && mbedtls_ssl_tls13_is_psk_supported(ssl) && ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl); #else ((void) ssl); return 0; #endif } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) return mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl) && mbedtls_ssl_tls13_is_psk_ephemeral_supported(ssl) && ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl); #else ((void) ssl); return 0; #endif } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_ephemeral_available(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) return mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl) && ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(ssl); #else ((void) ssl); return 0; #endif } #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) static psa_algorithm_t ssl_tls13_iana_sig_alg_to_psa_alg(uint16_t sig_alg) { switch (sig_alg) { case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: return PSA_ALG_ECDSA(PSA_ALG_SHA_256); case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: return PSA_ALG_ECDSA(PSA_ALG_SHA_384); case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: return PSA_ALG_ECDSA(PSA_ALG_SHA_512); case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: return PSA_ALG_RSA_PSS(PSA_ALG_SHA_256); case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: return PSA_ALG_RSA_PSS(PSA_ALG_SHA_384); case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: return PSA_ALG_RSA_PSS(PSA_ALG_SHA_512); case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256); case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384); case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512); default: return PSA_ALG_NONE; } } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Pick best ( private key, certificate chain ) pair based on the signature * algorithms supported by the client. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_pick_key_cert(mbedtls_ssl_context *ssl) { mbedtls_ssl_key_cert *key_cert, *key_cert_list; const uint16_t *sig_alg = ssl->handshake->received_sig_algs; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_key_cert != NULL) { key_cert_list = ssl->handshake->sni_key_cert; } else #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ key_cert_list = ssl->conf->key_cert; if (key_cert_list == NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("server has no certificate")); return -1; } for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) { continue; } if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) { continue; } for (key_cert = key_cert_list; key_cert != NULL; key_cert = key_cert->next) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t psa_alg = PSA_ALG_NONE; #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_CRT(3, "certificate (chain) candidate", key_cert->cert); /* * This avoids sending the client a cert it'll reject based on * keyUsage or other extensions. */ if (mbedtls_x509_crt_check_key_usage( key_cert->cert, MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0 || mbedtls_x509_crt_check_extended_key_usage( key_cert->cert, MBEDTLS_OID_SERVER_AUTH, MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH)) != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: " "(extended) key usage extension")); continue; } MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_tls13_pick_key_cert:" "check signature algorithm %s [%04x]", mbedtls_ssl_sig_alg_to_str(*sig_alg), *sig_alg)); #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_alg = ssl_tls13_iana_sig_alg_to_psa_alg(*sig_alg); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (mbedtls_ssl_tls13_check_sig_alg_cert_key_match( *sig_alg, &key_cert->cert->pk) #if defined(MBEDTLS_USE_PSA_CRYPTO) && psa_alg != PSA_ALG_NONE && mbedtls_pk_can_do_ext(&key_cert->cert->pk, psa_alg, PSA_KEY_USAGE_SIGN_HASH) == 1 #endif /* MBEDTLS_USE_PSA_CRYPTO */ ) { ssl->handshake->key_cert = key_cert; MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_tls13_pick_key_cert:" "selected signature algorithm" " %s [%04x]", mbedtls_ssl_sig_alg_to_str(*sig_alg), *sig_alg)); MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate (chain)", ssl->handshake->key_cert->cert); return 0; } } } MBEDTLS_SSL_DEBUG_MSG(2, ("ssl_tls13_pick_key_cert:" "no suitable certificate found")); return -1; } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * * STATE HANDLING: ClientHello * * There are three possible classes of outcomes when parsing the ClientHello: * * 1) The ClientHello was well-formed and matched the server's configuration. * * In this case, the server progresses to sending its ServerHello. * * 2) The ClientHello was well-formed but didn't match the server's * configuration. * * For example, the client might not have offered a key share which * the server supports, or the server might require a cookie. * * In this case, the server sends a HelloRetryRequest. * * 3) The ClientHello was ill-formed * * In this case, we abort the handshake. * */ /* * Structure of this message: * * uint16 ProtocolVersion; * opaque Random[32]; * uint8 CipherSuite[2]; // Cryptographic suite selector * * struct { * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 * Random random; * opaque legacy_session_id<0..32>; * CipherSuite cipher_suites<2..2^16-2>; * opaque legacy_compression_methods<1..2^8-1>; * Extension extensions<8..2^16-1>; * } ClientHello; */ #define SSL_CLIENT_HELLO_OK 0 #define SSL_CLIENT_HELLO_HRR_REQUIRED 1 #define SSL_CLIENT_HELLO_TLS1_2 2 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; const unsigned char *random; size_t legacy_session_id_len; const unsigned char *legacy_session_id; size_t cipher_suites_len; const unsigned char *cipher_suites; const unsigned char *cipher_suites_end; size_t extensions_len; const unsigned char *extensions_end; const unsigned char *supported_versions_data; const unsigned char *supported_versions_data_end; mbedtls_ssl_handshake_params *handshake = ssl->handshake; int hrr_required = 0; int no_usable_share_for_key_agreement = 0; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) int got_psk = 0; struct psk_attributes psk = PSK_ATTRIBUTES_INIT; const unsigned char *pre_shared_key_ext = NULL; const unsigned char *pre_shared_key_ext_end = NULL; #endif /* * ClientHello layout: * 0 . 1 protocol version * 2 . 33 random bytes * 34 . 34 session id length ( 1 byte ) * 35 . 34+x session id * .. . .. ciphersuite list length ( 2 bytes ) * .. . .. ciphersuite list * .. . .. compression alg. list length ( 1 byte ) * .. . .. compression alg. list * .. . .. extensions length ( 2 bytes, optional ) * .. . .. extensions ( optional ) */ /* * Minimal length ( with everything empty and extensions omitted ) is * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can * read at least up to session id length without worrying. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 38); /* ... * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 * ... * with ProtocolVersion defined as: * uint16 ProtocolVersion; */ if (mbedtls_ssl_read_version(p, ssl->conf->transport) != MBEDTLS_SSL_VERSION_TLS1_2) { MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } p += 2; /* ... * Random random; * ... * with Random defined as: * opaque Random[32]; */ random = p; p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; /* ... * opaque legacy_session_id<0..32>; * ... */ legacy_session_id_len = *(p++); legacy_session_id = p; /* * Check we have enough data for the legacy session identifier * and the ciphersuite list length. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_len + 2); p += legacy_session_id_len; /* ... * CipherSuite cipher_suites<2..2^16-2>; * ... * with CipherSuite defined as: * uint8 CipherSuite[2]; */ cipher_suites_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; cipher_suites = p; /* * The length of the ciphersuite list has to be even. */ if (cipher_suites_len & 1) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Check we have enough data for the ciphersuite list, the legacy * compression methods and the length of the extensions. * * cipher_suites cipher_suites_len bytes * legacy_compression_methods length 1 byte */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 1); p += cipher_suites_len; cipher_suites_end = p; /* Check if we have enough data for legacy_compression_methods * and the length of the extensions (2 bytes). */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p + 1, end, p[0] + 2); /* * Search for the supported versions extension and parse it to determine * if the client supports TLS 1.3. */ ret = mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( ssl, p + 1 + p[0], end, &supported_versions_data, &supported_versions_data_end); if (ret < 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts"), ret); return ret; } if (ret == 0) { return SSL_CLIENT_HELLO_TLS1_2; } if (ret == 1) { ret = ssl_tls13_parse_supported_versions_ext(ssl, supported_versions_data, supported_versions_data_end); if (ret < 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_tls13_parse_supported_versions_ext"), ret); return ret; } /* * The supported versions extension was parsed successfully as the * value returned by ssl_tls13_parse_supported_versions_ext() is * positive. The return value is then equal to * MBEDTLS_SSL_VERSION_TLS1_2 or MBEDTLS_SSL_VERSION_TLS1_3, defining * the TLS version to negotiate. */ if (MBEDTLS_SSL_VERSION_TLS1_2 == ret) { return SSL_CLIENT_HELLO_TLS1_2; } } /* * We negotiate TLS 1.3. */ ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; ssl->session_negotiate->endpoint = ssl->conf->endpoint; /* Before doing any crypto, make sure we can. */ ret = mbedtls_ssl_tls13_crypto_init(ssl); if (ret != 0) { return ret; } /* * We are negotiating the version 1.3 of the protocol. Do what we have * postponed: copy of the client random bytes, copy of the legacy session * identifier and selection of the TLS 1.3 cipher suite. */ MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); memcpy(&handshake->randbytes[0], random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); if (legacy_session_id_len > sizeof(ssl->session_negotiate->id)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->session_negotiate->id_len = legacy_session_id_len; MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", legacy_session_id, legacy_session_id_len); memcpy(&ssl->session_negotiate->id[0], legacy_session_id, legacy_session_id_len); /* * Search for a matching ciphersuite */ MBEDTLS_SSL_DEBUG_BUF(3, "client hello, list of cipher suites", cipher_suites, cipher_suites_len); ssl_tls13_select_ciphersuite(ssl, cipher_suites, cipher_suites_end, 0, PSA_ALG_NONE, &handshake->ciphersuite_info); if (handshake->ciphersuite_info == NULL) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id; MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s", ((unsigned) handshake->ciphersuite_info->id), handshake->ciphersuite_info->name)); /* ... * opaque legacy_compression_methods<1..2^8-1>; * ... */ if (p[0] != 1 || p[1] != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += 2; /* ... * Extension extensions<8..2^16-1>; * ... * with Extension defined as: * struct { * ExtensionType extension_type; * opaque extension_data<0..2^16-1>; * } Extension; */ extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", p, extensions_len); handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; const unsigned char *extension_data_end; uint32_t allowed_exts = MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH; if (ssl->handshake->hello_retry_request_flag) { /* Do not accept early data extension in 2nd ClientHello */ allowed_exts &= ~MBEDTLS_SSL_EXT_MASK(EARLY_DATA); } /* RFC 8446, section 4.2.11 * * The "pre_shared_key" extension MUST be the last extension in the * ClientHello (this facilitates implementation as described below). * Servers MUST check that it is the last extension and otherwise fail * the handshake with an "illegal_parameter" alert. */ if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) { MBEDTLS_SSL_DEBUG_MSG( 3, ("pre_shared_key is not last extension.")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); extension_data_end = p + extension_data_len; ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type, allowed_exts); if (ret != 0) { return ret; } switch (extension_type) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) case MBEDTLS_TLS_EXT_SERVERNAME: MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension")); ret = mbedtls_ssl_parse_server_name_ext(ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_parse_servername_ext", ret); return ret; } break; #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: MBEDTLS_SSL_DEBUG_MSG(3, ("found supported group extension")); /* Supported Groups Extension * * When sent by the client, the "supported_groups" extension * indicates the named groups which the client supports, * ordered from most preferred to least preferred. */ ret = ssl_tls13_parse_supported_groups_ext( ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_supported_groups_ext", ret); return ret; } break; #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH*/ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) case MBEDTLS_TLS_EXT_KEY_SHARE: MBEDTLS_SSL_DEBUG_MSG(3, ("found key share extension")); /* * Key Share Extension * * When sent by the client, the "key_share" extension * contains the endpoint's cryptographic parameters for * ECDHE/DHE key establishment methods. */ ret = ssl_tls13_parse_key_shares_ext( ssl, p, extension_data_end); if (ret == SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH) { MBEDTLS_SSL_DEBUG_MSG(2, ("No usable share for key agreement.")); no_usable_share_for_key_agreement = 1; } if (ret < 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_key_shares_ext", ret); return ret; } break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: /* Already parsed */ break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES: MBEDTLS_SSL_DEBUG_MSG( 3, ("found psk key exchange modes extension")); ret = ssl_tls13_parse_key_exchange_modes_ext( ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_key_exchange_modes_ext", ret); return ret; } break; #endif case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension")); if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)) == 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* Delay processing of the PSK identity once we have * found out which algorithms to use. We keep a pointer * to the buffer and the size for later processing. */ pre_shared_key_ext = p; pre_shared_key_ext_end = extension_data_end; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ break; #if defined(MBEDTLS_SSL_ALPN) case MBEDTLS_TLS_EXT_ALPN: MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); ret = mbedtls_ssl_parse_alpn_ext(ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, ("mbedtls_ssl_parse_alpn_ext"), ret); return ret; } break; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_TLS_EXT_SIG_ALG: MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension")); ret = mbedtls_ssl_parse_sig_alg_ext( ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_parse_sig_alg_ext", ret); return ret; } break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension")); ret = mbedtls_ssl_tls13_parse_record_size_limit_ext( ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, ("mbedtls_ssl_tls13_parse_record_size_limit_ext"), ret); return ret; } break; #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type, "( ignored )"); break; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CLIENT_HELLO, handshake->received_extensions); ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, p - buf); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_add_hs_hdr_to_checksum"), ret); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* Update checksum with either * - The entire content of the CH message, if no PSK extension is present * - The content up to but excluding the PSK extension, if present. * Always parse the pre-shared-key extension when present in the * ClientHello even if some pre-requisites for PSK key exchange modes are * not met. That way we always validate the syntax of the extension. */ if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) { ret = handshake->update_checksum(ssl, buf, pre_shared_key_ext - buf); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } ret = ssl_tls13_parse_pre_shared_key_ext(ssl, pre_shared_key_ext, pre_shared_key_ext_end, cipher_suites, cipher_suites_end, &psk); if (ret == 0) { got_psk = 1; } else if (ret != MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_pre_shared_key_ext", ret); return ret; } } else #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ { ret = handshake->update_checksum(ssl, buf, p - buf); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } } /* * Determine the key exchange algorithm to use. * There are three types of key exchanges supported in TLS 1.3: * - (EC)DH with ECDSA, * - (EC)DH with PSK, * - plain PSK. * * The PSK-based key exchanges may additionally be used with 0-RTT. * * Our built-in order of preference is * 1 ) (EC)DHE-PSK Mode ( psk_ephemeral ) * 2 ) Certificate Mode ( ephemeral ) * 3 ) Plain PSK Mode ( psk ) */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (got_psk && (psk.key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL)) { handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral")); } else #endif if (ssl_tls13_key_exchange_is_ephemeral_available(ssl)) { handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL; MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral")); } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) else if (got_psk && (psk.key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK)) { handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk")); } #endif else { MBEDTLS_SSL_DEBUG_MSG( 1, ("ClientHello message misses mandatory extensions.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (handshake->key_exchange_mode & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL) { handshake->ciphersuite_info = psk.ciphersuite_info; ssl->session_negotiate->ciphersuite = psk.ciphersuite_info->id; MBEDTLS_SSL_DEBUG_MSG(2, ("Select PSK ciphersuite: %04x - %s", ((unsigned) psk.ciphersuite_info->id), psk.ciphersuite_info->name)); if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { handshake->resume = 1; } } #endif if (handshake->key_exchange_mode != MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) { hrr_required = (no_usable_share_for_key_agreement != 0); } mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info); return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK; } #if defined(MBEDTLS_SSL_EARLY_DATA) static int ssl_tls13_check_early_data_requirements(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params *handshake = ssl->handshake; if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_DISABLED) { MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, feature disabled in server configuration.")); return -1; } if (!handshake->resume) { /* We currently support early data only in the case of PSKs established via a NewSessionTicket message thus in the case of a session resumption. */ MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, not a session resumption.")); return -1; } /* RFC 8446 4.2.10 * * In order to accept early data, the server MUST have accepted a PSK cipher * suite and selected the first key offered in the client's "pre_shared_key" * extension. In addition, it MUST verify that the following values are the * same as those associated with the selected PSK: * - The TLS version number * - The selected cipher suite * - The selected ALPN [RFC7301] protocol, if any * * NOTE: * - The TLS version number is checked in * ssl_tls13_offered_psks_check_identity_match_ticket(). */ if (handshake->selected_identity != 0) { MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, the selected key in " "`pre_shared_key` is not the first one.")); return -1; } if (handshake->ciphersuite_info->id != ssl->session_negotiate->ciphersuite) { MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, the selected ciphersuite is not the one " "of the selected pre-shared key.")); return -1; } if (!mbedtls_ssl_tls13_session_ticket_allow_early_data(ssl->session_negotiate)) { MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, early_data not allowed in ticket " "permission bits.")); return -1; } #if defined(MBEDTLS_SSL_ALPN) const char *alpn = mbedtls_ssl_get_alpn_protocol(ssl); size_t alpn_len; if (alpn == NULL && ssl->session_negotiate->ticket_alpn == NULL) { return 0; } if (alpn != NULL) { alpn_len = strlen(alpn); } if (alpn == NULL || ssl->session_negotiate->ticket_alpn == NULL || alpn_len != strlen(ssl->session_negotiate->ticket_alpn) || (memcmp(alpn, ssl->session_negotiate->ticket_alpn, alpn_len) != 0)) { MBEDTLS_SSL_DEBUG_MSG(1, ("EarlyData: rejected, the selected ALPN is different " "from the one associated with the pre-shared key.")); return -1; } #endif return 0; } #endif /* MBEDTLS_SSL_EARLY_DATA */ /* Update the handshake state machine */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl, int hrr_required) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * Server certificate selection */ if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret); return ret; } #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) ssl->handshake->sni_name = NULL; ssl->handshake->sni_name_len = 0; #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls1_3_key_schedule_stage_early", ret); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) { ssl->handshake->early_data_accepted = (!hrr_required) && (ssl_tls13_check_early_data_requirements(ssl) == 0); if (ssl->handshake->early_data_accepted) { ret = mbedtls_ssl_tls13_compute_early_transform(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_compute_early_transform", ret); return ret; } } else { ssl->discard_early_data_record = hrr_required ? MBEDTLS_SSL_EARLY_DATA_DISCARD : MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD; } } #else ((void) hrr_required); #endif /* MBEDTLS_SSL_EARLY_DATA */ return 0; } /* * Main entry point from the state machine; orchestrates the otherfunctions. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf = NULL; size_t buflen = 0; int parse_client_hello_ret; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, &buf, &buflen)); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_parse_client_hello(ssl, buf, buf + buflen)); parse_client_hello_ret = ret; /* Store positive return value of * parse_client_hello, * as negative error codes are handled * by MBEDTLS_SSL_PROC_CHK_NEG. */ /* * Version 1.2 of the protocol has to be used for the handshake. * If TLS 1.2 is not supported, abort the handshake. Otherwise, set the * ssl->keep_current_message flag for the ClientHello to be kept and parsed * as a TLS 1.2 ClientHello. We also change ssl->tls_version to * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step() * will dispatch to the TLS 1.2 state machine. */ if (SSL_CLIENT_HELLO_TLS1_2 == parse_client_hello_ret) { /* Check if server supports TLS 1.2 */ if (!mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) { MBEDTLS_SSL_DEBUG_MSG( 1, ("TLS 1.2 not supported.")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } ssl->keep_current_message = 1; ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; return 0; } MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_client_hello(ssl, parse_client_hello_ret == SSL_CLIENT_HELLO_HRR_REQUIRED)); if (SSL_CLIENT_HELLO_OK == parse_client_hello_ret) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); } else { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_RETRY_REQUEST); } cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client hello")); return ret; } /* * Handler for MBEDTLS_SSL_SERVER_HELLO */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *server_randbytes = ssl->handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN; if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, server_randbytes, MBEDTLS_SERVER_HELLO_RANDOM_LEN)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_rng", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", server_randbytes, MBEDTLS_SERVER_HELLO_RANDOM_LEN); #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); #endif /* MBEDTLS_HAVE_TIME */ return ret; } /* * ssl_tls13_write_server_hello_supported_versions_ext (): * * struct { * ProtocolVersion selected_version; * } SupportedVersions; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_hello_supported_versions_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, write selected version")); /* Check if we have space to write the extension: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - selected_version (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, buf, 0); MBEDTLS_PUT_UINT16_BE(2, buf, 2); mbedtls_ssl_write_version(buf + 4, ssl->conf->transport, ssl->tls_version); MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [%04x]", ssl->tls_version)); *out_len = 6; mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS); return 0; } /* Generate and export a single key share. For hybrid KEMs, this can * be called multiple times with the different components of the hybrid. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_generate_and_write_key_share(mbedtls_ssl_context *ssl, uint16_t named_group, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; *out_len = 0; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group) || mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) { ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( ssl, named_group, buf, end, out_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange", ret); return ret; } } else #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ if (0 /* Other kinds of KEMs */) { } else { ((void) ssl); ((void) named_group); ((void) buf); ((void) end); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return ret; } /* * ssl_tls13_write_key_share_ext * * Structure of key_share extension in ServerHello: * * struct { * NamedGroup group; * opaque key_exchange<1..2^16-1>; * } KeyShareEntry; * struct { * KeyShareEntry server_share; * } KeyShareServerHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; uint16_t group = ssl->handshake->offered_group_id; unsigned char *server_share = buf + 4; size_t key_exchange_length; *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding key share extension")); MBEDTLS_SSL_DEBUG_MSG(2, ("server hello, write selected_group: %s (%04x)", mbedtls_ssl_named_group_to_str(group), group)); /* Check if we have space for header and length fields: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - group (2 bytes) * - key_exchange_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 8); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, p, 0); MBEDTLS_PUT_UINT16_BE(group, server_share, 0); p += 8; /* When we introduce PQC-ECDHE hybrids, we'll want to call this * function multiple times. */ ret = ssl_tls13_generate_and_write_key_share( ssl, group, server_share + 4, end, &key_exchange_length); if (ret != 0) { return ret; } p += key_exchange_length; MBEDTLS_PUT_UINT16_BE(key_exchange_length, server_share + 2, 0); MBEDTLS_PUT_UINT16_BE(p - server_share, buf, 2); *out_len = p - buf; mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_hrr_key_share_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { uint16_t selected_group = ssl->handshake->hrr_selected_group; /* key_share Extension * * struct { * select (Handshake.msg_type) { * ... * case hello_retry_request: * NamedGroup selected_group; * ... * }; * } KeyShare; */ *out_len = 0; /* * For a pure PSK key exchange, there is no group to agree upon. The purpose * of the HRR is then to transmit a cookie to force the client to demonstrate * reachability at their apparent network address (primarily useful for DTLS). */ if (!mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { return 0; } /* We should only send the key_share extension if the client's initial * key share was not acceptable. */ if (ssl->handshake->offered_group_id != 0) { MBEDTLS_SSL_DEBUG_MSG(4, ("Skip key_share extension in HRR")); return 0; } if (selected_group == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("no matching named group found")); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* Check if we have enough space: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - selected_group (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0); MBEDTLS_PUT_UINT16_BE(2, buf, 2); MBEDTLS_PUT_UINT16_BE(selected_group, buf, 4); MBEDTLS_SSL_DEBUG_MSG(3, ("HRR selected_group: %s (%x)", mbedtls_ssl_named_group_to_str(selected_group), selected_group)); *out_len = 6; mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); return 0; } /* * Structure of ServerHello message: * * struct { * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 * Random random; * opaque legacy_session_id_echo<0..32>; * CipherSuite cipher_suite; * uint8 legacy_compression_method = 0; * Extension extensions<6..2^16-1>; * } ServerHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_hello_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, int is_hrr) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; unsigned char *p_extensions_len; size_t output_len; *out_len = 0; ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; /* ... * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 * ... * with ProtocolVersion defined as: * uint16 ProtocolVersion; */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(0x0303, p, 0); p += 2; /* ... * Random random; * ... * with Random defined as: * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN); if (is_hrr) { memcpy(p, mbedtls_ssl_tls13_hello_retry_request_magic, MBEDTLS_SERVER_HELLO_RANDOM_LEN); } else { memcpy(p, &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], MBEDTLS_SERVER_HELLO_RANDOM_LEN); } MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; /* ... * opaque legacy_session_id_echo<0..32>; * ... */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + ssl->session_negotiate->id_len); *p++ = (unsigned char) ssl->session_negotiate->id_len; if (ssl->session_negotiate->id_len > 0) { memcpy(p, &ssl->session_negotiate->id[0], ssl->session_negotiate->id_len); p += ssl->session_negotiate->id_len; MBEDTLS_SSL_DEBUG_BUF(3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len); } /* ... * CipherSuite cipher_suite; * ... * with CipherSuite defined as: * uint8 CipherSuite[2]; */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %s ( id=%d )", mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite), ssl->session_negotiate->ciphersuite)); /* ... * uint8 legacy_compression_method = 0; * ... */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1); *p++ = MBEDTLS_SSL_COMPRESS_NULL; /* ... * Extension extensions<6..2^16-1>; * ... * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p_extensions_len = p; p += 2; if ((ret = ssl_tls13_write_server_hello_supported_versions_ext( ssl, p, end, &output_len)) != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_write_server_hello_supported_versions_ext", ret); return ret; } p += output_len; if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { if (is_hrr) { ret = ssl_tls13_write_hrr_key_share_ext(ssl, p, end, &output_len); } else { ret = ssl_tls13_write_key_share_ext(ssl, p, end, &output_len); } if (ret != 0) { return ret; } p += output_len; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (!is_hrr && mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { ret = ssl_tls13_write_server_pre_shared_key_ext(ssl, p, end, &output_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_server_pre_shared_key_ext", ret); return ret; } p += output_len; } #endif MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); MBEDTLS_SSL_DEBUG_BUF(4, "server hello extensions", p_extensions_len, p - p_extensions_len); *out_len = p - buf; MBEDTLS_SSL_DEBUG_BUF(3, "server hello", buf, *out_len); MBEDTLS_SSL_PRINT_EXTS( 3, is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST : MBEDTLS_SSL_HS_SERVER_HELLO, ssl->handshake->sent_extensions); return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_finalize_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_compute_handshake_transform", ret); return ret; } return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello")); MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_server_hello(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf, buf + buf_len, &msg_len, 0)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_finalize_server_hello(ssl)); #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /* The server sends a dummy change_cipher_spec record immediately * after its first handshake message. This may either be after * a ServerHello or a HelloRetryRequest. */ mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO); #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello")); return ret; } /* * Handler for MBEDTLS_SSL_HELLO_RETRY_REQUEST */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl->handshake->hello_retry_request_flag) { MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* * Create stateless transcript hash for HRR */ MBEDTLS_SSL_DEBUG_MSG(4, ("Reset transcript for HRR")); ret = mbedtls_ssl_reset_transcript_for_hrr(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_transcript_for_hrr", ret); return ret; } mbedtls_ssl_session_reset_msg_layer(ssl, 0); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello retry request")); MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_hello_retry_request(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf, buf + buf_len, &msg_len, 1)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len, msg_len)); ssl->handshake->hello_retry_request_flag = 1; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /* The server sends a dummy change_cipher_spec record immediately * after its first handshake message. This may either be after * a ServerHello or a HelloRetryRequest. */ mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST); #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello retry request")); return ret; } /* * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS */ /* * struct { * Extension extensions<0..2 ^ 16 - 1>; * } EncryptedExtensions; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_encrypted_extensions_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t extensions_len = 0; unsigned char *p_extensions_len; size_t output_len; *out_len = 0; MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p_extensions_len = p; p += 2; ((void) ssl); ((void) ret); ((void) output_len); #if defined(MBEDTLS_SSL_ALPN) ret = mbedtls_ssl_write_alpn_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->handshake->early_data_accepted) { ret = mbedtls_ssl_tls13_write_early_data_ext( ssl, 0, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) { ret = mbedtls_ssl_tls13_write_record_size_limit_ext( ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif extensions_len = (p - p_extensions_len) - 2; MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0); *out_len = p - buf; MBEDTLS_SSL_DEBUG_BUF(4, "encrypted extensions", buf, *out_len); MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, ssl->handshake->sent_extensions); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_encrypted_extensions(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len, msg_len; mbedtls_ssl_set_outbound_transform(ssl, ssl->handshake->transform_handshake); MBEDTLS_SSL_DEBUG_MSG( 3, ("switching to handshake transform for outbound data")); MBEDTLS_SSL_DEBUG_MSG(2, ("=> write encrypted extensions")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_encrypted_extensions_body( ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); } else { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); } #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); #endif cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write encrypted extensions")); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #define SSL_CERTIFICATE_REQUEST_SEND_REQUEST 0 #define SSL_CERTIFICATE_REQUEST_SKIP 1 /* Coordination: * Check whether a CertificateRequest message should be written. * Returns a negative code on failure, or * - SSL_CERTIFICATE_REQUEST_SEND_REQUEST * - SSL_CERTIFICATE_REQUEST_SKIP * indicating if the writing of the CertificateRequest * should be skipped or not. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl) { int authmode; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) { authmode = ssl->handshake->sni_authmode; } else #endif authmode = ssl->conf->authmode; if (authmode == MBEDTLS_SSL_VERIFY_NONE) { ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; return SSL_CERTIFICATE_REQUEST_SKIP; } ssl->handshake->certificate_request_sent = 1; return SSL_CERTIFICATE_REQUEST_SEND_REQUEST; } /* * struct { * opaque certificate_request_context<0..2^8-1>; * Extension extensions<2..2^16-1>; * } CertificateRequest; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_request_body(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t output_len = 0; unsigned char *p_extensions_len; *out_len = 0; /* Check if we have enough space: * - certificate_request_context (1 byte) * - extensions length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3); /* * Write certificate_request_context */ /* * We use a zero length context for the normal handshake * messages. For post-authentication handshake messages * this request context would be set to a non-zero value. */ *p++ = 0x0; /* * Write extensions */ /* The extensions must contain the signature_algorithms. */ p_extensions_len = p; p += 2; ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); *out_len = p - buf; MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, ssl->handshake->sent_extensions); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request")); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl)); if (ret == SSL_CERTIFICATE_REQUEST_SEND_REQUEST) { unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_request_body( ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request")); ret = 0; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request")); return ret; } /* * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_certificate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_X509_CRT_PARSE_C) if ((ssl_tls13_pick_key_cert(ssl) != 0) || mbedtls_ssl_own_cert(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("No certificate available.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ ret = mbedtls_ssl_tls13_write_certificate(ssl); if (ret != 0) { return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY); return 0; } /* * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl) { int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl); if (ret != 0) { return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * RFC 8446 section A.2 * * | Send ServerHello * | K_send = handshake * | Send EncryptedExtensions * | [Send CertificateRequest] * Can send | [Send Certificate + CertificateVerify] * app data | Send Finished * after --> | K_send = application * here +--------+--------+ * No 0-RTT | | 0-RTT * | | * K_recv = handshake | | K_recv = early data * [Skip decrypt errors] | +------> WAIT_EOED -+ * | | Recv | | Recv EndOfEarlyData * | | early data | | K_recv = handshake * | +------------+ | * | | * +> WAIT_FLIGHT2 <--------+ * | * +--------+--------+ * No auth | | Client auth * | | * | v * | WAIT_CERT * | Recv | | Recv Certificate * | empty | v * | Certificate | WAIT_CV * | | | Recv * | v | CertificateVerify * +-> WAIT_FINISHED <---+ * | Recv Finished * * * The following function handles the state changes after WAIT_FLIGHT2 in the * above diagram. We are not going to receive early data related messages * anymore, prepare to receive the first handshake message of the client * second flight. */ static void ssl_tls13_prepare_for_handshake_second_flight( mbedtls_ssl_context *ssl) { if (ssl->handshake->certificate_request_sent) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate")); MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify")); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); } } /* * Handler for MBEDTLS_SSL_SERVER_FINISHED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_finished(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_tls13_write_finished_message(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_compute_application_transform(ssl); if (ret != 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->handshake->early_data_accepted) { /* See RFC 8446 section A.2 for more information */ MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to early keys for inbound traffic. " "( K_recv = early data )")); mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_earlydata); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA); return 0; } #endif /* MBEDTLS_SSL_EARLY_DATA */ MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to handshake keys for inbound traffic " "( K_recv = handshake )")); mbedtls_ssl_set_inbound_transform(ssl, ssl->handshake->transform_handshake); ssl_tls13_prepare_for_handshake_second_flight(ssl); return 0; } #if defined(MBEDTLS_SSL_EARLY_DATA) /* * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA */ #define SSL_GOT_END_OF_EARLY_DATA 0 #define SSL_GOT_EARLY_DATA 1 /* Coordination: * Deals with the ambiguity of not knowing if the next message is an * EndOfEarlyData message or an application message containing early data. * Returns a negative code on failure, or * - SSL_GOT_END_OF_EARLY_DATA * - SSL_GOT_EARLY_DATA * indicating which message is received. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_end_of_early_data_coordinate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } ssl->keep_current_message = 1; if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_msg[0] == MBEDTLS_SSL_HS_END_OF_EARLY_DATA) { MBEDTLS_SSL_DEBUG_MSG(3, ("Received an end_of_early_data message.")); return SSL_GOT_END_OF_EARLY_DATA; } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) { if (ssl->in_offt == NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("Received early data")); /* Set the reading pointer */ ssl->in_offt = ssl->in_msg; ret = mbedtls_ssl_tls13_check_early_data_len(ssl, ssl->in_msglen); if (ret != 0) { return ret; } } return SSL_GOT_EARLY_DATA; } MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_end_of_early_data(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { /* RFC 8446 section 4.5 * * struct {} EndOfEarlyData; */ if (buf != end) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } return 0; } /* * RFC 8446 section A.2 * * | Send ServerHello * | K_send = handshake * | Send EncryptedExtensions * | [Send CertificateRequest] * Can send | [Send Certificate + CertificateVerify] * app data | Send Finished * after --> | K_send = application * here +--------+--------+ * No 0-RTT | | 0-RTT * | | * K_recv = handshake | | K_recv = early data * [Skip decrypt errors] | +------> WAIT_EOED -+ * | | Recv | | Recv EndOfEarlyData * | | early data | | K_recv = handshake * | +------------+ | * | | * +> WAIT_FLIGHT2 <--------+ * | * +--------+--------+ * No auth | | Client auth * | | * | v * | WAIT_CERT * | Recv | | Recv Certificate * | empty | v * | Certificate | WAIT_CV * | | | Recv * | v | CertificateVerify * +-> WAIT_FINISHED <---+ * | Recv Finished * * The function handles actions and state changes from 0-RTT to WAIT_FLIGHT2 in * the above diagram. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_end_of_early_data(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_process_end_of_early_data")); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_end_of_early_data_coordinate(ssl)); if (ret == SSL_GOT_END_OF_EARLY_DATA) { unsigned char *buf; size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_end_of_early_data( ssl, buf, buf + buf_len)); MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to handshake keys for inbound traffic" "( K_recv = handshake )")); mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, buf, buf_len)); ssl_tls13_prepare_for_handshake_second_flight(ssl); } else if (ret == SSL_GOT_EARLY_DATA) { ret = MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA; goto cleanup; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_process_end_of_early_data")); return ret; } #endif /* MBEDTLS_SSL_EARLY_DATA */ /* * Handler for MBEDTLS_SSL_CLIENT_FINISHED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_client_finished(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_tls13_process_finished_message(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_compute_resumption_master_secret", ret); } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); return 0; } /* * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); mbedtls_ssl_tls13_handshake_wrapup(ssl); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* TODO: Remove the check of SOME_PSK_ENABLED since SESSION_TICKETS requires * SOME_PSK_ENABLED to be enabled. Here is just to make CI happy. It is * expected to be resolved with issue#6395. */ /* Sent NewSessionTicket message only when client supports PSK */ if (mbedtls_ssl_tls13_is_some_psk_supported(ssl)) { mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); } else #endif { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); } return 0; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) /* * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET */ #define SSL_NEW_SESSION_TICKET_SKIP 0 #define SSL_NEW_SESSION_TICKET_WRITE 1 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_new_session_ticket_coordinate(mbedtls_ssl_context *ssl) { /* Check whether the use of session tickets is enabled */ if (ssl->conf->f_ticket_write == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled," " callback is not set")); return SSL_NEW_SESSION_TICKET_SKIP; } if (ssl->conf->new_session_tickets_count == 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled," " configured count is zero")); return SSL_NEW_SESSION_TICKET_SKIP; } if (ssl->handshake->new_session_tickets_count == 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: all tickets have " "been sent.")); return SSL_NEW_SESSION_TICKET_SKIP; } return SSL_NEW_SESSION_TICKET_WRITE; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl, unsigned char *ticket_nonce, size_t ticket_nonce_size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_session *session = ssl->session; mbedtls_ssl_ciphersuite_t *ciphersuite_info; psa_algorithm_t psa_hash_alg; int hash_length; MBEDTLS_SSL_DEBUG_MSG(2, ("=> prepare NewSessionTicket msg")); /* Set ticket_flags depends on the advertised psk key exchange mode */ mbedtls_ssl_tls13_session_clear_ticket_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) mbedtls_ssl_tls13_session_set_ticket_flags( session, ssl->handshake->tls13_kex_modes); #endif #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED && ssl->conf->max_early_data_size > 0) { mbedtls_ssl_tls13_session_set_ticket_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); session->max_early_data_size = ssl->conf->max_early_data_size; } #endif /* MBEDTLS_SSL_EARLY_DATA */ MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) if (session->ticket_alpn == NULL) { ret = mbedtls_ssl_session_set_ticket_alpn(session, ssl->alpn_chosen); if (ret != 0) { return ret; } } #endif /* Generate ticket_age_add */ if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, (unsigned char *) &session->ticket_age_add, sizeof(session->ticket_age_add)) != 0)) { MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_age_add", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", (unsigned int) session->ticket_age_add)); /* Generate ticket_nonce */ ret = ssl->conf->f_rng(ssl->conf->p_rng, ticket_nonce, ticket_nonce_size); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_nonce", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:", ticket_nonce, ticket_nonce_size); ciphersuite_info = (mbedtls_ssl_ciphersuite_t *) ssl->handshake->ciphersuite_info; psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); hash_length = PSA_HASH_LENGTH(psa_hash_alg); if (hash_length == -1 || (size_t) hash_length > sizeof(session->resumption_key)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* In this code the psk key length equals the length of the hash */ session->resumption_key_len = hash_length; session->ciphersuite = ciphersuite_info->id; /* Compute resumption key * * HKDF-Expand-Label( resumption_master_secret, * "resumption", ticket_nonce, Hash.length ) */ ret = mbedtls_ssl_tls13_hkdf_expand_label( psa_hash_alg, session->app_secrets.resumption_master_secret, hash_length, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption), ticket_nonce, ticket_nonce_size, session->resumption_key, hash_length); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(2, "Creating the ticket-resumed PSK failed", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK", session->resumption_key, session->resumption_key_len); MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret", session->app_secrets.resumption_master_secret, hash_length); return 0; } /* This function creates a NewSessionTicket message in the following format: * * struct { * uint32 ticket_lifetime; * uint32 ticket_age_add; * opaque ticket_nonce<0..255>; * opaque ticket<1..2^16-1>; * Extension extensions<0..2^16-2>; * } NewSessionTicket; * * The ticket inside the NewSessionTicket message is an encrypted container * carrying the necessary information so that the server is later able to * re-start the communication. * * The following fields are placed inside the ticket by the * f_ticket_write() function: * * - creation time (ticket_creation_time) * - flags (ticket_flags) * - age add (ticket_age_add) * - key (resumption_key) * - key length (resumption_key_len) * - ciphersuite (ciphersuite) * - max_early_data_size (max_early_data_size) */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, unsigned char *ticket_nonce, size_t ticket_nonce_size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; mbedtls_ssl_session *session = ssl->session; size_t ticket_len; uint32_t ticket_lifetime; unsigned char *p_extensions_len; *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write NewSessionTicket msg")); /* * ticket_lifetime 4 bytes * ticket_age_add 4 bytes * ticket_nonce 1 + ticket_nonce_size bytes * ticket >=2 bytes */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2); /* Generate ticket and ticket_lifetime */ #if defined(MBEDTLS_HAVE_TIME) session->ticket_creation_time = mbedtls_ms_time(); #endif ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket, session, p + 9 + ticket_nonce_size + 2, end, &ticket_len, &ticket_lifetime); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "write_ticket", ret); return ret; } /* RFC 8446 section 4.6.1 * * ticket_lifetime: Indicates the lifetime in seconds as a 32-bit * unsigned integer in network byte order from the time of ticket * issuance. Servers MUST NOT use any value greater than * 604800 seconds (7 days) ... */ if (ticket_lifetime > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Ticket lifetime (%u) is greater than 7 days.", (unsigned int) ticket_lifetime)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT32_BE(ticket_lifetime, p, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u", (unsigned int) ticket_lifetime)); /* Write ticket_age_add */ MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 4); MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", (unsigned int) session->ticket_age_add)); /* Write ticket_nonce */ p[8] = (unsigned char) ticket_nonce_size; if (ticket_nonce_size > 0) { memcpy(p + 9, ticket_nonce, ticket_nonce_size); } p += 9 + ticket_nonce_size; /* Write ticket */ MBEDTLS_PUT_UINT16_BE(ticket_len, p, 0); p += 2; MBEDTLS_SSL_DEBUG_BUF(4, "ticket", p, ticket_len); p += ticket_len; /* Ticket Extensions * * Extension extensions<0..2^16-2>; */ ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p_extensions_len = p; p += 2; #if defined(MBEDTLS_SSL_EARLY_DATA) if (mbedtls_ssl_tls13_session_ticket_allow_early_data(session)) { size_t output_len; if ((ret = mbedtls_ssl_tls13_write_early_data_ext( ssl, 1, p, end, &output_len)) != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_write_early_data_ext", ret); return ret; } p += output_len; } else { MBEDTLS_SSL_DEBUG_MSG( 4, ("early_data not allowed, " "skip early_data extension in NewSessionTicket")); } #endif /* MBEDTLS_SSL_EARLY_DATA */ MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); *out_len = p - buf; MBEDTLS_SSL_DEBUG_BUF(4, "ticket", buf, *out_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket")); MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, ssl->handshake->sent_extensions); return 0; } /* * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET */ static int ssl_tls13_write_new_session_ticket(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_write_new_session_ticket_coordinate(ssl)); if (ret == SSL_NEW_SESSION_TICKET_WRITE) { unsigned char ticket_nonce[MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH]; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_new_session_ticket( ssl, ticket_nonce, sizeof(ticket_nonce))); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_new_session_ticket_body( ssl, buf, buf + buf_len, &msg_len, ticket_nonce, sizeof(ticket_nonce))); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); /* Limit session tickets count to one when resumption connection. * * See document of mbedtls_ssl_conf_new_session_tickets. */ if (ssl->handshake->resume == 1) { ssl->handshake->new_session_tickets_count = 0; } else { ssl->handshake->new_session_tickets_count--; } mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH); } else { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); } cleanup: return ret; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * TLS 1.3 State Machine -- server side */ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_DEBUG_MSG(2, ("tls13 server state: %s(%d)", mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state), ssl->state)); switch (ssl->state) { /* start state */ case MBEDTLS_SSL_HELLO_REQUEST: mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); ret = 0; break; case MBEDTLS_SSL_CLIENT_HELLO: ret = ssl_tls13_process_client_hello(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_process_client_hello", ret); } break; case MBEDTLS_SSL_HELLO_RETRY_REQUEST: ret = ssl_tls13_write_hello_retry_request(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_hello_retry_request", ret); return ret; } break; case MBEDTLS_SSL_SERVER_HELLO: ret = ssl_tls13_write_server_hello(ssl); break; case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: ret = ssl_tls13_write_encrypted_extensions(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_encrypted_extensions", ret); return ret; } break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_SSL_CERTIFICATE_REQUEST: ret = ssl_tls13_write_certificate_request(ssl); break; case MBEDTLS_SSL_SERVER_CERTIFICATE: ret = ssl_tls13_write_server_certificate(ssl); break; case MBEDTLS_SSL_CERTIFICATE_VERIFY: ret = ssl_tls13_write_certificate_verify(ssl); break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * Injection of dummy-CCS's for middlebox compatibility */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret == 0) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); } break; case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret != 0) { break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); break; #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ case MBEDTLS_SSL_SERVER_FINISHED: ret = ssl_tls13_write_server_finished(ssl); break; #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_SSL_END_OF_EARLY_DATA: ret = ssl_tls13_process_end_of_early_data(ssl); break; #endif /* MBEDTLS_SSL_EARLY_DATA */ case MBEDTLS_SSL_CLIENT_FINISHED: ret = ssl_tls13_process_client_finished(ssl); break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: ret = ssl_tls13_handshake_wrapup(ssl); break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = mbedtls_ssl_tls13_process_certificate(ssl); if (ret == 0) { if (ssl->session_negotiate->peer_cert != NULL) { mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify")); mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED); } } break; case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: ret = mbedtls_ssl_tls13_process_certificate_verify(ssl); if (ret == 0) { mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED); } break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: ret = ssl_tls13_write_new_session_ticket(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_new_session_ticket ", ret); } break; case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH: /* This state is necessary to do the flush of the New Session * Ticket message written in MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET * as part of ssl_prepare_handshake_step. */ ret = 0; if (ssl->handshake->new_session_tickets_count == 0) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); } else { mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); } break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ default: MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } return ret; } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_3 */ webfakes/src/mbedtls/library/camellia.c0000644000176200001440000010413214740737024017652 0ustar liggesusers/* * Camellia implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The Camellia block cipher was designed by NTT and Mitsubishi Electric * Corporation. * * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf */ #include "common.h" #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #include "mbedtls/platform_util.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_CAMELLIA_ALT) static const unsigned char SIGMA_CHARS[6][8] = { { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } }; #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) static const unsigned char FSb[256] = { 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 }; #define SBOX1(n) FSb[(n)] #define SBOX2(n) (unsigned char) ((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) #define SBOX3(n) (unsigned char) ((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) #define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] #else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ static const unsigned char FSb[256] = { 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 }; static const unsigned char FSb2[256] = { 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 }; static const unsigned char FSb3[256] = { 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 }; static const unsigned char FSb4[256] = { 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 }; #define SBOX1(n) FSb[(n)] #define SBOX2(n) FSb2[(n)] #define SBOX3(n) FSb3[(n)] #define SBOX4(n) FSb4[(n)] #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ static const unsigned char shifts[2][4][4] = { { { 1, 1, 1, 1 }, /* KL */ { 0, 0, 0, 0 }, /* KR */ { 1, 1, 1, 1 }, /* KA */ { 0, 0, 0, 0 } /* KB */ }, { { 1, 0, 1, 1 }, /* KL */ { 1, 1, 0, 1 }, /* KR */ { 1, 1, 1, 0 }, /* KA */ { 1, 1, 0, 1 } /* KB */ } }; static const signed char indexes[2][4][20] = { { { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ }, { { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ } }; static const signed char transposes[2][20] = { { 21, 22, 23, 20, -1, -1, -1, -1, 18, 19, 16, 17, 11, 8, 9, 10, 15, 12, 13, 14 }, { 25, 26, 27, 24, 29, 30, 31, 28, 18, 19, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1 } }; /* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ #define ROTL(DEST, SRC, SHIFT) \ { \ (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ } #define FL(XL, XR, KL, KR) \ { \ (XR) = ((((XL) &(KL)) << 1) | (((XL) &(KL)) >> 31)) ^ (XR); \ (XL) = ((XR) | (KR)) ^ (XL); \ } #define FLInv(YL, YR, KL, KR) \ { \ (YL) = ((YR) | (KR)) ^ (YL); \ (YR) = ((((YL) &(KL)) << 1) | (((YL) &(KL)) >> 31)) ^ (YR); \ } #define SHIFT_AND_PLACE(INDEX, OFFSET) \ { \ TK[0] = KC[(OFFSET) * 4 + 0]; \ TK[1] = KC[(OFFSET) * 4 + 1]; \ TK[2] = KC[(OFFSET) * 4 + 2]; \ TK[3] = KC[(OFFSET) * 4 + 3]; \ \ for (i = 1; i <= 4; i++) \ if (shifts[(INDEX)][(OFFSET)][i -1]) \ ROTL(TK + i * 4, TK, (15 * i) % 32); \ \ for (i = 0; i < 20; i++) \ if (indexes[(INDEX)][(OFFSET)][i] != -1) { \ RK[indexes[(INDEX)][(OFFSET)][i]] = TK[i]; \ } \ } static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t z[2]) { uint32_t I0, I1; I0 = x[0] ^ k[0]; I1 = x[1] ^ k[1]; I0 = ((uint32_t) SBOX1(MBEDTLS_BYTE_3(I0)) << 24) | ((uint32_t) SBOX2(MBEDTLS_BYTE_2(I0)) << 16) | ((uint32_t) SBOX3(MBEDTLS_BYTE_1(I0)) << 8) | ((uint32_t) SBOX4(MBEDTLS_BYTE_0(I0))); I1 = ((uint32_t) SBOX2(MBEDTLS_BYTE_3(I1)) << 24) | ((uint32_t) SBOX3(MBEDTLS_BYTE_2(I1)) << 16) | ((uint32_t) SBOX4(MBEDTLS_BYTE_1(I1)) << 8) | ((uint32_t) SBOX1(MBEDTLS_BYTE_0(I1))); I0 ^= (I1 << 8) | (I1 >> 24); I1 ^= (I0 << 16) | (I0 >> 16); I0 ^= (I1 >> 8) | (I1 << 24); I1 ^= (I0 >> 8) | (I0 << 24); z[0] ^= I1; z[1] ^= I0; } void mbedtls_camellia_init(mbedtls_camellia_context *ctx) { memset(ctx, 0, sizeof(mbedtls_camellia_context)); } void mbedtls_camellia_free(mbedtls_camellia_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_camellia_context)); } /* * Camellia key schedule (encryption) */ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits) { int idx; size_t i; uint32_t *RK; unsigned char t[64]; uint32_t SIGMA[6][2]; uint32_t KC[16]; uint32_t TK[20]; RK = ctx->rk; memset(t, 0, 64); memset(RK, 0, sizeof(ctx->rk)); switch (keybits) { case 128: ctx->nr = 3; idx = 0; break; case 192: case 256: ctx->nr = 4; idx = 1; break; default: return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } for (i = 0; i < keybits / 8; ++i) { t[i] = key[i]; } if (keybits == 192) { for (i = 0; i < 8; i++) { t[24 + i] = ~t[16 + i]; } } /* * Prepare SIGMA values */ for (i = 0; i < 6; i++) { SIGMA[i][0] = MBEDTLS_GET_UINT32_BE(SIGMA_CHARS[i], 0); SIGMA[i][1] = MBEDTLS_GET_UINT32_BE(SIGMA_CHARS[i], 4); } /* * Key storage in KC * Order: KL, KR, KA, KB */ memset(KC, 0, sizeof(KC)); /* Store KL, KR */ for (i = 0; i < 8; i++) { KC[i] = MBEDTLS_GET_UINT32_BE(t, i * 4); } /* Generate KA */ for (i = 0; i < 4; ++i) { KC[8 + i] = KC[i] ^ KC[4 + i]; } camellia_feistel(KC + 8, SIGMA[0], KC + 10); camellia_feistel(KC + 10, SIGMA[1], KC + 8); for (i = 0; i < 4; ++i) { KC[8 + i] ^= KC[i]; } camellia_feistel(KC + 8, SIGMA[2], KC + 10); camellia_feistel(KC + 10, SIGMA[3], KC + 8); if (keybits > 128) { /* Generate KB */ for (i = 0; i < 4; ++i) { KC[12 + i] = KC[4 + i] ^ KC[8 + i]; } camellia_feistel(KC + 12, SIGMA[4], KC + 14); camellia_feistel(KC + 14, SIGMA[5], KC + 12); } /* * Generating subkeys */ /* Manipulating KL */ SHIFT_AND_PLACE(idx, 0); /* Manipulating KR */ if (keybits > 128) { SHIFT_AND_PLACE(idx, 1); } /* Manipulating KA */ SHIFT_AND_PLACE(idx, 2); /* Manipulating KB */ if (keybits > 128) { SHIFT_AND_PLACE(idx, 3); } /* Do transpositions */ for (i = 0; i < 20; i++) { if (transposes[idx][i] != -1) { RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; } } return 0; } /* * Camellia key schedule (decryption) */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits) { int idx, ret; size_t i; mbedtls_camellia_context cty; uint32_t *RK; uint32_t *SK; mbedtls_camellia_init(&cty); /* Also checks keybits */ if ((ret = mbedtls_camellia_setkey_enc(&cty, key, keybits)) != 0) { goto exit; } ctx->nr = cty.nr; idx = (ctx->nr == 4); RK = ctx->rk; SK = cty.rk + 24 * 2 + 8 * idx * 2; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4) { *RK++ = *SK++; *RK++ = *SK++; } SK -= 2; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; exit: mbedtls_camellia_free(&cty); return ret; } #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /* * Camellia-ECB block encryption/decryption */ int mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { int NR; uint32_t *RK, X[4]; if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } ((void) mode); NR = ctx->nr; RK = ctx->rk; X[0] = MBEDTLS_GET_UINT32_BE(input, 0); X[1] = MBEDTLS_GET_UINT32_BE(input, 4); X[2] = MBEDTLS_GET_UINT32_BE(input, 8); X[3] = MBEDTLS_GET_UINT32_BE(input, 12); X[0] ^= *RK++; X[1] ^= *RK++; X[2] ^= *RK++; X[3] ^= *RK++; while (NR) { --NR; camellia_feistel(X, RK, X + 2); RK += 2; camellia_feistel(X + 2, RK, X); RK += 2; camellia_feistel(X, RK, X + 2); RK += 2; camellia_feistel(X + 2, RK, X); RK += 2; camellia_feistel(X, RK, X + 2); RK += 2; camellia_feistel(X + 2, RK, X); RK += 2; if (NR) { FL(X[0], X[1], RK[0], RK[1]); RK += 2; FLInv(X[2], X[3], RK[0], RK[1]); RK += 2; } } X[2] ^= *RK++; X[3] ^= *RK++; X[0] ^= *RK++; X[1] ^= *RK++; MBEDTLS_PUT_UINT32_BE(X[2], output, 0); MBEDTLS_PUT_UINT32_BE(X[3], output, 4); MBEDTLS_PUT_UINT32_BE(X[0], output, 8); MBEDTLS_PUT_UINT32_BE(X[1], output, 12); return 0; } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * Camellia-CBC buffer encryption/decryption */ int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output) { unsigned char temp[16]; if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } if (length % 16) { return MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH; } if (mode == MBEDTLS_CAMELLIA_DECRYPT) { while (length > 0) { memcpy(temp, input, 16); mbedtls_camellia_crypt_ecb(ctx, mode, input, output); mbedtls_xor(output, output, iv, 16); memcpy(iv, temp, 16); input += 16; output += 16; length -= 16; } } else { while (length > 0) { mbedtls_xor(output, input, iv, 16); mbedtls_camellia_crypt_ecb(ctx, mode, output, output); memcpy(iv, output, 16); input += 16; output += 16; length -= 16; } } return 0; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * Camellia-CFB128 buffer encryption/decryption */ int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int c; size_t n; if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } n = *iv_off; if (n >= 16) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } if (mode == MBEDTLS_CAMELLIA_DECRYPT) { while (length--) { if (n == 0) { mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv); } c = *input++; *output++ = (unsigned char) (c ^ iv[n]); iv[n] = (unsigned char) c; n = (n + 1) & 0x0F; } } else { while (length--) { if (n == 0) { mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv); } iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++); n = (n + 1) & 0x0F; } } *iv_off = n; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * Camellia-CTR buffer encryption/decryption */ int mbedtls_camellia_crypt_ctr(mbedtls_camellia_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output) { int c, i; size_t n; n = *nc_off; if (n >= 16) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } while (length--) { if (n == 0) { mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, stream_block); for (i = 16; i > 0; i--) { if (++nonce_counter[i - 1] != 0) { break; } } } c = *input++; *output++ = (unsigned char) (c ^ stream_block[n]); n = (n + 1) & 0x0F; } *nc_off = n; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* !MBEDTLS_CAMELLIA_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * Camellia test vectors from: * * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt * (For each bitlength: Key 0, Nr 39) */ #define CAMELLIA_TESTS_ECB 2 static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = { { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, }; static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = { { { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } }, { { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } }, { { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } } }; #if defined(MBEDTLS_CIPHER_MODE_CBC) #define CAMELLIA_TESTS_CBC 3 static const unsigned char camellia_test_cbc_key[3][32] = { { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } , { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } , { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } }; static const unsigned char camellia_test_cbc_iv[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } ; static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = { { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } }; static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = { { { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } }, { { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } }, { { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } } }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * Camellia-CTR test vectors from: * * http://www.faqs.org/rfcs/rfc5528.html */ static const unsigned char camellia_test_ctr_key[3][16] = { { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } }; static const unsigned char camellia_test_ctr_nonce_counter[3][16] = { { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } }; static const unsigned char camellia_test_ctr_pt[3][48] = { { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23 } }; static const unsigned char camellia_test_ctr_ct[3][48] = { { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, 0xDF, 0x50, 0x86, 0x96 } }; static const int camellia_test_ctr_len[3] = { 16, 32, 36 }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ /* * Checkup routine */ int mbedtls_camellia_self_test(int verbose) { int i, j, u, v; unsigned char key[32]; unsigned char buf[64]; unsigned char src[16]; unsigned char dst[16]; #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char iv[16]; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) size_t offset, len; unsigned char nonce_counter[16]; unsigned char stream_block[16]; #endif int ret = 1; mbedtls_camellia_context ctx; mbedtls_camellia_init(&ctx); memset(key, 0, 32); for (j = 0; j < 6; j++) { u = j >> 1; v = j & 1; if (verbose != 0) { mbedtls_printf(" CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); } #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (v == MBEDTLS_CAMELLIA_DECRYPT) { if (verbose != 0) { mbedtls_printf("skipped\n"); } continue; } #endif for (i = 0; i < CAMELLIA_TESTS_ECB; i++) { memcpy(key, camellia_test_ecb_key[u][i], 16 + 8 * u); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (v == MBEDTLS_CAMELLIA_DECRYPT) { mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64); memcpy(src, camellia_test_ecb_cipher[u][i], 16); memcpy(dst, camellia_test_ecb_plain[i], 16); } else #endif { /* MBEDTLS_CAMELLIA_ENCRYPT */ mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64); memcpy(src, camellia_test_ecb_plain[i], 16); memcpy(dst, camellia_test_ecb_cipher[u][i], 16); } mbedtls_camellia_crypt_ecb(&ctx, v, src, buf); if (memcmp(buf, dst, 16) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * CBC mode */ for (j = 0; j < 6; j++) { u = j >> 1; v = j & 1; if (verbose != 0) { mbedtls_printf(" CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); } memcpy(src, camellia_test_cbc_iv, 16); memcpy(dst, camellia_test_cbc_iv, 16); memcpy(key, camellia_test_cbc_key[u], 16 + 8 * u); if (v == MBEDTLS_CAMELLIA_DECRYPT) { mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64); } else { mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64); } for (i = 0; i < CAMELLIA_TESTS_CBC; i++) { if (v == MBEDTLS_CAMELLIA_DECRYPT) { memcpy(iv, src, 16); memcpy(src, camellia_test_cbc_cipher[u][i], 16); memcpy(dst, camellia_test_cbc_plain[i], 16); } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ memcpy(iv, dst, 16); memcpy(src, camellia_test_cbc_plain[i], 16); memcpy(dst, camellia_test_cbc_cipher[u][i], 16); } mbedtls_camellia_crypt_cbc(&ctx, v, 16, iv, src, buf); if (memcmp(buf, dst, 16) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } } if (verbose != 0) { mbedtls_printf("passed\n"); } } #endif /* MBEDTLS_CIPHER_MODE_CBC */ if (verbose != 0) { mbedtls_printf("\n"); } #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * CTR mode */ for (i = 0; i < 6; i++) { u = i >> 1; v = i & 1; if (verbose != 0) { mbedtls_printf(" CAMELLIA-CTR-128 (%s): ", (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); } memcpy(nonce_counter, camellia_test_ctr_nonce_counter[u], 16); memcpy(key, camellia_test_ctr_key[u], 16); offset = 0; mbedtls_camellia_setkey_enc(&ctx, key, 128); if (v == MBEDTLS_CAMELLIA_DECRYPT) { len = camellia_test_ctr_len[u]; memcpy(buf, camellia_test_ctr_ct[u], len); mbedtls_camellia_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block, buf, buf); if (memcmp(buf, camellia_test_ctr_pt[u], len) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } } else { len = camellia_test_ctr_len[u]; memcpy(buf, camellia_test_ctr_pt[u], len); mbedtls_camellia_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block, buf, buf); if (memcmp(buf, camellia_test_ctr_ct[u], len) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ ret = 0; exit: mbedtls_camellia_free(&ctx); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_CAMELLIA_C */ webfakes/src/mbedtls/library/bignum_mod.c0000644000176200001440000002634214740737024020231 0ustar liggesusers/** * Modular bignum functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT) #include #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/bignum.h" #include "mbedtls/platform.h" #include "bignum_core.h" #include "bignum_mod.h" #include "bignum_mod_raw.h" #include "constant_time_internal.h" int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *p, size_t p_limbs) { if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } r->limbs = N->limbs; r->p = p; return 0; } void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r) { if (r == NULL) { return; } r->limbs = 0; r->p = NULL; } void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N) { if (N == NULL) { return; } N->p = NULL; N->limbs = 0; N->bits = 0; N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; } void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N) { if (N == NULL) { return; } switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: if (N->rep.mont.rr != NULL) { mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr, N->limbs * sizeof(mbedtls_mpi_uint)); N->rep.mont.rr = NULL; } N->rep.mont.mm = 0; break; case MBEDTLS_MPI_MOD_REP_OPT_RED: N->rep.ored.modp = NULL; break; case MBEDTLS_MPI_MOD_REP_INVALID: break; } N->p = NULL; N->limbs = 0; N->bits = 0; N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; } static int set_mont_const_square(const mbedtls_mpi_uint **X, const mbedtls_mpi_uint *A, size_t limbs) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi N; mbedtls_mpi RR; *X = NULL; mbedtls_mpi_init(&N); mbedtls_mpi_init(&RR); if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) { goto cleanup; } if (mbedtls_mpi_grow(&N, limbs)) { goto cleanup; } memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs); ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N); if (ret == 0) { *X = RR.p; RR.p = NULL; } cleanup: mbedtls_mpi_free(&N); mbedtls_mpi_free(&RR); ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0; return ret; } static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs, mbedtls_mpi_mod_rep_selector int_rep) { N->p = p; N->limbs = p_limbs; N->bits = mbedtls_mpi_core_bitlen(p, p_limbs); N->int_rep = int_rep; } int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs) { int ret = 0; standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY); N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p); ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs); if (ret != 0) { mbedtls_mpi_mod_modulus_free(N); } return ret; } int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs, mbedtls_mpi_modp_fn modp) { standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED); N->rep.ored.modp = modp; return 0; } int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N) { if (N->limbs == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL); if (T == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T); mbedtls_free(T); return 0; } int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N) { if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N); return 0; } static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *working_memory) { /* Input already in Montgomery form, so there's little to do */ mbedtls_mpi_mod_raw_inv_prime(X->p, A->p, N->p, N->limbs, N->rep.mont.rr, working_memory); return 0; } static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *working_memory) { /* Need to convert input into Montgomery form */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_mod_modulus Nmont; mbedtls_mpi_mod_modulus_init(&Nmont); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs)); /* We'll use X->p to hold the Montgomery form of the input A->p */ mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs, Nmont.rep.mont.mm, Nmont.rep.mont.rr, working_memory); mbedtls_mpi_mod_raw_inv_prime(X->p, X->p, Nmont.p, Nmont.limbs, Nmont.rep.mont.rr, working_memory); /* And convert back from Montgomery form */ mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs, Nmont.rep.mont.mm, working_memory); cleanup: mbedtls_mpi_mod_modulus_free(&Nmont); return ret; } int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_modulus *N) { if (X->limbs != N->limbs || A->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* Zero has the same value regardless of Montgomery form or not */ if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } size_t working_limbs = mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs); mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs, sizeof(mbedtls_mpi_uint)); if (working_memory == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory); break; case MBEDTLS_MPI_MOD_REP_OPT_RED: ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory); break; default: ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; break; } mbedtls_zeroize_and_free(working_memory, working_limbs * sizeof(mbedtls_mpi_uint)); return ret; } int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N) { if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N); return 0; } int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X, mbedtls_mpi_uint min, const mbedtls_mpi_mod_modulus *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (X->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng); } int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, const unsigned char *buf, size_t buflen, mbedtls_mpi_mod_ext_rep ext_rep) { int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; /* Do our best to check if r and m have been set up */ if (r->limbs == 0 || N->limbs == 0) { goto cleanup; } if (r->limbs != N->limbs) { goto cleanup; } ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep); if (ret != 0) { goto cleanup; } r->limbs = N->limbs; ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N); cleanup: return ret; } int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, unsigned char *buf, size_t buflen, mbedtls_mpi_mod_ext_rep ext_rep) { /* Do our best to check if r and m have been set up */ if (r->limbs == 0 || N->limbs == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (r->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_uint *working_memory = r->p; size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs; if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) { working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint)); if (working_memory == NULL) { ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; goto cleanup; } memcpy(working_memory, r->p, working_memory_len); ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N); if (ret != 0) { goto cleanup; } } ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep); cleanup: if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY && working_memory != NULL) { mbedtls_zeroize_and_free(working_memory, working_memory_len); } return ret; } #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */ webfakes/src/mbedtls/library/ssl_tls13_keys.h0000644000176200001440000006757214740737024021012 0ustar liggesusers/* * TLS 1.3 key schedule * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #if !defined(MBEDTLS_SSL_TLS1_3_KEYS_H) #define MBEDTLS_SSL_TLS1_3_KEYS_H /* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at * the point of use. See e.g. the definition of mbedtls_ssl_tls13_labels_union * below. */ #define MBEDTLS_SSL_TLS1_3_LABEL_LIST \ MBEDTLS_SSL_TLS1_3_LABEL(finished, "finished") \ MBEDTLS_SSL_TLS1_3_LABEL(resumption, "resumption") \ MBEDTLS_SSL_TLS1_3_LABEL(traffic_upd, "traffic upd") \ MBEDTLS_SSL_TLS1_3_LABEL(exporter, "exporter") \ MBEDTLS_SSL_TLS1_3_LABEL(key, "key") \ MBEDTLS_SSL_TLS1_3_LABEL(iv, "iv") \ MBEDTLS_SSL_TLS1_3_LABEL(c_hs_traffic, "c hs traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(c_ap_traffic, "c ap traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(c_e_traffic, "c e traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(s_hs_traffic, "s hs traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(s_ap_traffic, "s ap traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(s_e_traffic, "s e traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(e_exp_master, "e exp master") \ MBEDTLS_SSL_TLS1_3_LABEL(res_master, "res master") \ MBEDTLS_SSL_TLS1_3_LABEL(exp_master, "exp master") \ MBEDTLS_SSL_TLS1_3_LABEL(ext_binder, "ext binder") \ MBEDTLS_SSL_TLS1_3_LABEL(res_binder, "res binder") \ MBEDTLS_SSL_TLS1_3_LABEL(derived, "derived") \ MBEDTLS_SSL_TLS1_3_LABEL(client_cv, "TLS 1.3, client CertificateVerify") \ MBEDTLS_SSL_TLS1_3_LABEL(server_cv, "TLS 1.3, server CertificateVerify") #define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0 #define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED 1 #define MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL 0 #define MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION 1 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ const unsigned char name [sizeof(string) - 1]; union mbedtls_ssl_tls13_labels_union { MBEDTLS_SSL_TLS1_3_LABEL_LIST }; struct mbedtls_ssl_tls13_labels_struct { MBEDTLS_SSL_TLS1_3_LABEL_LIST }; #undef MBEDTLS_SSL_TLS1_3_LABEL extern const struct mbedtls_ssl_tls13_labels_struct mbedtls_ssl_tls13_labels; #define MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL) \ sizeof(mbedtls_ssl_tls13_labels.LABEL) #define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(LABEL) \ mbedtls_ssl_tls13_labels.LABEL, \ MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL) #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \ sizeof(union mbedtls_ssl_tls13_labels_union) /* The maximum length of HKDF contexts used in the TLS 1.3 standard. * Since contexts are always hashes of message transcripts, this can * be approximated from above by the maximum hash size. */ #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN \ PSA_HASH_MAX_SIZE /* Maximum desired length for expanded key material generated * by HKDF-Expand-Label. * * Warning: If this ever needs to be increased, the implementation * ssl_tls13_hkdf_encode_label() in ssl_tls13_keys.c needs to be * adjusted since it currently assumes that HKDF key expansion * is never used with more than 255 Bytes of output. */ #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN 255 /** * \brief The \c HKDF-Expand-Label function from * the TLS 1.3 standard RFC 8446. * * * HKDF-Expand-Label( Secret, Label, Context, Length ) = * HKDF-Expand( Secret, HkdfLabel, Length ) * * * \param hash_alg The identifier for the hash algorithm to use. * \param secret The \c Secret argument to \c HKDF-Expand-Label. * This must be a readable buffer of length * \p secret_len Bytes. * \param secret_len The length of \p secret in Bytes. * \param label The \c Label argument to \c HKDF-Expand-Label. * This must be a readable buffer of length * \p label_len Bytes. * \param label_len The length of \p label in Bytes. * \param ctx The \c Context argument to \c HKDF-Expand-Label. * This must be a readable buffer of length \p ctx_len Bytes. * \param ctx_len The length of \p context in Bytes. * \param buf The destination buffer to hold the expanded secret. * This must be a writable buffer of length \p buf_len Bytes. * \param buf_len The desired size of the expanded secret in Bytes. * * \returns \c 0 on success. * \return A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_hkdf_expand_label( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, unsigned char *buf, size_t buf_len); /** * \brief This function is part of the TLS 1.3 key schedule. * It extracts key and IV for the actual client/server traffic * from the client/server traffic secrets. * * From RFC 8446: * * * [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length) * [sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)* * * * \param hash_alg The identifier for the hash algorithm to be used * for the HKDF-based expansion of the secret. * \param client_secret The client traffic secret. * This must be a readable buffer of size * \p secret_len Bytes * \param server_secret The server traffic secret. * This must be a readable buffer of size * \p secret_len Bytes * \param secret_len Length of the secrets \p client_secret and * \p server_secret in Bytes. * \param key_len The desired length of the key to be extracted in Bytes. * \param iv_len The desired length of the IV to be extracted in Bytes. * \param keys The address of the structure holding the generated * keys and IVs. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_make_traffic_keys( psa_algorithm_t hash_alg, const unsigned char *client_secret, const unsigned char *server_secret, size_t secret_len, size_t key_len, size_t iv_len, mbedtls_ssl_key_set *keys); /** * \brief The \c Derive-Secret function from the TLS 1.3 standard RFC 8446. * * * Derive-Secret( Secret, Label, Messages ) = * HKDF-Expand-Label( Secret, Label, * Hash( Messages ), * Hash.Length ) ) * * * \param hash_alg The identifier for the hash function used for the * applications of HKDF. * \param secret The \c Secret argument to the \c Derive-Secret function. * This must be a readable buffer of length * \p secret_len Bytes. * \param secret_len The length of \p secret in Bytes. * \param label The \c Label argument to the \c Derive-Secret function. * This must be a readable buffer of length * \p label_len Bytes. * \param label_len The length of \p label in Bytes. * \param ctx The hash of the \c Messages argument to the * \c Derive-Secret function, or the \c Messages argument * itself, depending on \p ctx_hashed. * \param ctx_len The length of \p ctx in Bytes. * \param ctx_hashed This indicates whether the \p ctx contains the hash of * the \c Messages argument in the application of the * \c Derive-Secret function * (value MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED), or whether * it is the content of \c Messages itself, in which case * the function takes care of the hashing * (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED). * \param dstbuf The target buffer to write the output of * \c Derive-Secret to. This must be a writable buffer of * size \p dtsbuf_len Bytes. * \param dstbuf_len The length of \p dstbuf in Bytes. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_secret( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, int ctx_hashed, unsigned char *dstbuf, size_t dstbuf_len); /** * \brief Derive TLS 1.3 early data key material from early secret. * * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() * with the appropriate labels. * * * Early Secret * | * +-----> Derive-Secret(., "c e traffic", ClientHello) * | = client_early_traffic_secret * | * +-----> Derive-Secret(., "e exp master", ClientHello) * . = early_exporter_master_secret * . * . * * * \note To obtain the actual key and IV for the early data traffic, * the client secret derived by this function need to be * further processed by mbedtls_ssl_tls13_make_traffic_keys(). * * \note The binder key, which is also generated from the early secret, * is omitted here. Its calculation is part of the separate routine * mbedtls_ssl_tls13_create_psk_binder(). * * \param hash_alg The hash algorithm associated with the PSK for which * early data key material is being derived. * \param early_secret The early secret from which the early data key material * should be derived. This must be a readable buffer whose * length is the digest size of the hash algorithm * represented by \p md_size. * \param transcript The transcript of the handshake so far, calculated with * respect to \p hash_alg. This must be a readable buffer * whose length is the digest size of the hash algorithm * represented by \p md_size. * \param derived The address of the structure in which to store * the early data key material. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_early_secrets( psa_algorithm_t hash_alg, unsigned char const *early_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_early_secrets *derived); /** * \brief Derive TLS 1.3 handshake key material from the handshake secret. * * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() * with the appropriate labels from the standard. * * * Handshake Secret * | * +-----> Derive-Secret( ., "c hs traffic", * | ClientHello...ServerHello ) * | = client_handshake_traffic_secret * | * +-----> Derive-Secret( ., "s hs traffic", * . ClientHello...ServerHello ) * . = server_handshake_traffic_secret * . * * * \note To obtain the actual key and IV for the encrypted handshake traffic, * the client and server secret derived by this function need to be * further processed by mbedtls_ssl_tls13_make_traffic_keys(). * * \param hash_alg The hash algorithm associated with the ciphersuite * that's being used for the connection. * \param handshake_secret The handshake secret from which the handshake key * material should be derived. This must be a readable * buffer whose length is the digest size of the hash * algorithm represented by \p md_size. * \param transcript The transcript of the handshake so far, calculated * with respect to \p hash_alg. This must be a readable * buffer whose length is the digest size of the hash * algorithm represented by \p md_size. * \param derived The address of the structure in which to * store the handshake key material. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_handshake_secrets( psa_algorithm_t hash_alg, unsigned char const *handshake_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_handshake_secrets *derived); /** * \brief Derive TLS 1.3 application key material from the master secret. * * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() * with the appropriate labels from the standard. * * * Master Secret * | * +-----> Derive-Secret( ., "c ap traffic", * | ClientHello...server Finished ) * | = client_application_traffic_secret_0 * | * +-----> Derive-Secret( ., "s ap traffic", * | ClientHello...Server Finished ) * | = server_application_traffic_secret_0 * | * +-----> Derive-Secret( ., "exp master", * . ClientHello...server Finished) * . = exporter_master_secret * . * * * \note To obtain the actual key and IV for the (0-th) application traffic, * the client and server secret derived by this function need to be * further processed by mbedtls_ssl_tls13_make_traffic_keys(). * * \param hash_alg The hash algorithm associated with the ciphersuite * that's being used for the connection. * \param master_secret The master secret from which the application key * material should be derived. This must be a readable * buffer whose length is the digest size of the hash * algorithm represented by \p md_size. * \param transcript The transcript of the handshake up to and including * the ServerFinished message, calculated with respect * to \p hash_alg. This must be a readable buffer whose * length is the digest size of the hash algorithm * represented by \p hash_alg. * \param derived The address of the structure in which to * store the application key material. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_application_secrets( psa_algorithm_t hash_alg, unsigned char const *master_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_application_secrets *derived); /** * \brief Derive TLS 1.3 resumption master secret from the master secret. * * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() * with the appropriate labels from the standard. * * \param hash_alg The hash algorithm used in the application for which * key material is being derived. * \param application_secret The application secret from which the resumption master * secret should be derived. This must be a readable * buffer whose length is the digest size of the hash * algorithm represented by \p md_size. * \param transcript The transcript of the handshake up to and including * the ClientFinished message, calculated with respect * to \p hash_alg. This must be a readable buffer whose * length is the digest size of the hash algorithm * represented by \p hash_alg. * \param transcript_len The length of \p transcript in Bytes. * \param derived The address of the structure in which to * store the resumption master secret. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_resumption_master_secret( psa_algorithm_t hash_alg, unsigned char const *application_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_application_secrets *derived); /** * \brief Compute the next secret in the TLS 1.3 key schedule * * The TLS 1.3 key schedule proceeds as follows to compute * the three main secrets during the handshake: The early * secret for early data, the handshake secret for all * other encrypted handshake messages, and the master * secret for all application traffic. * * * 0 * | * v * PSK -> HKDF-Extract = Early Secret * | * v * Derive-Secret( ., "derived", "" ) * | * v * (EC)DHE -> HKDF-Extract = Handshake Secret * | * v * Derive-Secret( ., "derived", "" ) * | * v * 0 -> HKDF-Extract = Master Secret * * * Each of the three secrets in turn is the basis for further * key derivations, such as the derivation of traffic keys and IVs; * see e.g. mbedtls_ssl_tls13_make_traffic_keys(). * * This function implements one step in this evolution of secrets: * * * old_secret * | * v * Derive-Secret( ., "derived", "" ) * | * v * input -> HKDF-Extract = new_secret * * * \param hash_alg The identifier for the hash function used for the * applications of HKDF. * \param secret_old The address of the buffer holding the old secret * on function entry. If not \c NULL, this must be a * readable buffer whose size matches the output size * of the hash function represented by \p hash_alg. * If \c NULL, an all \c 0 array will be used instead. * \param input The address of the buffer holding the additional * input for the key derivation (e.g., the PSK or the * ephemeral (EC)DH secret). If not \c NULL, this must be * a readable buffer whose size \p input_len Bytes. * If \c NULL, an all \c 0 array will be used instead. * \param input_len The length of \p input in Bytes. * \param secret_new The address of the buffer holding the new secret * on function exit. This must be a writable buffer * whose size matches the output size of the hash * function represented by \p hash_alg. * This may be the same as \p secret_old. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_evolve_secret( psa_algorithm_t hash_alg, const unsigned char *secret_old, const unsigned char *input, size_t input_len, unsigned char *secret_new); /** * \brief Calculate a TLS 1.3 PSK binder. * * \param ssl The SSL context. This is used for debugging only and may * be \c NULL if MBEDTLS_DEBUG_C is disabled. * \param hash_alg The hash algorithm associated to the PSK \p psk. * \param psk The buffer holding the PSK for which to create a binder. * \param psk_len The size of \p psk in bytes. * \param psk_type This indicates whether the PSK \p psk is externally * provisioned (#MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL) or a * resumption PSK (#MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION). * \param transcript The handshake transcript up to the point where the * PSK binder calculation happens. This must be readable, * and its size must be equal to the digest size of * the hash algorithm represented by \p hash_alg. * \param result The address at which to store the PSK binder on success. * This must be writable, and its size must be equal to the * digest size of the hash algorithm represented by * \p hash_alg. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl, const psa_algorithm_t hash_alg, unsigned char const *psk, size_t psk_len, int psk_type, unsigned char const *transcript, unsigned char *result); /** * \bref Setup an SSL transform structure representing the * record protection mechanism used by TLS 1.3 * * \param transform The SSL transform structure to be created. This must have * been initialized through mbedtls_ssl_transform_init() and * not used in any other way prior to calling this function. * In particular, this function does not clean up the * transform structure prior to installing the new keys. * \param endpoint Indicates whether the transform is for the client * (value #MBEDTLS_SSL_IS_CLIENT) or the server * (value #MBEDTLS_SSL_IS_SERVER). * \param ciphersuite The numerical identifier for the ciphersuite to use. * This must be one of the identifiers listed in * ssl_ciphersuites.h. * \param traffic_keys The key material to use. No reference is stored in * the SSL transform being generated, and the caller * should destroy the key material afterwards. * \param ssl (Debug-only) The SSL context to use for debug output * in case of failure. This parameter is only needed if * #MBEDTLS_DEBUG_C is set, and is ignored otherwise. * * \return \c 0 on success. In this case, \p transform is ready to * be used with mbedtls_ssl_transform_decrypt() and * mbedtls_ssl_transform_encrypt(). * \return A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform, int endpoint, int ciphersuite, mbedtls_ssl_key_set const *traffic_keys, mbedtls_ssl_context *ssl); /* * TLS 1.3 key schedule evolutions * * Early -> Handshake -> Application * * Small wrappers around mbedtls_ssl_tls13_evolve_secret(). */ /** * \brief Begin TLS 1.3 key schedule by calculating early secret. * * The TLS 1.3 key schedule can be viewed as a simple state machine * with states Initial -> Early -> Handshake -> Application, and * this function represents the Initial -> Early transition. * * \param ssl The SSL context to operate on. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl); /** * \brief Compute TLS 1.3 resumption master secret. * * \param ssl The SSL context to operate on. This must be in * key schedule stage \c Application, see * mbedtls_ssl_tls13_key_schedule_stage_application(). * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl); /** * \brief Calculate the verify_data value for the client or server TLS 1.3 * Finished message. * * \param ssl The SSL context to operate on. This must be in * key schedule stage \c Handshake, see * mbedtls_ssl_tls13_key_schedule_stage_application(). * \param dst The address at which to write the verify_data value. * \param dst_len The size of \p dst in bytes. * \param actual_len The address at which to store the amount of data * actually written to \p dst upon success. * \param which The message to calculate the `verify_data` for: * - #MBEDTLS_SSL_IS_CLIENT for the Client's Finished message * - #MBEDTLS_SSL_IS_SERVER for the Server's Finished message * * \note Both client and server call this function twice, once to * generate their own Finished message, and once to verify the * peer's Finished message. * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl, unsigned char *dst, size_t dst_len, size_t *actual_len, int which); #if defined(MBEDTLS_SSL_EARLY_DATA) /** * \brief Compute TLS 1.3 early transform * * \param ssl The SSL context to operate on. * * \returns \c 0 on success. * \returns A negative error code on failure. * * \warning The function does not compute the early master secret. Call * mbedtls_ssl_tls13_key_schedule_stage_early() before to * call this function to generate the early master secret. * \note For a client/server endpoint, the function computes only the * encryption/decryption part of the transform as the decryption/ * encryption part is not defined by the specification (no early * traffic from the server to the client). */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_EARLY_DATA */ /** * \brief Compute TLS 1.3 handshake transform * * \param ssl The SSL context to operate on. The early secret must have been * computed. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl); /** * \brief Compute TLS 1.3 application transform * * \param ssl The SSL context to operate on. The early secret must have been * computed. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /** * \brief Export TLS 1.3 PSK from handshake context * * \param[in] ssl The SSL context to operate on. * \param[out] psk PSK output pointer. * \param[out] psk_len Length of PSK. * * \returns \c 0 if there is a configured PSK and it was exported * successfully. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl, unsigned char **psk, size_t *psk_len); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */ webfakes/src/mbedtls/library/pkcs12.c0000644000176200001440000003235614740737024017216 0ustar liggesusers/* * PKCS#12 Personal Information Exchange Syntax * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 * * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn */ #include "common.h" #if defined(MBEDTLS_PKCS12_C) #include "mbedtls/pkcs12.h" #include "mbedtls/asn1.h" #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif /* MBEDTLS_CIPHER_C */ #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #endif #include "psa_util_internal.h" #if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) static int pkcs12_parse_pbe_params(mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char **p = ¶ms->p; const unsigned char *end = params->p + params->len; /* * pkcs-12PbeParams ::= SEQUENCE { * salt OCTET STRING, * iterations INTEGER * } * */ if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } if ((ret = mbedtls_asn1_get_tag(p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret); } salt->p = *p; *p += salt->len; if ((ret = mbedtls_asn1_get_int(p, end, iterations)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret); } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } #define PKCS12_MAX_PWDLEN 128 static int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, unsigned char *key, size_t keylen, unsigned char *iv, size_t ivlen) { int ret, iterations = 0; mbedtls_asn1_buf salt; size_t i; unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; if (pwdlen > PKCS12_MAX_PWDLEN) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } memset(&salt, 0, sizeof(mbedtls_asn1_buf)); memset(&unipwd, 0, sizeof(unipwd)); if ((ret = pkcs12_parse_pbe_params(pbe_params, &salt, &iterations)) != 0) { return ret; } for (i = 0; i < pwdlen; i++) { unipwd[i * 2 + 1] = pwd[i]; } if ((ret = mbedtls_pkcs12_derivation(key, keylen, unipwd, pwdlen * 2 + 2, salt.p, salt.len, md_type, MBEDTLS_PKCS12_DERIVE_KEY, iterations)) != 0) { return ret; } if (iv == NULL || ivlen == 0) { return 0; } if ((ret = mbedtls_pkcs12_derivation(iv, ivlen, unipwd, pwdlen * 2 + 2, salt.p, salt.len, md_type, MBEDTLS_PKCS12_DERIVE_IV, iterations)) != 0) { return ret; } return 0; } #undef PKCS12_MAX_PWDLEN #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output, size_t output_size, size_t *output_len); #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output) { size_t output_len = 0; /* We assume caller of the function is providing a big enough output buffer * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees * for the output size actually being correct. */ return mbedtls_pkcs12_pbe_ext(pbe_params, mode, cipher_type, md_type, pwd, pwdlen, data, len, output, SIZE_MAX, &output_len); } #endif int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output, size_t output_size, size_t *output_len) { int ret, keylen = 0; unsigned char key[32]; unsigned char iv[16]; const mbedtls_cipher_info_t *cipher_info; mbedtls_cipher_context_t cipher_ctx; size_t iv_len = 0; size_t finish_olen = 0; unsigned int padlen = 0; if (pwd == NULL && pwdlen != 0) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (cipher_info == NULL) { return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; } keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { if (output_size < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } } if (mode == MBEDTLS_PKCS12_PBE_ENCRYPT) { padlen = cipher_info->block_size - (len % cipher_info->block_size); if (output_size < (len + padlen)) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } } iv_len = mbedtls_cipher_info_get_iv_size(cipher_info); if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, md_type, pwd, pwdlen, key, keylen, iv, iv_len)) != 0) { return ret; } mbedtls_cipher_init(&cipher_ctx); if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) { goto exit; } if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode)) != 0) { goto exit; } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) { /* PKCS12 uses CBC with PKCS7 padding */ mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) /* For historical reasons, when decrypting, this function works when * decrypting even when support for PKCS7 padding is disabled. In this * case, it ignores the padding, and so will never report a * password mismatch. */ if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { padding = MBEDTLS_PADDING_NONE; } #endif if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { goto exit; } } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ ret = mbedtls_cipher_crypt(&cipher_ctx, iv, iv_len, data, len, output, &finish_olen); if (ret == MBEDTLS_ERR_CIPHER_INVALID_PADDING) { ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; } *output_len += finish_olen; exit: mbedtls_platform_zeroize(key, sizeof(key)); mbedtls_platform_zeroize(iv, sizeof(iv)); mbedtls_cipher_free(&cipher_ctx); return ret; } #endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ static void pkcs12_fill_buffer(unsigned char *data, size_t data_len, const unsigned char *filler, size_t fill_len) { unsigned char *p = data; size_t use_len; if (filler != NULL && fill_len != 0) { while (data_len > 0) { use_len = (data_len > fill_len) ? fill_len : data_len; memcpy(p, filler, use_len); p += use_len; data_len -= use_len; } } else { /* If either of the above are not true then clearly there is nothing * that this function can do. The function should *not* be called * under either of those circumstances, as you could end up with an * incorrect output but for safety's sake, leaving the check in as * otherwise we could end up with memory corruption.*/ } } static int calculate_hashes(mbedtls_md_type_t md_type, int iterations, unsigned char *diversifier, unsigned char *salt_block, unsigned char *pwd_block, unsigned char *hash_output, int use_salt, int use_password, size_t hlen, size_t v) { int ret = -1; size_t i; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; md_info = mbedtls_md_info_from_type(md_type); if (md_info == NULL) { return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; } mbedtls_md_init(&md_ctx); if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { return ret; } // Calculate hash( diversifier || salt_block || pwd_block ) if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, diversifier, v)) != 0) { goto exit; } if (use_salt != 0) { if ((ret = mbedtls_md_update(&md_ctx, salt_block, v)) != 0) { goto exit; } } if (use_password != 0) { if ((ret = mbedtls_md_update(&md_ctx, pwd_block, v)) != 0) { goto exit; } } if ((ret = mbedtls_md_finish(&md_ctx, hash_output)) != 0) { goto exit; } // Perform remaining ( iterations - 1 ) recursive hash calculations for (i = 1; i < (size_t) iterations; i++) { if ((ret = mbedtls_md(md_info, hash_output, hlen, hash_output)) != 0) { goto exit; } } exit: mbedtls_md_free(&md_ctx); return ret; } int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, const unsigned char *pwd, size_t pwdlen, const unsigned char *salt, size_t saltlen, mbedtls_md_type_t md_type, int id, int iterations) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned int j; unsigned char diversifier[128]; unsigned char salt_block[128], pwd_block[128], hash_block[128] = { 0 }; unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; unsigned char *p; unsigned char c; int use_password = 0; int use_salt = 0; size_t hlen, use_len, v, i; // This version only allows max of 64 bytes of password or salt if (datalen > 128 || pwdlen > 64 || saltlen > 64) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } if (pwd == NULL && pwdlen != 0) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } if (salt == NULL && saltlen != 0) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } use_password = (pwd && pwdlen != 0); use_salt = (salt && saltlen != 0); hlen = mbedtls_md_get_size_from_type(md_type); if (hlen <= 32) { v = 64; } else { v = 128; } memset(diversifier, (unsigned char) id, v); if (use_salt != 0) { pkcs12_fill_buffer(salt_block, v, salt, saltlen); } if (use_password != 0) { pkcs12_fill_buffer(pwd_block, v, pwd, pwdlen); } p = data; while (datalen > 0) { if (calculate_hashes(md_type, iterations, diversifier, salt_block, pwd_block, hash_output, use_salt, use_password, hlen, v) != 0) { goto exit; } use_len = (datalen > hlen) ? hlen : datalen; memcpy(p, hash_output, use_len); datalen -= use_len; p += use_len; if (datalen == 0) { break; } // Concatenating copies of hash_output into hash_block (B) pkcs12_fill_buffer(hash_block, v, hash_output, hlen); // B += 1 for (i = v; i > 0; i--) { if (++hash_block[i - 1] != 0) { break; } } if (use_salt != 0) { // salt_block += B c = 0; for (i = v; i > 0; i--) { j = salt_block[i - 1] + hash_block[i - 1] + c; c = MBEDTLS_BYTE_1(j); salt_block[i - 1] = MBEDTLS_BYTE_0(j); } } if (use_password != 0) { // pwd_block += B c = 0; for (i = v; i > 0; i--) { j = pwd_block[i - 1] + hash_block[i - 1] + c; c = MBEDTLS_BYTE_1(j); pwd_block[i - 1] = MBEDTLS_BYTE_0(j); } } } ret = 0; exit: mbedtls_platform_zeroize(salt_block, sizeof(salt_block)); mbedtls_platform_zeroize(pwd_block, sizeof(pwd_block)); mbedtls_platform_zeroize(hash_block, sizeof(hash_block)); mbedtls_platform_zeroize(hash_output, sizeof(hash_output)); return ret; } #endif /* MBEDTLS_PKCS12_C */ webfakes/src/mbedtls/library/net_sockets.c0000644000176200001440000004316114740737024020430 0ustar liggesusers/* * TCP/IP or UDP/IP networking functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must * be set before mbedtls_config.h, which pulls in glibc's features.h indirectly. * Harmless on other platforms. */ #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200112L #endif #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 600 /* sockaddr_storage */ #endif #include "common.h" #if defined(MBEDTLS_NET_C) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ !defined(__HAIKU__) && !defined(__midipix__) #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in mbedtls_config.h" #endif #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" #include "mbedtls/error.h" #include #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) #define IS_EINTR(ret) ((ret) == WSAEINTR) #include #include #include #if (_WIN32_WINNT < 0x0501) #include #endif #if defined(_MSC_VER) #if defined(_WIN32_WCE) #pragma comment( lib, "ws2.lib" ) #else #pragma comment( lib, "ws2_32.lib" ) #endif #endif /* _MSC_VER */ #define read(fd, buf, len) recv(fd, (char *) (buf), (int) (len), 0) #define write(fd, buf, len) send(fd, (char *) (buf), (int) (len), 0) #define close(fd) closesocket(fd) static int wsa_init_done = 0; #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ #include #include #include #include #include #include #include #include #include #include #define IS_EINTR(ret) ((ret) == EINTR) #define SOCKET int #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ /* Some MS functions want int and MSVC warns if we pass size_t, * but the standard functions use socklen_t, so cast only for MSVC */ #if defined(_MSC_VER) #define MSVC_INT_CAST (int) #else #define MSVC_INT_CAST #endif #include #if defined(MBEDTLS_HAVE_TIME) #include #endif #include /* * Prepare for using the sockets interface */ static int net_prepare(void) { #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) WSADATA wsaData; if (wsa_init_done == 0) { if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { return MBEDTLS_ERR_NET_SOCKET_FAILED; } wsa_init_done = 1; } #else #if !defined(EFIX64) && !defined(EFI32) signal(SIGPIPE, SIG_IGN); #endif #endif return 0; } /* * Return 0 if the file descriptor is valid, an error otherwise. * If for_select != 0, check whether the file descriptor is within the range * allowed for fd_set used for the FD_xxx macros and the select() function. */ static int check_fd(int fd, int for_select) { if (fd < 0) { return MBEDTLS_ERR_NET_INVALID_CONTEXT; } #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) (void) for_select; #else /* A limitation of select() is that it only works with file descriptors * that are strictly less than FD_SETSIZE. This is a limitation of the * fd_set type. Error out early, because attempting to call FD_SET on a * large file descriptor is a buffer overflow on typical platforms. */ if (for_select && fd >= FD_SETSIZE) { return MBEDTLS_ERR_NET_POLL_FAILED; } #endif return 0; } /* * Initialize a context */ void mbedtls_net_init(mbedtls_net_context *ctx) { ctx->fd = -1; } /* * Initiate a TCP connection with host:port and the given protocol */ int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; struct addrinfo hints, *addr_list, *cur; if ((ret = net_prepare()) != 0) { return ret; } /* Do name resolution with both IPv6 and IPv4 */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; if (getaddrinfo(host, port, &hints, &addr_list) != 0) { return MBEDTLS_ERR_NET_UNKNOWN_HOST; } /* Try the sockaddrs until a connection succeeds */ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; for (cur = addr_list; cur != NULL; cur = cur->ai_next) { ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); if (ctx->fd < 0) { ret = MBEDTLS_ERR_NET_SOCKET_FAILED; continue; } if (connect(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) == 0) { ret = 0; break; } close(ctx->fd); ret = MBEDTLS_ERR_NET_CONNECT_FAILED; } freeaddrinfo(addr_list); return ret; } /* * Create a listening socket on bind_ip:port */ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto) { int n, ret; struct addrinfo hints, *addr_list, *cur; if ((ret = net_prepare()) != 0) { return ret; } /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; if (bind_ip == NULL) { hints.ai_flags = AI_PASSIVE; } if (getaddrinfo(bind_ip, port, &hints, &addr_list) != 0) { return MBEDTLS_ERR_NET_UNKNOWN_HOST; } /* Try the sockaddrs until a binding succeeds */ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; for (cur = addr_list; cur != NULL; cur = cur->ai_next) { ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); if (ctx->fd < 0) { ret = MBEDTLS_ERR_NET_SOCKET_FAILED; continue; } n = 1; if (setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n)) != 0) { close(ctx->fd); ret = MBEDTLS_ERR_NET_SOCKET_FAILED; continue; } if (bind(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) != 0) { close(ctx->fd); ret = MBEDTLS_ERR_NET_BIND_FAILED; continue; } /* Listen only makes sense for TCP */ if (proto == MBEDTLS_NET_PROTO_TCP) { if (listen(ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG) != 0) { close(ctx->fd); ret = MBEDTLS_ERR_NET_LISTEN_FAILED; continue; } } /* Bind was successful */ ret = 0; break; } freeaddrinfo(addr_list); return ret; } #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) /* * Check if the requested operation would be blocking on a non-blocking socket * and thus 'failed' with a negative return value. */ static int net_would_block(const mbedtls_net_context *ctx) { ((void) ctx); return WSAGetLastError() == WSAEWOULDBLOCK; } #else /* * Check if the requested operation would be blocking on a non-blocking socket * and thus 'failed' with a negative return value. * * Note: on a blocking socket this function always returns 0! */ static int net_would_block(const mbedtls_net_context *ctx) { int err = errno; /* * Never return 'WOULD BLOCK' on a blocking socket */ if ((fcntl(ctx->fd, F_GETFL) & O_NONBLOCK) != O_NONBLOCK) { errno = err; return 0; } switch (errno = err) { #if defined EAGAIN case EAGAIN: #endif #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif return 1; } return 0; } #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ /* * Accept a connection from a remote client */ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, void *client_ip, size_t buf_size, size_t *cip_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int type; struct sockaddr_storage client_addr; #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \ defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) socklen_t n = (socklen_t) sizeof(client_addr); socklen_t type_len = (socklen_t) sizeof(type); #else int n = (int) sizeof(client_addr); int type_len = (int) sizeof(type); #endif /* Is this a TCP or UDP socket? */ if (getsockopt(bind_ctx->fd, SOL_SOCKET, SO_TYPE, (void *) &type, &type_len) != 0 || (type != SOCK_STREAM && type != SOCK_DGRAM)) { return MBEDTLS_ERR_NET_ACCEPT_FAILED; } if (type == SOCK_STREAM) { /* TCP: actual accept() */ ret = client_ctx->fd = (int) accept(bind_ctx->fd, (struct sockaddr *) &client_addr, &n); } else { /* UDP: wait for a message, but keep it in the queue */ char buf[1] = { 0 }; ret = (int) recvfrom(bind_ctx->fd, buf, sizeof(buf), MSG_PEEK, (struct sockaddr *) &client_addr, &n); #if defined(_WIN32) if (ret == SOCKET_ERROR && WSAGetLastError() == WSAEMSGSIZE) { /* We know buf is too small, thanks, just peeking here */ ret = 0; } #endif } if (ret < 0) { if (net_would_block(bind_ctx) != 0) { return MBEDTLS_ERR_SSL_WANT_READ; } return MBEDTLS_ERR_NET_ACCEPT_FAILED; } /* UDP: hijack the listening socket to communicate with the client, * then bind a new socket to accept new connections */ if (type != SOCK_STREAM) { struct sockaddr_storage local_addr; int one = 1; if (connect(bind_ctx->fd, (struct sockaddr *) &client_addr, n) != 0) { return MBEDTLS_ERR_NET_ACCEPT_FAILED; } client_ctx->fd = bind_ctx->fd; bind_ctx->fd = -1; /* In case we exit early */ n = sizeof(struct sockaddr_storage); if (getsockname(client_ctx->fd, (struct sockaddr *) &local_addr, &n) != 0 || (bind_ctx->fd = (int) socket(local_addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0 || setsockopt(bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &one, sizeof(one)) != 0) { return MBEDTLS_ERR_NET_SOCKET_FAILED; } if (bind(bind_ctx->fd, (struct sockaddr *) &local_addr, n) != 0) { return MBEDTLS_ERR_NET_BIND_FAILED; } } if (client_ip != NULL) { if (client_addr.ss_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; *cip_len = sizeof(addr4->sin_addr.s_addr); if (buf_size < *cip_len) { return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL; } memcpy(client_ip, &addr4->sin_addr.s_addr, *cip_len); } else { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; *cip_len = sizeof(addr6->sin6_addr.s6_addr); if (buf_size < *cip_len) { return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL; } memcpy(client_ip, &addr6->sin6_addr.s6_addr, *cip_len); } } return 0; } /* * Set the socket blocking or non-blocking */ int mbedtls_net_set_block(mbedtls_net_context *ctx) { #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) u_long n = 0; return ioctlsocket(ctx->fd, FIONBIO, &n); #else return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) & ~O_NONBLOCK); #endif } int mbedtls_net_set_nonblock(mbedtls_net_context *ctx) { #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) u_long n = 1; return ioctlsocket(ctx->fd, FIONBIO, &n); #else return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) | O_NONBLOCK); #endif } /* * Check if data is available on the socket */ int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; struct timeval tv; fd_set read_fds; fd_set write_fds; int fd = ctx->fd; ret = check_fd(fd, 1); if (ret != 0) { return ret; } #if defined(__has_feature) #if __has_feature(memory_sanitizer) /* Ensure that memory sanitizers consider read_fds and write_fds as * initialized even on platforms such as Glibc/x86_64 where FD_ZERO * is implemented in assembly. */ memset(&read_fds, 0, sizeof(read_fds)); memset(&write_fds, 0, sizeof(write_fds)); #endif #endif FD_ZERO(&read_fds); if (rw & MBEDTLS_NET_POLL_READ) { rw &= ~MBEDTLS_NET_POLL_READ; FD_SET((SOCKET) fd, &read_fds); } FD_ZERO(&write_fds); if (rw & MBEDTLS_NET_POLL_WRITE) { rw &= ~MBEDTLS_NET_POLL_WRITE; FD_SET((SOCKET) fd, &write_fds); } if (rw != 0) { return MBEDTLS_ERR_NET_BAD_INPUT_DATA; } tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; do { ret = select(fd + 1, &read_fds, &write_fds, NULL, timeout == (uint32_t) -1 ? NULL : &tv); } while (IS_EINTR(ret)); if (ret < 0) { return MBEDTLS_ERR_NET_POLL_FAILED; } ret = 0; if (FD_ISSET(fd, &read_fds)) { ret |= MBEDTLS_NET_POLL_READ; } if (FD_ISSET(fd, &write_fds)) { ret |= MBEDTLS_NET_POLL_WRITE; } return ret; } /* * Portable usleep helper */ void mbedtls_net_usleep(unsigned long usec) { #if defined(_WIN32) Sleep((usec + 999) / 1000); #else struct timeval tv; tv.tv_sec = usec / 1000000; #if defined(__unix__) || defined(__unix) || \ (defined(__APPLE__) && defined(__MACH__)) tv.tv_usec = (suseconds_t) usec % 1000000; #else tv.tv_usec = usec % 1000000; #endif select(0, NULL, NULL, NULL, &tv); #endif } /* * Read at most 'len' characters */ int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int fd = ((mbedtls_net_context *) ctx)->fd; ret = check_fd(fd, 0); if (ret != 0) { return ret; } ret = (int) read(fd, buf, len); if (ret < 0) { if (net_would_block(ctx) != 0) { return MBEDTLS_ERR_SSL_WANT_READ; } #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) if (WSAGetLastError() == WSAECONNRESET) { return MBEDTLS_ERR_NET_CONN_RESET; } #else if (errno == EPIPE || errno == ECONNRESET) { return MBEDTLS_ERR_NET_CONN_RESET; } if (errno == EINTR) { return MBEDTLS_ERR_SSL_WANT_READ; } #endif return MBEDTLS_ERR_NET_RECV_FAILED; } return ret; } /* * Read at most 'len' characters, blocking for at most 'timeout' ms */ int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; struct timeval tv; fd_set read_fds; int fd = ((mbedtls_net_context *) ctx)->fd; ret = check_fd(fd, 1); if (ret != 0) { return ret; } FD_ZERO(&read_fds); FD_SET((SOCKET) fd, &read_fds); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; ret = select(fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv); /* Zero fds ready means we timed out */ if (ret == 0) { return MBEDTLS_ERR_SSL_TIMEOUT; } if (ret < 0) { #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) if (WSAGetLastError() == WSAEINTR) { return MBEDTLS_ERR_SSL_WANT_READ; } #else if (errno == EINTR) { return MBEDTLS_ERR_SSL_WANT_READ; } #endif return MBEDTLS_ERR_NET_RECV_FAILED; } /* This call will not block */ return mbedtls_net_recv(ctx, buf, len); } /* * Write at most 'len' characters */ int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int fd = ((mbedtls_net_context *) ctx)->fd; ret = check_fd(fd, 0); if (ret != 0) { return ret; } ret = (int) write(fd, buf, len); if (ret < 0) { if (net_would_block(ctx) != 0) { return MBEDTLS_ERR_SSL_WANT_WRITE; } #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) if (WSAGetLastError() == WSAECONNRESET) { return MBEDTLS_ERR_NET_CONN_RESET; } #else if (errno == EPIPE || errno == ECONNRESET) { return MBEDTLS_ERR_NET_CONN_RESET; } if (errno == EINTR) { return MBEDTLS_ERR_SSL_WANT_WRITE; } #endif return MBEDTLS_ERR_NET_SEND_FAILED; } return ret; } /* * Close the connection */ void mbedtls_net_close(mbedtls_net_context *ctx) { if (ctx->fd == -1) { return; } close(ctx->fd); ctx->fd = -1; } /* * Gracefully close the connection */ void mbedtls_net_free(mbedtls_net_context *ctx) { if (ctx == NULL || ctx->fd == -1) { return; } shutdown(ctx->fd, 2); close(ctx->fd); ctx->fd = -1; } #endif /* MBEDTLS_NET_C */ webfakes/src/mbedtls/library/entropy_poll.h0000644000176200001440000000324114740737024020635 0ustar liggesusers/** * \file entropy_poll.h * * \brief Platform-specific and custom entropy polling functions */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ENTROPY_POLL_H #define MBEDTLS_ENTROPY_POLL_H #include "mbedtls/build_info.h" #include #ifdef __cplusplus extern "C" { #endif /* * Default thresholds for built-in sources, in bytes */ #define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ #if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) #define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ #endif #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) /** * \brief Platform-specific entropy poll callback */ int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen); #endif #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) /** * \brief Entropy poll callback for a hardware source * * \warning This is not provided by Mbed TLS! * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in mbedtls_config.h. * * \note This must accept NULL as its first argument. */ int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen); #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) /** * \brief Entropy poll callback for a non-volatile seed file * * \note This must accept NULL as its first argument. */ int mbedtls_nv_seed_poll(void *data, unsigned char *output, size_t len, size_t *olen); #endif #ifdef __cplusplus } #endif #endif /* entropy_poll.h */ webfakes/src/mbedtls/library/sha3.c0000644000176200001440000005333614740737024016752 0ustar liggesusers/* * FIPS-202 compliant SHA3 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-3 Secure Hash Standard was published by NIST in 2015. * * https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf */ #include "common.h" #if defined(MBEDTLS_SHA3_C) /* * These macros select manually unrolled implementations of parts of the main permutation function. * * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot * from manually unrolling at higher optimisation levels. * * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and * x86-64. */ #if !defined(MBEDTLS_SHA3_THETA_UNROLL) #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names #endif #if !defined(MBEDTLS_SHA3_CHI_UNROLL) #if defined(__OPTIMIZE_SIZE__) #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names #else #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names #endif #endif #if !defined(MBEDTLS_SHA3_PI_UNROLL) #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names #endif #if !defined(MBEDTLS_SHA3_RHO_UNROLL) #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names #endif #include "mbedtls/sha3.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_SELF_TEST) #include "mbedtls/platform.h" #endif /* MBEDTLS_SELF_TEST */ #define XOR_BYTE 0x6 /* Precomputed masks for the iota transform. * * Each round uses a 64-bit mask value. In each mask values, only * bits whose position is of the form 2^k-1 can be set, thus only * 7 of 64 bits of the mask need to be known for each mask value. * * We use a compressed encoding of the mask where bits 63, 31 and 15 * are moved to bits 4-6. This allows us to make each mask value * 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with * perhaps a little variation due to alignment). Decompressing this * requires a little code, but much less than the savings on the table. * * The impact on performance depends on the platform and compiler. * There's a bit more computation, but less memory bandwidth. A quick * benchmark on x86_64 shows a 7% speed improvement with GCC and a * 5% speed penalty with Clang, compared to the naive uint64_t[24] table. * YMMV. */ /* Helper macro to set the values of the higher bits in unused low positions */ #define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4) static const uint8_t iota_r_packed[24] = { H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00, H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09, H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a, H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03, H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x80, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x08, }; #undef H static const uint32_t rho[6] = { 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832 }; static const uint32_t pi[6] = { 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916 }; #define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right #define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \ } while (0) #define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3))) #define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0) /* The permutation function. */ static void keccak_f1600(mbedtls_sha3_context *ctx) { uint64_t lane[5]; uint64_t *s = ctx->state; int i; for (int round = 0; round < 24; round++) { uint64_t t; /* Theta */ #if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names for (i = 0; i < 5; i++) { lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; } for (i = 0; i < 5; i++) { t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63); s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t; } #else lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; t = lane[4] ^ ROTR64(lane[1], 63); s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t; t = lane[0] ^ ROTR64(lane[2], 63); s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t; t = lane[1] ^ ROTR64(lane[3], 63); s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t; t = lane[2] ^ ROTR64(lane[4], 63); s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t; t = lane[3] ^ ROTR64(lane[0], 63); s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t; #endif /* Rho */ for (i = 1; i < 25; i += 4) { uint32_t r = rho[(i - 1) >> 2]; #if MBEDTLS_SHA3_RHO_UNROLL == 0 for (int j = i; j < i + 4; j++) { uint8_t r8 = (uint8_t) (r >> 24); r <<= 8; s[j] = ROTR64(s[j], r8); } #else s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r)); s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r)); s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r)); s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r)); #endif } /* Pi */ t = s[1]; #if MBEDTLS_SHA3_PI_UNROLL == 0 for (i = 0; i < 24; i += 4) { uint32_t p = pi[i >> 2]; for (unsigned j = 0; j < 4; j++) { SWAP(s[p & 0xff], t); p >>= 8; } } #else uint32_t p = pi[0]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[1]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[2]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[3]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[4]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[5]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); #endif /* Chi */ #if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names for (i = 0; i <= 20; i += 5) { lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2]; lane[3] = s[i + 3]; lane[4] = s[i + 4]; s[i + 0] ^= (~lane[1]) & lane[2]; s[i + 1] ^= (~lane[2]) & lane[3]; s[i + 2] ^= (~lane[3]) & lane[4]; s[i + 3] ^= (~lane[4]) & lane[0]; s[i + 4] ^= (~lane[0]) & lane[1]; } #else lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4]; s[0] ^= (~lane[1]) & lane[2]; s[1] ^= (~lane[2]) & lane[3]; s[2] ^= (~lane[3]) & lane[4]; s[3] ^= (~lane[4]) & lane[0]; s[4] ^= (~lane[0]) & lane[1]; lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9]; s[5] ^= (~lane[1]) & lane[2]; s[6] ^= (~lane[2]) & lane[3]; s[7] ^= (~lane[3]) & lane[4]; s[8] ^= (~lane[4]) & lane[0]; s[9] ^= (~lane[0]) & lane[1]; lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14]; s[10] ^= (~lane[1]) & lane[2]; s[11] ^= (~lane[2]) & lane[3]; s[12] ^= (~lane[3]) & lane[4]; s[13] ^= (~lane[4]) & lane[0]; s[14] ^= (~lane[0]) & lane[1]; lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19]; s[15] ^= (~lane[1]) & lane[2]; s[16] ^= (~lane[2]) & lane[3]; s[17] ^= (~lane[3]) & lane[4]; s[18] ^= (~lane[4]) & lane[0]; s[19] ^= (~lane[0]) & lane[1]; lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24]; s[20] ^= (~lane[1]) & lane[2]; s[21] ^= (~lane[2]) & lane[3]; s[22] ^= (~lane[3]) & lane[4]; s[23] ^= (~lane[4]) & lane[0]; s[24] ^= (~lane[0]) & lane[1]; #endif /* Iota */ /* Decompress the round masks (see definition of rc) */ s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 | (iota_r_packed[round] & 0x20ull) << 26 | (iota_r_packed[round] & 0x10ull) << 11 | (iota_r_packed[round] & 0x8f)); } } void mbedtls_sha3_init(mbedtls_sha3_context *ctx) { memset(ctx, 0, sizeof(mbedtls_sha3_context)); } void mbedtls_sha3_free(mbedtls_sha3_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context)); } void mbedtls_sha3_clone(mbedtls_sha3_context *dst, const mbedtls_sha3_context *src) { *dst = *src; } /* * SHA-3 context setup */ int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id) { switch (id) { case MBEDTLS_SHA3_224: ctx->olen = 224 / 8; ctx->max_block_size = 1152 / 8; break; case MBEDTLS_SHA3_256: ctx->olen = 256 / 8; ctx->max_block_size = 1088 / 8; break; case MBEDTLS_SHA3_384: ctx->olen = 384 / 8; ctx->max_block_size = 832 / 8; break; case MBEDTLS_SHA3_512: ctx->olen = 512 / 8; ctx->max_block_size = 576 / 8; break; default: return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA; } memset(ctx->state, 0, sizeof(ctx->state)); ctx->index = 0; return 0; } /* * SHA-3 process buffer */ int mbedtls_sha3_update(mbedtls_sha3_context *ctx, const uint8_t *input, size_t ilen) { if (ilen >= 8) { // 8-byte align index int align_bytes = 8 - (ctx->index % 8); if (align_bytes) { for (; align_bytes > 0; align_bytes--) { ABSORB(ctx, ctx->index, *input++); ilen--; ctx->index++; } if ((ctx->index = ctx->index % ctx->max_block_size) == 0) { keccak_f1600(ctx); } } // process input in 8-byte chunks while (ilen >= 8) { ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0)); input += 8; ilen -= 8; if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) { keccak_f1600(ctx); } } } // handle remaining bytes while (ilen-- > 0) { ABSORB(ctx, ctx->index, *input++); if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) { keccak_f1600(ctx); } } return 0; } int mbedtls_sha3_finish(mbedtls_sha3_context *ctx, uint8_t *output, size_t olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Catch SHA-3 families, with fixed output length */ if (ctx->olen > 0) { if (ctx->olen > olen) { ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA; goto exit; } olen = ctx->olen; } ABSORB(ctx, ctx->index, XOR_BYTE); ABSORB(ctx, ctx->max_block_size - 1, 0x80); keccak_f1600(ctx); ctx->index = 0; while (olen-- > 0) { *output++ = SQUEEZE(ctx, ctx->index); if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) { keccak_f1600(ctx); } } ret = 0; exit: mbedtls_sha3_free(ctx); return ret; } /* * output = SHA-3( input buffer ) */ int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input, size_t ilen, uint8_t *output, size_t olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha3_context ctx; mbedtls_sha3_init(&ctx); /* Sanity checks are performed in every mbedtls_sha3_xxx() */ if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) { goto exit; } if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) { goto exit; } exit: mbedtls_sha3_free(&ctx); return ret; } /**************** Self-tests ****************/ #if defined(MBEDTLS_SELF_TEST) static const unsigned char test_data[2][4] = { "", "abc", }; static const size_t test_data_len[2] = { 0, /* "" */ 3 /* "abc" */ }; static const unsigned char test_hash_sha3_224[2][28] = { { /* "" */ 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7, 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB, 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F, 0x5B, 0x5A, 0x6B, 0xC7 }, { /* "abc" */ 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A, 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F, 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD, 0x73, 0xB4, 0x6F, 0xDF } }; static const unsigned char test_hash_sha3_256[2][32] = { { /* "" */ 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66, 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62, 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA, 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A }, { /* "abc" */ 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2, 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD, 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B, 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32 } }; static const unsigned char test_hash_sha3_384[2][48] = { { /* "" */ 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D, 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85, 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61, 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A, 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47, 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04 }, { /* "abc" */ 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9, 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D, 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25, 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2, 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5, 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25 } }; static const unsigned char test_hash_sha3_512[2][64] = { { /* "" */ 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5, 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E, 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59, 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6, 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C, 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58, 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3, 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26 }, { /* "abc" */ 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A, 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E, 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D, 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E, 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9, 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40, 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5, 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0 } }; static const unsigned char long_kat_hash_sha3_224[28] = { 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E, 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C, 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7, 0xA7, 0xFD, 0x65, 0x3C }; static const unsigned char long_kat_hash_sha3_256[32] = { 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34, 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6, 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99, 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1 }; static const unsigned char long_kat_hash_sha3_384[48] = { 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53, 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD, 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E, 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84, 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42, 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40 }; static const unsigned char long_kat_hash_sha3_512[64] = { 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB, 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E, 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF, 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59, 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE, 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66, 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E, 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87 }; static int mbedtls_sha3_kat_test(int verbose, const char *type_name, mbedtls_sha3_id id, int test_num) { uint8_t hash[64]; int result; result = mbedtls_sha3(id, test_data[test_num], test_data_len[test_num], hash, sizeof(hash)); if (result != 0) { if (verbose != 0) { mbedtls_printf(" %s test %d error code: %d\n", type_name, test_num, result); } return result; } switch (id) { case MBEDTLS_SHA3_224: result = memcmp(hash, test_hash_sha3_224[test_num], 28); break; case MBEDTLS_SHA3_256: result = memcmp(hash, test_hash_sha3_256[test_num], 32); break; case MBEDTLS_SHA3_384: result = memcmp(hash, test_hash_sha3_384[test_num], 48); break; case MBEDTLS_SHA3_512: result = memcmp(hash, test_hash_sha3_512[test_num], 64); break; default: break; } if (0 != result) { if (verbose != 0) { mbedtls_printf(" %s test %d failed\n", type_name, test_num); } return -1; } if (verbose != 0) { mbedtls_printf(" %s test %d passed\n", type_name, test_num); } return 0; } static int mbedtls_sha3_long_kat_test(int verbose, const char *type_name, mbedtls_sha3_id id) { mbedtls_sha3_context ctx; unsigned char buffer[1000]; unsigned char hash[64]; int result = 0; memset(buffer, 'a', 1000); if (verbose != 0) { mbedtls_printf(" %s long KAT test ", type_name); } mbedtls_sha3_init(&ctx); result = mbedtls_sha3_starts(&ctx, id); if (result != 0) { if (verbose != 0) { mbedtls_printf("setup failed\n "); } } /* Process 1,000,000 (one million) 'a' characters */ for (int i = 0; i < 1000; i++) { result = mbedtls_sha3_update(&ctx, buffer, 1000); if (result != 0) { if (verbose != 0) { mbedtls_printf("update error code: %i\n", result); } goto cleanup; } } result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash)); if (result != 0) { if (verbose != 0) { mbedtls_printf("finish error code: %d\n", result); } goto cleanup; } switch (id) { case MBEDTLS_SHA3_224: result = memcmp(hash, long_kat_hash_sha3_224, 28); break; case MBEDTLS_SHA3_256: result = memcmp(hash, long_kat_hash_sha3_256, 32); break; case MBEDTLS_SHA3_384: result = memcmp(hash, long_kat_hash_sha3_384, 48); break; case MBEDTLS_SHA3_512: result = memcmp(hash, long_kat_hash_sha3_512, 64); break; default: break; } if (result != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } } if (verbose != 0) { mbedtls_printf("passed\n"); } cleanup: mbedtls_sha3_free(&ctx); return result; } int mbedtls_sha3_self_test(int verbose) { int i; /* SHA-3 Known Answer Tests (KAT) */ for (i = 0; i < 2; i++) { if (0 != mbedtls_sha3_kat_test(verbose, "SHA3-224", MBEDTLS_SHA3_224, i)) { return 1; } if (0 != mbedtls_sha3_kat_test(verbose, "SHA3-256", MBEDTLS_SHA3_256, i)) { return 1; } if (0 != mbedtls_sha3_kat_test(verbose, "SHA3-384", MBEDTLS_SHA3_384, i)) { return 1; } if (0 != mbedtls_sha3_kat_test(verbose, "SHA3-512", MBEDTLS_SHA3_512, i)) { return 1; } } /* SHA-3 long KAT tests */ if (0 != mbedtls_sha3_long_kat_test(verbose, "SHA3-224", MBEDTLS_SHA3_224)) { return 1; } if (0 != mbedtls_sha3_long_kat_test(verbose, "SHA3-256", MBEDTLS_SHA3_256)) { return 1; } if (0 != mbedtls_sha3_long_kat_test(verbose, "SHA3-384", MBEDTLS_SHA3_384)) { return 1; } if (0 != mbedtls_sha3_long_kat_test(verbose, "SHA3-512", MBEDTLS_SHA3_512)) { return 1; } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SHA3_C */ webfakes/src/mbedtls/library/ssl_tls13_client.c0000644000176200001440000032241714740737024021300 0ustar liggesusers/* * TLS 1.3 client-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) #include #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "ssl_misc.h" #include "ssl_client.h" #include "ssl_tls13_keys.h" #include "ssl_debug_helpers.h" #include "mbedtls/psa_util.h" #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif /* Write extensions */ /* * ssl_tls13_write_supported_versions_ext(): * * struct { * ProtocolVersion versions<2..254>; * } SupportedVersions; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_supported_versions_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; unsigned char versions_len = (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) ? 4 : 2; *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported versions extension")); /* Check if we have space to write the extension: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - versions_length (1 byte ) * - versions (2 or 4 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + versions_len); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, p, 0); MBEDTLS_PUT_UINT16_BE(versions_len + 1, p, 2); p += 4; /* Length of versions */ *p++ = versions_len; /* Write values of supported versions. * They are defined by the configuration. * Currently, we advertise only TLS 1.3 or both TLS 1.3 and TLS 1.2. */ mbedtls_ssl_write_version(p, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_VERSION_TLS1_3); MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:4]")); if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) { mbedtls_ssl_write_version(p + 2, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_VERSION_TLS1_2); MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:3]")); } *out_len = 5 + versions_len; mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { ((void) ssl); MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2); if (mbedtls_ssl_read_version(buf, ssl->conf->transport) != MBEDTLS_SSL_VERSION_TLS1_3) { MBEDTLS_SSL_DEBUG_MSG(1, ("unexpected version")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } if (&buf[2] != end) { MBEDTLS_SSL_DEBUG_MSG( 1, ("supported_versions ext data length incorrect")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } return 0; } #if defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_alpn_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { const unsigned char *p = buf; const unsigned char *end = buf + len; size_t protocol_name_list_len, protocol_name_len; const unsigned char *protocol_name_list_end; /* If we didn't send it, the server shouldn't send it */ if (ssl->conf->alpn_list == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; * * the "ProtocolNameList" MUST contain exactly one "ProtocolName" */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len); protocol_name_list_end = p + protocol_name_list_len; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, 1); protocol_name_len = *p++; /* Check that the server chosen protocol was in our list and save it */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, protocol_name_len); for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) { if (protocol_name_len == strlen(*alpn) && memcmp(p, *alpn, protocol_name_len) == 0) { ssl->alpn_chosen = *alpn; return 0; } } return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* MBEDTLS_SSL_ALPN */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_reset_key_share(mbedtls_ssl_context *ssl) { uint16_t group_id = ssl->handshake->offered_group_id; if (group_id == 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) || mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Destroy generated private key. */ status = psa_destroy_key(ssl->handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); return ret; } ssl->handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return 0; } else #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ if (0 /* other KEMs? */) { /* Do something */ } return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * Functions for writing key_share extension. */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_get_default_group_id(mbedtls_ssl_context *ssl, uint16_t *group_id) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); /* Pick first available ECDHE group compatible with TLS 1.3 */ if (group_list == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *group_list != 0; group_list++) { #if defined(PSA_WANT_ALG_ECDH) if ((mbedtls_ssl_get_psa_curve_info_from_tls_id( *group_list, NULL, NULL) == PSA_SUCCESS) && mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) { *group_id = *group_list; return 0; } #endif #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) { *group_id = *group_list; return 0; } #endif } #else ((void) ssl); ((void) group_id); #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ return ret; } /* * ssl_tls13_write_key_share_ext * * Structure of key_share extension in ClientHello: * * struct { * NamedGroup group; * opaque key_exchange<1..2^16-1>; * } KeyShareEntry; * struct { * KeyShareEntry client_shares<0..2^16-1>; * } KeyShareClientHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; unsigned char *client_shares; /* Start of client_shares */ size_t client_shares_len; /* Length of client_shares */ uint16_t group_id; int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; *out_len = 0; /* Check if we have space for header and length fields: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - client_shares_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); p += 6; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello: adding key share extension")); /* HRR could already have requested something else. */ group_id = ssl->handshake->offered_group_id; if (!mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) && !mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) { MBEDTLS_SSL_PROC_CHK(ssl_tls13_get_default_group_id(ssl, &group_id)); } /* * Dispatch to type-specific key generation function. * * So far, we're only supporting ECDHE. With the introduction * of PQC KEMs, we'll want to have multiple branches, one per * type of KEM, and dispatch to the corresponding crypto. And * only one key share entry is allowed. */ client_shares = p; #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) || mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) { /* Pointer to group */ unsigned char *group = p; /* Length of key_exchange */ size_t key_exchange_len = 0; /* Check there is space for header of KeyShareEntry * - group (2 bytes) * - key_exchange_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); p += 4; ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( ssl, group_id, p, end, &key_exchange_len); p += key_exchange_len; if (ret != 0) { return ret; } /* Write group */ MBEDTLS_PUT_UINT16_BE(group_id, group, 0); /* Write key_exchange_length */ MBEDTLS_PUT_UINT16_BE(key_exchange_len, group, 2); } else #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ if (0 /* other KEMs? */) { /* Do something */ } else { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Length of client_shares */ client_shares_len = p - client_shares; if (client_shares_len == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("No key share defined.")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Write extension_type */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0); /* Write extension_data_length */ MBEDTLS_PUT_UINT16_BE(client_shares_len + 2, buf, 2); /* Write client_shares_length */ MBEDTLS_PUT_UINT16_BE(client_shares_len, buf, 4); /* Update offered_group_id field */ ssl->handshake->offered_group_id = group_id; /* Output the total length of key_share extension. */ *out_len = p - buf; MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, key_share extension", buf, *out_len); mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); cleanup: return ret; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ /* * ssl_tls13_parse_hrr_key_share_ext() * Parse key_share extension in Hello Retry Request * * struct { * NamedGroup selected_group; * } KeyShareHelloRetryRequest; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) const unsigned char *p = buf; int selected_group; int found = 0; const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); if (group_list == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } MBEDTLS_SSL_DEBUG_BUF(3, "key_share extension", p, end - buf); /* Read selected_group */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); selected_group = MBEDTLS_GET_UINT16_BE(p, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("selected_group ( %d )", selected_group)); /* Upon receipt of this extension in a HelloRetryRequest, the client * MUST first verify that the selected_group field corresponds to a * group which was provided in the "supported_groups" extension in the * original ClientHello. * The supported_group was based on the info in ssl->conf->group_list. * * If the server provided a key share that was not sent in the ClientHello * then the client MUST abort the handshake with an "illegal_parameter" alert. */ for (; *group_list != 0; group_list++) { #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) { if ((mbedtls_ssl_get_psa_curve_info_from_tls_id( *group_list, NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) || *group_list != selected_group) { found = 1; break; } } #endif /* PSA_WANT_ALG_ECDH */ #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) { found = 1; break; } #endif /* PSA_WANT_ALG_FFDH */ } /* Client MUST verify that the selected_group field does not * correspond to a group which was provided in the "key_share" * extension in the original ClientHello. If the server sent an * HRR message with a key share already provided in the * ClientHello then the client MUST abort the handshake with * an "illegal_parameter" alert. */ if (found == 0 || selected_group == ssl->handshake->offered_group_id) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid key share in HRR")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* Remember server's preference for next ClientHello */ ssl->handshake->offered_group_id = selected_group; return 0; #else /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ (void) ssl; (void) buf; (void) end; return MBEDTLS_ERR_SSL_BAD_CONFIG; #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ } /* * ssl_tls13_parse_key_share_ext() * Parse key_share extension in Server Hello * * struct { * KeyShareEntry server_share; * } KeyShareServerHello; * struct { * NamedGroup group; * opaque key_exchange<1..2^16-1>; * } KeyShareEntry; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_key_share_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; uint16_t group, offered_group; /* ... * NamedGroup group; (2 bytes) * ... */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); group = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Check that the chosen group matches the one we offered. */ offered_group = ssl->handshake->offered_group_id; if (offered_group != group) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Invalid server key share, our group %u, their group %u", (unsigned) offered_group, (unsigned) group)); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) || mbedtls_ssl_tls13_named_group_is_ffdh(group)) { MBEDTLS_SSL_DEBUG_MSG(2, ("DHE group name: %s", mbedtls_ssl_named_group_to_str(group))); ret = mbedtls_ssl_tls13_read_public_xxdhe_share(ssl, p, end - p); if (ret != 0) { return ret; } } else #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ if (0 /* other KEMs? */) { /* Do something */ } else { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return ret; } /* * ssl_tls13_parse_cookie_ext() * Parse cookie extension in Hello Retry Request * * struct { * opaque cookie<1..2^16-1>; * } Cookie; * * When sending a HelloRetryRequest, the server MAY provide a "cookie" * extension to the client (this is an exception to the usual rule that * the only extensions that may be sent are those that appear in the * ClientHello). When sending the new ClientHello, the client MUST copy * the contents of the extension received in the HelloRetryRequest into * a "cookie" extension in the new ClientHello. Clients MUST NOT use * cookies in their initial ClientHello in subsequent connections. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_cookie_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { uint16_t cookie_len; const unsigned char *p = buf; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Retrieve length field of cookie */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); cookie_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cookie_len); MBEDTLS_SSL_DEBUG_BUF(3, "cookie extension", p, cookie_len); mbedtls_free(handshake->cookie); handshake->cookie_len = 0; handshake->cookie = mbedtls_calloc(1, cookie_len); if (handshake->cookie == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc failed ( %ud bytes )", cookie_len)); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(handshake->cookie, p, cookie_len); handshake->cookie_len = cookie_len; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_cookie_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; *out_len = 0; mbedtls_ssl_handshake_params *handshake = ssl->handshake; if (handshake->cookie == NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("no cookie to send; skip extension")); return 0; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", handshake->cookie, handshake->cookie_len); MBEDTLS_SSL_CHK_BUF_PTR(p, end, handshake->cookie_len + 6); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding cookie extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_COOKIE, p, 0); MBEDTLS_PUT_UINT16_BE(handshake->cookie_len + 2, p, 2); MBEDTLS_PUT_UINT16_BE(handshake->cookie_len, p, 4); p += 6; /* Cookie */ memcpy(p, handshake->cookie, handshake->cookie_len); *out_len = handshake->cookie_len + 6; mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_COOKIE); return 0; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* * ssl_tls13_write_psk_key_exchange_modes_ext() structure: * * enum { psk_ke( 0 ), psk_dhe_ke( 1 ), ( 255 ) } PskKeyExchangeMode; * * struct { * PskKeyExchangeMode ke_modes<1..255>; * } PskKeyExchangeModes; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; int ke_modes_len = 0; ((void) ke_modes_len); *out_len = 0; /* Skip writing extension if no PSK key exchange mode * is enabled in the config. */ if (!mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) { MBEDTLS_SSL_DEBUG_MSG(3, ("skip psk_key_exchange_modes extension")); return 0; } /* Require 7 bytes of data, otherwise fail, * even if extension might be shorter. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7); MBEDTLS_SSL_DEBUG_MSG( 3, ("client hello, adding psk_key_exchange_modes extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, p, 0); /* Skip extension length (2 bytes) and * ke_modes length (1 byte) for now. */ p += 5; if (mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl)) { *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE; ke_modes_len++; MBEDTLS_SSL_DEBUG_MSG(4, ("Adding PSK-ECDHE key exchange mode")); } if (mbedtls_ssl_conf_tls13_is_psk_enabled(ssl)) { *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE; ke_modes_len++; MBEDTLS_SSL_DEBUG_MSG(4, ("Adding pure PSK key exchange mode")); } /* Now write the extension and ke_modes length */ MBEDTLS_PUT_UINT16_BE(ke_modes_len + 1, buf, 2); buf[4] = ke_modes_len; *out_len = p - buf; mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES); return 0; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) static psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = NULL; ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); if (ciphersuite_info != NULL) { return mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); } return PSA_ALG_NONE; } static int ssl_tls13_has_configured_ticket(mbedtls_ssl_context *ssl) { mbedtls_ssl_session *session = ssl->session_negotiate; return ssl->handshake->resume && session != NULL && session->ticket != NULL && mbedtls_ssl_conf_tls13_is_kex_mode_enabled( ssl, mbedtls_ssl_tls13_session_get_ticket_flags( session, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL)); } #if defined(MBEDTLS_SSL_EARLY_DATA) static int ssl_tls13_early_data_has_valid_ticket(mbedtls_ssl_context *ssl) { mbedtls_ssl_session *session = ssl->session_negotiate; return ssl->handshake->resume && session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && mbedtls_ssl_tls13_session_ticket_allow_early_data(session) && mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, session->ciphersuite); } #endif MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_ticket_get_identity(mbedtls_ssl_context *ssl, psa_algorithm_t *hash_alg, const unsigned char **identity, size_t *identity_len) { mbedtls_ssl_session *session = ssl->session_negotiate; if (!ssl_tls13_has_configured_ticket(ssl)) { return -1; } *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite); *identity = session->ticket; *identity_len = session->ticket_len; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_ticket_get_psk(mbedtls_ssl_context *ssl, psa_algorithm_t *hash_alg, const unsigned char **psk, size_t *psk_len) { mbedtls_ssl_session *session = ssl->session_negotiate; if (!ssl_tls13_has_configured_ticket(ssl)) { return -1; } *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite); *psk = session->resumption_key; *psk_len = session->resumption_key_len; return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_psk_get_identity(mbedtls_ssl_context *ssl, psa_algorithm_t *hash_alg, const unsigned char **identity, size_t *identity_len) { if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) { return -1; } *hash_alg = PSA_ALG_SHA_256; *identity = ssl->conf->psk_identity; *identity_len = ssl->conf->psk_identity_len; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_psk_get_psk(mbedtls_ssl_context *ssl, psa_algorithm_t *hash_alg, const unsigned char **psk, size_t *psk_len) { if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) { return -1; } *hash_alg = PSA_ALG_SHA_256; *psk = ssl->conf->psk; *psk_len = ssl->conf->psk_len; return 0; } static int ssl_tls13_get_configured_psk_count(mbedtls_ssl_context *ssl) { int configured_psk_count = 0; #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl_tls13_has_configured_ticket(ssl)) { MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket is configured")); configured_psk_count++; } #endif if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) { MBEDTLS_SSL_DEBUG_MSG(3, ("PSK is configured")); configured_psk_count++; } return configured_psk_count; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_identity(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, const unsigned char *identity, size_t identity_len, uint32_t obfuscated_ticket_age, size_t *out_len) { ((void) ssl); *out_len = 0; /* * - identity_len (2 bytes) * - identity (psk_identity_len bytes) * - obfuscated_ticket_age (4 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6 + identity_len); MBEDTLS_PUT_UINT16_BE(identity_len, buf, 0); memcpy(buf + 2, identity, identity_len); MBEDTLS_PUT_UINT32_BE(obfuscated_ticket_age, buf, 2 + identity_len); MBEDTLS_SSL_DEBUG_BUF(4, "write identity", buf, 6 + identity_len); *out_len = 6 + identity_len; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_binder(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, int psk_type, psa_algorithm_t hash_alg, const unsigned char *psk, size_t psk_len, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char binder_len; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len = 0; *out_len = 0; binder_len = PSA_HASH_LENGTH(hash_alg); /* * - binder_len (1 bytes) * - binder (binder_len bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1 + binder_len); buf[0] = binder_len; /* Get current state of handshake transcript. */ ret = mbedtls_ssl_get_handshake_transcript( ssl, mbedtls_md_type_from_psa_alg(hash_alg), transcript, sizeof(transcript), &transcript_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_create_psk_binder(ssl, hash_alg, psk, psk_len, psk_type, transcript, buf + 1); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_create_psk_binder", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(4, "write binder", buf, 1 + binder_len); *out_len = 1 + binder_len; return 0; } /* * mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext() structure: * * struct { * opaque identity<1..2^16-1>; * uint32 obfuscated_ticket_age; * } PskIdentity; * * opaque PskBinderEntry<32..255>; * * struct { * PskIdentity identities<7..2^16-1>; * PskBinderEntry binders<33..2^16-1>; * } OfferedPsks; * * struct { * select (Handshake.msg_type) { * case client_hello: OfferedPsks; * ... * }; * } PreSharedKeyExtension; * */ int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, size_t *binders_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int configured_psk_count = 0; unsigned char *p = buf; psa_algorithm_t hash_alg = PSA_ALG_NONE; const unsigned char *identity; size_t identity_len; size_t l_binders_len = 0; size_t output_len; *out_len = 0; *binders_len = 0; /* Check if we have any PSKs to offer. If no, skip pre_shared_key */ configured_psk_count = ssl_tls13_get_configured_psk_count(ssl); if (configured_psk_count == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("skip pre_shared_key extensions")); return 0; } MBEDTLS_SSL_DEBUG_MSG(4, ("Pre-configured PSK number = %d", configured_psk_count)); /* Check if we have space to write the extension, binders included. * - extension_type (2 bytes) * - extension_data_len (2 bytes) * - identities_len (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); p += 6; #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl_tls13_ticket_get_identity( ssl, &hash_alg, &identity, &identity_len) == 0) { #if defined(MBEDTLS_HAVE_TIME) mbedtls_ms_time_t now = mbedtls_ms_time(); mbedtls_ssl_session *session = ssl->session_negotiate; /* The ticket age has been checked to be smaller than the * `ticket_lifetime` in ssl_prepare_client_hello() which is smaller than * 7 days (enforced in ssl_tls13_parse_new_session_ticket()) . Thus the * cast to `uint32_t` of the ticket age is safe. */ uint32_t obfuscated_ticket_age = (uint32_t) (now - session->ticket_reception_time); obfuscated_ticket_age += session->ticket_age_add; ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, obfuscated_ticket_age, &output_len); #else ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, 0, &output_len); #endif /* MBEDTLS_HAVE_TIME */ if (ret != 0) { return ret; } p += output_len; l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg); } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ if (ssl_tls13_psk_get_identity( ssl, &hash_alg, &identity, &identity_len) == 0) { ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, 0, &output_len); if (ret != 0) { return ret; } p += output_len; l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg); } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding pre_shared_key extension, " "omitting PSK binder list")); /* Take into account the two bytes for the length of the binders. */ l_binders_len += 2; /* Check if there is enough space for binders */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, l_binders_len); /* * - extension_type (2 bytes) * - extension_data_len (2 bytes) * - identities_len (2 bytes) */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, buf, 0); MBEDTLS_PUT_UINT16_BE(p - buf - 4 + l_binders_len, buf, 2); MBEDTLS_PUT_UINT16_BE(p - buf - 6, buf, 4); *out_len = (p - buf) + l_binders_len; *binders_len = l_binders_len; MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key identities", buf, p - buf); return 0; } int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; psa_algorithm_t hash_alg = PSA_ALG_NONE; const unsigned char *psk; size_t psk_len; size_t output_len; /* Check if we have space to write binders_len. * - binders_len (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p += 2; #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) { ret = ssl_tls13_write_binder(ssl, p, end, MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION, hash_alg, psk, psk_len, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ if (ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) { ret = ssl_tls13_write_binder(ssl, p, end, MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL, hash_alg, psk, psk_len, &output_len); if (ret != 0) { return ret; } p += output_len; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding PSK binder list.")); /* * - binders_len (2 bytes) */ MBEDTLS_PUT_UINT16_BE(p - buf - 2, buf, 0); MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key binders", buf, p - buf); mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY); return 0; } /* * struct { * opaque identity<1..2^16-1>; * uint32 obfuscated_ticket_age; * } PskIdentity; * * opaque PskBinderEntry<32..255>; * * struct { * * select (Handshake.msg_type) { * ... * case server_hello: uint16 selected_identity; * }; * * } PreSharedKeyExtension; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_server_pre_shared_key_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int selected_identity; const unsigned char *psk; size_t psk_len; psa_algorithm_t hash_alg; MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2); selected_identity = MBEDTLS_GET_UINT16_BE(buf, 0); ssl->handshake->selected_identity = (uint16_t) selected_identity; MBEDTLS_SSL_DEBUG_MSG(3, ("selected_identity = %d", selected_identity)); if (selected_identity >= ssl_tls13_get_configured_psk_count(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid PSK identity.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (selected_identity == 0 && ssl_tls13_has_configured_ticket(ssl)) { ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len); } else #endif if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) { ret = ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len); } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (ret != 0) { return ret; } if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac) != hash_alg) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Invalid ciphersuite for external psk.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); return ret; } return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t ext_len; *out_len = 0; ret = mbedtls_ssl_tls13_crypto_init(ssl); if (ret != 0) { return ret; } /* Write supported_versions extension * * Supported Versions Extension is mandatory with TLS 1.3. */ ret = ssl_tls13_write_supported_versions_ext(ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; /* Echo the cookie if the server provided one in its preceding * HelloRetryRequest message. */ ret = ssl_tls13_write_cookie_ext(ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) ret = mbedtls_ssl_tls13_write_record_size_limit_ext( ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { ret = ssl_tls13_write_key_share_ext(ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; } #endif #if defined(MBEDTLS_SSL_EARLY_DATA) /* In the first ClientHello, write the early data indication extension if * necessary and update the early data state. * If an HRR has been received and thus we are currently writing the * second ClientHello, the second ClientHello must not contain an early * data extension and the early data state must stay as it is: * MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT or * MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED. */ if (!ssl->handshake->hello_retry_request_flag) { if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) && ssl_tls13_early_data_has_valid_ticket(ssl) && ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { ret = mbedtls_ssl_tls13_write_early_data_ext( ssl, 0, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT; } else { ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT; } } #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* For PSK-based key exchange we need the pre_shared_key extension * and the psk_key_exchange_modes extension. * * The pre_shared_key extension MUST be the last extension in the * ClientHello. Servers MUST check that it is the last extension and * otherwise fail the handshake with an "illegal_parameter" alert. * * Add the psk_key_exchange_modes extension. */ ret = ssl_tls13_write_psk_key_exchange_modes_ext(ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; #endif *out_len = p - buf; return 0; } int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl) { ((void) ssl); #if defined(MBEDTLS_SSL_EARLY_DATA) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_algorithm_t hash_alg = PSA_ALG_NONE; const unsigned char *psk; size_t psk_len; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Set hs psk for early data when writing the first psk")); ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_ticket_get_psk", ret); return ret; } ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); return ret; } /* * Early data are going to be encrypted using the ciphersuite * associated with the pre-shared key used for the handshake. * Note that if the server rejects early data, the handshake * based on the pre-shared key may complete successfully * with a selected ciphersuite different from the ciphersuite * associated with the pre-shared key. Only the hashes of the * two ciphersuites have to be the same. In that case, the * encrypted handshake data and application data are * encrypted using a different ciphersuite than the one used for * the rejected early data. */ ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite); ssl->handshake->ciphersuite_info = ciphersuite_info; /* Enable psk and psk_ephemeral to make stage early happy */ ssl->handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; /* Start the TLS 1.3 key schedule: * Set the PSK and derive early secret. */ ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret); return ret; } /* Derive early data key material */ ret = mbedtls_ssl_tls13_compute_early_transform(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_compute_early_transform", ret); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO); #else MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to early data keys for outbound traffic")); mbedtls_ssl_set_outbound_transform( ssl, ssl->handshake->transform_earlydata); ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE; #endif } #endif /* MBEDTLS_SSL_EARLY_DATA */ return 0; } /* * Functions for parsing and processing Server Hello */ /** * \brief Detect if the ServerHello contains a supported_versions extension * or not. * * \param[in] ssl SSL context * \param[in] buf Buffer containing the ServerHello message * \param[in] end End of the buffer containing the ServerHello message * * \return 0 if the ServerHello does not contain a supported_versions extension * \return 1 if the ServerHello contains a supported_versions extension * \return A negative value if an error occurred while parsing the ServerHello. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_is_supported_versions_ext_present( mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t legacy_session_id_echo_len; const unsigned char *supported_versions_data; const unsigned char *supported_versions_data_end; /* * Check there is enough data to access the legacy_session_id_echo vector * length: * - legacy_version 2 bytes * - random MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes * - legacy_session_id_echo length 1 byte */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 3); p += MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2; legacy_session_id_echo_len = *p; /* * Jump to the extensions, jumping over: * - legacy_session_id_echo (legacy_session_id_echo_len + 1) bytes * - cipher_suite 2 bytes * - legacy_compression_method 1 byte */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len + 4); p += legacy_session_id_echo_len + 4; return mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( ssl, p, end, &supported_versions_data, &supported_versions_data_end); } /* Returns a negative value on failure, and otherwise * - 1 if the last eight bytes of the ServerHello random bytes indicate that * the server is TLS 1.3 capable but negotiating TLS 1.2 or below. * - 0 otherwise */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_is_downgrade_negotiation(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { /* First seven bytes of the magic downgrade strings, see RFC 8446 4.1.3 */ static const unsigned char magic_downgrade_string[] = { 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44 }; const unsigned char *last_eight_bytes_of_random; unsigned char last_byte_of_random; MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2); last_eight_bytes_of_random = buf + 2 + MBEDTLS_SERVER_HELLO_RANDOM_LEN - 8; if (memcmp(last_eight_bytes_of_random, magic_downgrade_string, sizeof(magic_downgrade_string)) == 0) { last_byte_of_random = last_eight_bytes_of_random[7]; return last_byte_of_random == 0 || last_byte_of_random == 1; } return 0; } /* Returns a negative value on failure, and otherwise * - SSL_SERVER_HELLO or * - SSL_SERVER_HELLO_HRR * to indicate which message is expected and to be parsed next. */ #define SSL_SERVER_HELLO 0 #define SSL_SERVER_HELLO_HRR 1 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_server_hello_is_hrr(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { /* Check whether this message is a HelloRetryRequest ( HRR ) message. * * Server Hello and HRR are only distinguished by Random set to the * special value of the SHA-256 of "HelloRetryRequest". * * struct { * ProtocolVersion legacy_version = 0x0303; * Random random; * opaque legacy_session_id_echo<0..32>; * CipherSuite cipher_suite; * uint8 legacy_compression_method = 0; * Extension extensions<6..2^16-1>; * } ServerHello; * */ MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2 + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)); if (memcmp(buf + 2, mbedtls_ssl_tls13_hello_retry_request_magic, sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)) == 0) { return SSL_SERVER_HELLO_HRR; } return SSL_SERVER_HELLO; } /* * Returns a negative value on failure, and otherwise * - SSL_SERVER_HELLO or * - SSL_SERVER_HELLO_HRR or * - SSL_SERVER_HELLO_TLS1_2 */ #define SSL_SERVER_HELLO_TLS1_2 2 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_is_supported_versions_ext_present( ssl, buf, end)); if (ret == 0) { MBEDTLS_SSL_PROC_CHK_NEG( ssl_tls13_is_downgrade_negotiation(ssl, buf, end)); /* If the server is negotiating TLS 1.2 or below and: * . we did not propose TLS 1.2 or * . the server responded it is TLS 1.3 capable but negotiating a lower * version of the protocol and thus we are under downgrade attack * abort the handshake with an "illegal parameter" alert. */ if (handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* * Version 1.2 of the protocol has been negotiated, set the * ssl->keep_current_message flag for the ServerHello to be kept and * parsed as a TLS 1.2 ServerHello. We also change ssl->tls_version to * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step() * will dispatch to the TLS 1.2 state machine. */ ssl->keep_current_message = 1; ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, (size_t) (end - buf))); if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { ret = ssl_tls13_reset_key_share(ssl); if (ret != 0) { return ret; } } return SSL_SERVER_HELLO_TLS1_2; } ssl->session_negotiate->tls_version = ssl->tls_version; ssl->session_negotiate->endpoint = ssl->conf->endpoint; handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; ret = ssl_server_hello_is_hrr(ssl, buf, end); switch (ret) { case SSL_SERVER_HELLO: MBEDTLS_SSL_DEBUG_MSG(2, ("received ServerHello message")); break; case SSL_SERVER_HELLO_HRR: MBEDTLS_SSL_DEBUG_MSG(2, ("received HelloRetryRequest message")); /* If a client receives a second HelloRetryRequest in the same * connection (i.e., where the ClientHello was itself in response * to a HelloRetryRequest), it MUST abort the handshake with an * "unexpected_message" alert. */ if (handshake->hello_retry_request_flag) { MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* * Clients must abort the handshake with an "illegal_parameter" * alert if the HelloRetryRequest would not result in any change * in the ClientHello. * In a PSK only key exchange that what we expect. */ if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Unexpected HRR in pure PSK key exchange.")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } handshake->hello_retry_request_flag = 1; break; } cleanup: return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_check_server_hello_session_id_echo(mbedtls_ssl_context *ssl, const unsigned char **buf, const unsigned char *end) { const unsigned char *p = *buf; size_t legacy_session_id_echo_len; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); legacy_session_id_echo_len = *p++; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len); /* legacy_session_id_echo */ if (ssl->session_negotiate->id_len != legacy_session_id_echo_len || memcmp(ssl->session_negotiate->id, p, legacy_session_id_echo_len) != 0) { MBEDTLS_SSL_DEBUG_BUF(3, "Expected Session ID", ssl->session_negotiate->id, ssl->session_negotiate->id_len); MBEDTLS_SSL_DEBUG_BUF(3, "Received Session ID", p, legacy_session_id_echo_len); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += legacy_session_id_echo_len; *buf = p; MBEDTLS_SSL_DEBUG_BUF(3, "Session ID", ssl->session_negotiate->id, ssl->session_negotiate->id_len); return 0; } /* Parse ServerHello message and configure context * * struct { * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 * Random random; * opaque legacy_session_id_echo<0..32>; * CipherSuite cipher_suite; * uint8 legacy_compression_method = 0; * Extension extensions<6..2^16-1>; * } ServerHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end, int is_hrr) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; mbedtls_ssl_handshake_params *handshake = ssl->handshake; size_t extensions_len; const unsigned char *extensions_end; uint16_t cipher_suite; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; int fatal_alert = 0; uint32_t allowed_extensions_mask; int hs_msg_type = is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST : MBEDTLS_SSL_HS_SERVER_HELLO; /* * Check there is space for minimal fields * * - legacy_version ( 2 bytes) * - random (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes) * - legacy_session_id_echo ( 1 byte ), minimum size * - cipher_suite ( 2 bytes) * - legacy_compression_method ( 1 byte ) */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6); MBEDTLS_SSL_DEBUG_BUF(4, "server hello", p, end - p); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", p, 2); /* ... * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 * ... * with ProtocolVersion defined as: * uint16 ProtocolVersion; */ if (mbedtls_ssl_read_version(p, ssl->conf->transport) != MBEDTLS_SSL_VERSION_TLS1_2) { MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; goto cleanup; } p += 2; /* ... * Random random; * ... * with Random defined as: * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; */ if (!is_hrr) { memcpy(&handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); } p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; /* ... * opaque legacy_session_id_echo<0..32>; * ... */ if (ssl_tls13_check_server_hello_session_id_echo(ssl, &p, end) != 0) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; goto cleanup; } /* ... * CipherSuite cipher_suite; * ... * with CipherSuite defined as: * uint8 CipherSuite[2]; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); /* * Check whether this ciphersuite is valid and offered. */ if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, ssl->tls_version, ssl->tls_version) != 0) || !mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } /* * If we received an HRR before and that the proposed selected * ciphersuite in this server hello is not the same as the one * proposed in the HRR, we abort the handshake and send an * "illegal_parameter" alert. */ else if ((!is_hrr) && handshake->hello_retry_request_flag && (cipher_suite != ssl->session_negotiate->ciphersuite)) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid ciphersuite(%04x) parameter", cipher_suite)); goto cleanup; } /* Configure ciphersuites */ mbedtls_ssl_optimize_checksum(ssl, ciphersuite_info); handshake->ciphersuite_info = ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: ( %04x ) - %s", cipher_suite, ciphersuite_info->name)); #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); #endif /* MBEDTLS_HAVE_TIME */ /* ... * uint8 legacy_compression_method = 0; * ... */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); if (p[0] != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method")); fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; goto cleanup; } p++; /* ... * Extension extensions<6..2^16-1>; * ... * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Check extensions do not go beyond the buffer of data. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; MBEDTLS_SSL_DEBUG_BUF(3, "server hello extensions", p, extensions_len); handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; allowed_extensions_mask = is_hrr ? MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR : MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; const unsigned char *extension_data_end; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); extension_data_end = p + extension_data_len; ret = mbedtls_ssl_tls13_check_received_extension( ssl, hs_msg_type, extension_type, allowed_extensions_mask); if (ret != 0) { return ret; } switch (extension_type) { case MBEDTLS_TLS_EXT_COOKIE: ret = ssl_tls13_parse_cookie_ext(ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_parse_cookie_ext", ret); goto cleanup; } break; case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: ret = ssl_tls13_parse_supported_versions_ext(ssl, p, extension_data_end); if (ret != 0) { goto cleanup; } break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension")); if ((ret = ssl_tls13_parse_server_pre_shared_key_ext( ssl, p, extension_data_end)) != 0) { MBEDTLS_SSL_DEBUG_RET( 1, ("ssl_tls13_parse_server_pre_shared_key_ext"), ret); return ret; } break; #endif case MBEDTLS_TLS_EXT_KEY_SHARE: MBEDTLS_SSL_DEBUG_MSG(3, ("found key_shares extension")); if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT; goto cleanup; } if (is_hrr) { ret = ssl_tls13_parse_hrr_key_share_ext(ssl, p, extension_data_end); } else { ret = ssl_tls13_parse_key_share_ext(ssl, p, extension_data_end); } if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_parse_key_share_ext", ret); goto cleanup; } break; default: ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, hs_msg_type, handshake->received_extensions); cleanup: if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION); ret = MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } else if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); ret = MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } return ret; } #if defined(MBEDTLS_DEBUG_C) static const char *ssl_tls13_get_kex_mode_str(int mode) { switch (mode) { case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK: return "psk"; case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL: return "ephemeral"; case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL: return "psk_ephemeral"; default: return "unknown mode"; } } #endif /* MBEDTLS_DEBUG_C */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Determine the key exchange mode: * 1) If both the pre_shared_key and key_share extensions were received * then the key exchange mode is PSK with EPHEMERAL. * 2) If only the pre_shared_key extension was received then the key * exchange mode is PSK-only. * 3) If only the key_share extension was received then the key * exchange mode is EPHEMERAL-only. */ switch (handshake->received_extensions & (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE))) { /* Only the pre_shared_key extension was received */ case MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY): handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; break; /* Only the key_share extension was received */ case MBEDTLS_SSL_EXT_MASK(KEY_SHARE): handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL; break; /* Both the pre_shared_key and key_share extensions were received */ case (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE)): handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; break; /* Neither pre_shared_key nor key_share extension was received */ default: MBEDTLS_SSL_DEBUG_MSG(1, ("Unknown key exchange.")); ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; goto cleanup; } if (!mbedtls_ssl_conf_tls13_is_kex_mode_enabled( ssl, handshake->key_exchange_mode)) { ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; MBEDTLS_SSL_DEBUG_MSG( 2, ("Key exchange mode(%s) is not supported.", ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode))); goto cleanup; } MBEDTLS_SSL_DEBUG_MSG( 3, ("Selected key exchange mode: %s", ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode))); /* Start the TLS 1.3 key scheduling if not already done. * * If we proposed early data then we have already derived an * early secret using the selected PSK and its associated hash. * It means that if the negotiated key exchange mode is psk or * psk_ephemeral, we have already correctly computed the * early secret and thus we do not do it again. In all other * cases we compute it here. */ #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT || handshake->key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL) #endif { ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret); goto cleanup; } } ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_compute_handshake_transform", ret); goto cleanup; } mbedtls_ssl_set_inbound_transform(ssl, handshake->transform_handshake); MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic")); ssl->session_in = ssl->session_negotiate; cleanup: if (ret != 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); } return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_postprocess_hrr(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_session_reset_msg_layer(ssl, 0); /* * We are going to re-generate a shared secret corresponding to the group * selected by the server, which is different from the group for which we * generated a shared secret in the first client hello. * Thus, reset the shared secret. */ ret = ssl_tls13_reset_key_share(ssl); if (ret != 0) { return ret; } ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id; #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) { ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED; } #endif return 0; } /* * Wait and parse ServerHello handshake message. * Handler for MBEDTLS_SSL_SERVER_HELLO */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf = NULL; size_t buf_len = 0; int is_hrr = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> %s", __func__)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); ret = ssl_tls13_preprocess_server_hello(ssl, buf, buf + buf_len); if (ret < 0) { goto cleanup; } else { is_hrr = (ret == SSL_SERVER_HELLO_HRR); } if (ret == SSL_SERVER_HELLO_TLS1_2) { ret = 0; goto cleanup; } MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_server_hello(ssl, buf, buf + buf_len, is_hrr)); if (is_hrr) { MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_reset_transcript_for_hrr(ssl)); } MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, buf_len)); if (is_hrr) { MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_hrr(ssl)); #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /* If not offering early data, the client sends a dummy CCS record * immediately before its second flight. This may either be before * its second ClientHello or before its encrypted handshake flight. */ mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO); #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ } else { MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_server_hello(ssl)); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); } cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= %s ( %s )", __func__, is_hrr ? "HelloRetryRequest" : "ServerHello")); return ret; } /* * * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS * * The EncryptedExtensions message contains any extensions which * should be protected, i.e., any which are not needed to establish * the cryptographic context. */ /* Parse EncryptedExtensions message * struct { * Extension extensions<0..2^16-1>; * } EncryptedExtensions; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_encrypted_extensions(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = 0; size_t extensions_len; const unsigned char *p = buf; const unsigned char *extensions_end; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; MBEDTLS_SSL_DEBUG_BUF(3, "encrypted extensions", p, extensions_len); handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; /* * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, extension_type, MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE); if (ret != 0) { return ret; } switch (extension_type) { #if defined(MBEDTLS_SSL_ALPN) case MBEDTLS_TLS_EXT_ALPN: MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); if ((ret = ssl_tls13_parse_alpn_ext( ssl, p, (size_t) extension_data_len)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_TLS_EXT_EARLY_DATA: if (extension_data_len != 0) { /* The message must be empty. */ MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } break; #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension")); ret = mbedtls_ssl_tls13_parse_record_size_limit_ext( ssl, p, p + extension_data_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, ("mbedtls_ssl_tls13_parse_record_size_limit_ext"), ret); return ret; } break; #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, extension_type, "( ignored )"); break; } p += extension_data_len; } if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) && (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH))) { MBEDTLS_SSL_DEBUG_MSG(3, ( "Record size limit extension cannot be used with max fragment length extension")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, handshake->received_extensions); /* Check that we consumed all the message. */ if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("EncryptedExtension lengths misaligned")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl) { int ret; unsigned char *buf; size_t buf_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, &buf, &buf_len)); /* Process the message contents */ MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_encrypted_extensions(ssl, buf, buf + buf_len)); #if defined(MBEDTLS_SSL_EARLY_DATA) if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) { /* RFC8446 4.2.11 * If the server supplies an "early_data" extension, the * client MUST verify that the server's selected_identity * is 0. If any other value is returned, the client MUST * abort the handshake with an "illegal_parameter" alert. * * RFC 8446 4.2.10 * In order to accept early data, the server MUST have accepted a PSK * cipher suite and selected the first key offered in the client's * "pre_shared_key" extension. In addition, it MUST verify that the * following values are the same as those associated with the * selected PSK: * - The TLS version number * - The selected cipher suite * - The selected ALPN [RFC7301] protocol, if any * * The server has sent an early data extension in its Encrypted * Extension message thus accepted to receive early data. We * check here that the additional constraints on the handshake * parameters, when early data are exchanged, are met, * namely: * - a PSK has been selected for the handshake * - the selected PSK for the handshake was the first one proposed * by the client. * - the selected ciphersuite for the handshake is the ciphersuite * associated with the selected PSK. */ if ((!mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) || handshake->selected_identity != 0 || handshake->ciphersuite_info->id != ssl->session_negotiate->ciphersuite) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED; } else if (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) { ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED; } #endif /* * In case the client has proposed a PSK associated with a ticket, * `ssl->session_negotiate->ciphersuite` still contains at this point the * identifier of the ciphersuite associated with the ticket. This is that * way because, if an exchange of early data is agreed upon, we need * it to check that the ciphersuite selected for the handshake is the * ticket ciphersuite (see above). This information is not needed * anymore thus we can now set it to the identifier of the ciphersuite * used in this session under negotiation. */ ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, buf_len)); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); } else { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); } #else ((void) ssl); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); #endif cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse encrypted extensions")); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) /* * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA * * RFC 8446 section 4.5 * * struct {} EndOfEarlyData; * * If the server sent an "early_data" extension in EncryptedExtensions, the * client MUST send an EndOfEarlyData message after receiving the server * Finished. Otherwise, the client MUST NOT send an EndOfEarlyData message. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_end_of_early_data(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf = NULL; size_t buf_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write EndOfEarlyData")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_hdr_to_checksum( ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 0)); MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_finish_handshake_msg(ssl, buf_len, 0)); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write EndOfEarlyData")); return ret; } int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl) { if ((ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) || (!mbedtls_ssl_is_handshake_over(ssl))) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } switch (ssl->early_data_state) { case MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT: return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED; break; case MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED: return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; break; case MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED: return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; break; default: return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * STATE HANDLING: CertificateRequest * */ #define SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST 0 #define SSL_CERTIFICATE_REQUEST_SKIP 1 /* Coordination: * Deals with the ambiguity of not knowing if a CertificateRequest * will be sent. Returns a negative code on failure, or * - SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST * - SSL_CERTIFICATE_REQUEST_SKIP * indicating if a Certificate Request is expected or not. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } ssl->keep_current_message = 1; if ((ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) && (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST)) { MBEDTLS_SSL_DEBUG_MSG(3, ("got a certificate request")); return SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST; } MBEDTLS_SSL_DEBUG_MSG(3, ("got no certificate request")); return SSL_CERTIFICATE_REQUEST_SKIP; } /* * ssl_tls13_parse_certificate_request() * Parse certificate request * struct { * opaque certificate_request_context<0..2^8-1>; * Extension extensions<2..2^16-1>; * } CertificateRequest; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_certificate_request(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; size_t certificate_request_context_len = 0; size_t extensions_len = 0; const unsigned char *extensions_end; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* ... * opaque certificate_request_context<0..2^8-1> * ... */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); certificate_request_context_len = (size_t) p[0]; p += 1; if (certificate_request_context_len > 0) { MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_request_context_len); MBEDTLS_SSL_DEBUG_BUF(3, "Certificate Request Context", p, certificate_request_context_len); handshake->certificate_request_context = mbedtls_calloc(1, certificate_request_context_len); if (handshake->certificate_request_context == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(handshake->certificate_request_context, p, certificate_request_context_len); p += certificate_request_context_len; } /* ... * Extension extensions<2..2^16-1>; * ... */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, extension_type, MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR); if (ret != 0) { return ret; } switch (extension_type) { case MBEDTLS_TLS_EXT_SIG_ALG: MBEDTLS_SSL_DEBUG_MSG(3, ("found signature algorithms extension")); ret = mbedtls_ssl_parse_sig_alg_ext(ssl, p, p + extension_data_len); if (ret != 0) { return ret; } break; default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, extension_type, "( ignored )"); break; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, handshake->received_extensions); /* Check that we consumed all the message. */ if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("CertificateRequest misaligned")); goto decode_error; } /* RFC 8446 section 4.3.2 * * The "signature_algorithms" extension MUST be specified */ if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(SIG_ALG)) == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("no signature algorithms extension found")); goto decode_error; } ssl->handshake->client_auth = 1; return 0; decode_error: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Handler for MBEDTLS_SSL_CERTIFICATE_REQUEST */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_certificate_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request")); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl)); if (ret == SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST) { unsigned char *buf; size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request( ssl, buf, buf + buf_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, buf, buf_len)); } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) { ret = 0; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate request")); return ret; } /* * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_server_certificate(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_process_certificate(ssl); if (ret != 0) { return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY); return 0; } /* * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_process_certificate_verify(ssl); if (ret != 0) { return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * Handler for MBEDTLS_SSL_SERVER_FINISHED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_process_finished_message(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_compute_application_transform(ssl); if (ret != 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED) { ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED; mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA); } else #endif /* MBEDTLS_SSL_EARLY_DATA */ { #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED); #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ } return 0; } /* * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_client_certificate(mbedtls_ssl_context *ssl) { int non_empty_certificate_msg = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake traffic keys for outbound traffic")); mbedtls_ssl_set_outbound_transform(ssl, ssl->handshake->transform_handshake); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) if (ssl->handshake->client_auth) { int ret = mbedtls_ssl_tls13_write_certificate(ssl); if (ret != 0) { return ret; } if (mbedtls_ssl_own_cert(ssl) != NULL) { non_empty_certificate_msg = 1; } } else { MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate")); } #endif if (non_empty_certificate_msg) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate verify")); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); } return 0; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_client_certificate_verify(mbedtls_ssl_context *ssl) { int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl); if (ret == 0) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); } return ret; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * Handler for MBEDTLS_SSL_CLIENT_FINISHED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_client_finished(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_write_finished_message(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_compute_resumption_master_secret ", ret); return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_FLUSH_BUFFERS); return 0; } /* * Handler for MBEDTLS_SSL_FLUSH_BUFFERS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_flush_buffers(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); return 0; } /* * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) { mbedtls_ssl_tls13_handshake_wrapup(ssl); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); return 0; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_EARLY_DATA) /* From RFC 8446 section 4.2.10 * * struct { * select (Handshake.msg_type) { * case new_session_ticket: uint32 max_early_data_size; * ... * }; * } EarlyDataIndication; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_new_session_ticket_early_data_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { mbedtls_ssl_session *session = ssl->session; MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 4); session->max_early_data_size = MBEDTLS_GET_UINT32_BE(buf, 0); mbedtls_ssl_tls13_session_set_ticket_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); MBEDTLS_SSL_DEBUG_MSG( 3, ("received max_early_data_size: %u", (unsigned int) session->max_early_data_size)); return 0; } #endif /* MBEDTLS_SSL_EARLY_DATA */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { mbedtls_ssl_handshake_params *handshake = ssl->handshake; const unsigned char *p = buf; handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < end) { unsigned int extension_type; size_t extension_data_len; int ret; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extension_data_len); ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, extension_type, MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST); if (ret != 0) { return ret; } switch (extension_type) { #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_TLS_EXT_EARLY_DATA: ret = ssl_tls13_parse_new_session_ticket_early_data_ext( ssl, p, p + extension_data_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_new_session_ticket_early_data_ext", ret); } break; #endif /* MBEDTLS_SSL_EARLY_DATA */ default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, extension_type, "( ignored )"); break; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, handshake->received_extensions); return 0; } /* * From RFC8446, page 74 * * struct { * uint32 ticket_lifetime; * uint32 ticket_age_add; * opaque ticket_nonce<0..255>; * opaque ticket<1..2^16-1>; * Extension extensions<0..2^16-2>; * } NewSessionTicket; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, unsigned char **ticket_nonce, size_t *ticket_nonce_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; mbedtls_ssl_session *session = ssl->session; size_t ticket_len; unsigned char *ticket; size_t extensions_len; *ticket_nonce = NULL; *ticket_nonce_len = 0; /* * ticket_lifetime 4 bytes * ticket_age_add 4 bytes * ticket_nonce_len 1 byte */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 9); session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u", (unsigned int) session->ticket_lifetime)); if (session->ticket_lifetime > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) { MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime exceeds 7 days.")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 4); MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", (unsigned int) session->ticket_age_add)); *ticket_nonce_len = p[8]; p += 9; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, *ticket_nonce_len); *ticket_nonce = p; MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:", *ticket_nonce, *ticket_nonce_len); p += *ticket_nonce_len; /* Ticket */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); ticket_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ticket_len); MBEDTLS_SSL_DEBUG_BUF(3, "received ticket", p, ticket_len); /* Check if we previously received a ticket already. */ if (session->ticket != NULL || session->ticket_len > 0) { mbedtls_free(session->ticket); session->ticket = NULL; session->ticket_len = 0; } if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ticket alloc failed")); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ticket, p, ticket_len); p += ticket_len; session->ticket = ticket; session->ticket_len = ticket_len; /* Clear all flags in ticket_flags */ mbedtls_ssl_tls13_session_clear_ticket_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); MBEDTLS_SSL_DEBUG_BUF(3, "ticket extension", p, extensions_len); ret = ssl_tls13_parse_new_session_ticket_exts(ssl, p, p + extensions_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_parse_new_session_ticket_exts", ret); return ret; } return 0; } /* Non negative return values for ssl_tls13_postprocess_new_session_ticket(). * - POSTPROCESS_NEW_SESSION_TICKET_SIGNAL, all good, we have to signal the * application that a valid ticket has been received. * - POSTPROCESS_NEW_SESSION_TICKET_DISCARD, no fatal error, we keep the * connection alive but we do not signal the ticket to the application. */ #define POSTPROCESS_NEW_SESSION_TICKET_SIGNAL 0 #define POSTPROCESS_NEW_SESSION_TICKET_DISCARD 1 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl, unsigned char *ticket_nonce, size_t ticket_nonce_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_session *session = ssl->session; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; psa_algorithm_t psa_hash_alg; int hash_length; if (session->ticket_lifetime == 0) { return POSTPROCESS_NEW_SESSION_TICKET_DISCARD; } #if defined(MBEDTLS_HAVE_TIME) /* Store ticket creation time */ session->ticket_reception_time = mbedtls_ms_time(); #endif ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(session->ciphersuite); if (ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); hash_length = PSA_HASH_LENGTH(psa_hash_alg); if (hash_length == -1 || (size_t) hash_length > sizeof(session->resumption_key)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret", session->app_secrets.resumption_master_secret, hash_length); /* Compute resumption key * * HKDF-Expand-Label( resumption_master_secret, * "resumption", ticket_nonce, Hash.length ) */ ret = mbedtls_ssl_tls13_hkdf_expand_label( psa_hash_alg, session->app_secrets.resumption_master_secret, hash_length, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption), ticket_nonce, ticket_nonce_len, session->resumption_key, hash_length); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(2, "Creating the ticket-resumed PSK failed", ret); return ret; } session->resumption_key_len = hash_length; MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK", session->resumption_key, session->resumption_key_len); /* Set ticket_flags depends on the selected key exchange modes */ mbedtls_ssl_tls13_session_set_ticket_flags( session, ssl->conf->tls13_kex_modes); MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags); return POSTPROCESS_NEW_SESSION_TICKET_SIGNAL; } /* * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len; unsigned char *ticket_nonce; size_t ticket_nonce_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, &buf, &buf_len)); /* * We are about to update (maybe only partially) ticket data thus block * any session export for the time being. */ ssl->session->exported = 1; MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_new_session_ticket( ssl, buf, buf + buf_len, &ticket_nonce, &ticket_nonce_len)); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_postprocess_new_session_ticket( ssl, ticket_nonce, ticket_nonce_len)); switch (ret) { case POSTPROCESS_NEW_SESSION_TICKET_SIGNAL: /* * All good, we have received a new valid ticket, session data can * be exported now and we signal the ticket to the application. */ ssl->session->exported = 0; ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET; break; case POSTPROCESS_NEW_SESSION_TICKET_DISCARD: ret = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("Discard new session ticket")); break; default: ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse new session ticket")); return ret; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) { int ret = 0; switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); break; case MBEDTLS_SSL_CLIENT_HELLO: ret = mbedtls_ssl_write_client_hello(ssl); break; case MBEDTLS_SSL_SERVER_HELLO: ret = ssl_tls13_process_server_hello(ssl); break; case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: ret = ssl_tls13_process_encrypted_extensions(ssl); break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_SSL_CERTIFICATE_REQUEST: ret = ssl_tls13_process_certificate_request(ssl); break; case MBEDTLS_SSL_SERVER_CERTIFICATE: ret = ssl_tls13_process_server_certificate(ssl); break; case MBEDTLS_SSL_CERTIFICATE_VERIFY: ret = ssl_tls13_process_certificate_verify(ssl); break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ case MBEDTLS_SSL_SERVER_FINISHED: ret = ssl_tls13_process_server_finished(ssl); break; #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_SSL_END_OF_EARLY_DATA: ret = ssl_tls13_write_end_of_early_data(ssl); break; #endif case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = ssl_tls13_write_client_certificate(ssl); break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: ret = ssl_tls13_write_client_certificate_verify(ssl); break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ case MBEDTLS_SSL_CLIENT_FINISHED: ret = ssl_tls13_write_client_finished(ssl); break; case MBEDTLS_SSL_FLUSH_BUFFERS: ret = ssl_tls13_flush_buffers(ssl); break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: ret = ssl_tls13_handshake_wrapup(ssl); break; /* * Injection of dummy-CCS's for middlebox compatibility */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret != 0) { break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); break; case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret != 0) { break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); break; #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret == 0) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to early data keys for outbound traffic")); mbedtls_ssl_set_outbound_transform( ssl, ssl->handshake->transform_earlydata); ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE; } break; #endif /* MBEDTLS_SSL_EARLY_DATA */ #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: ret = ssl_tls13_process_new_session_ticket(ssl); break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ default: MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return ret; } #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_3 */ webfakes/src/mbedtls/library/memory_buffer_alloc.c0000644000176200001440000004423514740737024022125 0ustar liggesusers/* * Buffer-based memory allocator * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #include "mbedtls/memory_buffer_alloc.h" /* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C is dependent upon MBEDTLS_PLATFORM_C */ #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_MEMORY_BACKTRACE) #include #endif #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #define MAGIC1 0xFF00AA55 #define MAGIC2 0xEE119966 #define MAX_BT 20 typedef struct _memory_header memory_header; struct _memory_header { size_t magic1; size_t size; size_t alloc; memory_header *prev; memory_header *next; memory_header *prev_free; memory_header *next_free; #if defined(MBEDTLS_MEMORY_BACKTRACE) char **trace; size_t trace_count; #endif size_t magic2; }; typedef struct { unsigned char *buf; size_t len; memory_header *first; memory_header *first_free; int verify; #if defined(MBEDTLS_MEMORY_DEBUG) size_t alloc_count; size_t free_count; size_t total_used; size_t maximum_used; size_t header_count; size_t maximum_header_count; #endif #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t mutex; #endif } buffer_alloc_ctx; static buffer_alloc_ctx heap; #if defined(MBEDTLS_MEMORY_DEBUG) static void debug_header(memory_header *hdr) { #if defined(MBEDTLS_MEMORY_BACKTRACE) size_t i; #endif mbedtls_fprintf(stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " "ALLOC(%zu), SIZE(%10zu)\n", (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, hdr->alloc, hdr->size); mbedtls_fprintf(stderr, " FPREV(%10zu), FNEXT(%10zu)\n", (size_t) hdr->prev_free, (size_t) hdr->next_free); #if defined(MBEDTLS_MEMORY_BACKTRACE) mbedtls_fprintf(stderr, "TRACE: \n"); for (i = 0; i < hdr->trace_count; i++) { mbedtls_fprintf(stderr, "%s\n", hdr->trace[i]); } mbedtls_fprintf(stderr, "\n"); #endif } static void debug_chain(void) { memory_header *cur = heap.first; mbedtls_fprintf(stderr, "\nBlock list\n"); while (cur != NULL) { debug_header(cur); cur = cur->next; } mbedtls_fprintf(stderr, "Free list\n"); cur = heap.first_free; while (cur != NULL) { debug_header(cur); cur = cur->next_free; } } #endif /* MBEDTLS_MEMORY_DEBUG */ static int verify_header(memory_header *hdr) { if (hdr->magic1 != MAGIC1) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: MAGIC1 mismatch\n"); #endif return 1; } if (hdr->magic2 != MAGIC2) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: MAGIC2 mismatch\n"); #endif return 1; } if (hdr->alloc > 1) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: alloc has illegal value\n"); #endif return 1; } if (hdr->prev != NULL && hdr->prev == hdr->next) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: prev == next\n"); #endif return 1; } if (hdr->prev_free != NULL && hdr->prev_free == hdr->next_free) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: prev_free == next_free\n"); #endif return 1; } return 0; } static int verify_chain(void) { memory_header *prv = heap.first, *cur; if (prv == NULL || verify_header(prv) != 0) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: verification of first header " "failed\n"); #endif return 1; } if (heap.first->prev != NULL) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: verification failed: " "first->prev != NULL\n"); #endif return 1; } cur = heap.first->next; while (cur != NULL) { if (verify_header(cur) != 0) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: verification of header " "failed\n"); #endif return 1; } if (cur->prev != prv) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: verification failed: " "cur->prev != prv\n"); #endif return 1; } prv = cur; cur = cur->next; } return 0; } static void *buffer_alloc_calloc(size_t n, size_t size) { memory_header *new, *cur = heap.first_free; unsigned char *p; void *ret; size_t original_len, len; #if defined(MBEDTLS_MEMORY_BACKTRACE) void *trace_buffer[MAX_BT]; size_t trace_cnt; #endif if (heap.buf == NULL || heap.first == NULL) { return NULL; } original_len = len = n * size; if (n == 0 || size == 0 || len / n != size) { return NULL; } else if (len > (size_t) -MBEDTLS_MEMORY_ALIGN_MULTIPLE) { return NULL; } if (len % MBEDTLS_MEMORY_ALIGN_MULTIPLE) { len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; } // Find block that fits // while (cur != NULL) { if (cur->size >= len) { break; } cur = cur->next_free; } if (cur == NULL) { return NULL; } if (cur->alloc != 0) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: block in free_list but allocated " "data\n"); #endif mbedtls_exit(1); } #if defined(MBEDTLS_MEMORY_DEBUG) heap.alloc_count++; #endif // Found location, split block if > memory_header + 4 room left // if (cur->size - len < sizeof(memory_header) + MBEDTLS_MEMORY_ALIGN_MULTIPLE) { cur->alloc = 1; // Remove from free_list // if (cur->prev_free != NULL) { cur->prev_free->next_free = cur->next_free; } else { heap.first_free = cur->next_free; } if (cur->next_free != NULL) { cur->next_free->prev_free = cur->prev_free; } cur->prev_free = NULL; cur->next_free = NULL; #if defined(MBEDTLS_MEMORY_DEBUG) heap.total_used += cur->size; if (heap.total_used > heap.maximum_used) { heap.maximum_used = heap.total_used; } #endif #if defined(MBEDTLS_MEMORY_BACKTRACE) trace_cnt = backtrace(trace_buffer, MAX_BT); cur->trace = backtrace_symbols(trace_buffer, trace_cnt); cur->trace_count = trace_cnt; #endif if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) { mbedtls_exit(1); } ret = (unsigned char *) cur + sizeof(memory_header); memset(ret, 0, original_len); return ret; } p = ((unsigned char *) cur) + sizeof(memory_header) + len; new = (memory_header *) p; new->size = cur->size - len - sizeof(memory_header); new->alloc = 0; new->prev = cur; new->next = cur->next; #if defined(MBEDTLS_MEMORY_BACKTRACE) new->trace = NULL; new->trace_count = 0; #endif new->magic1 = MAGIC1; new->magic2 = MAGIC2; if (new->next != NULL) { new->next->prev = new; } // Replace cur with new in free_list // new->prev_free = cur->prev_free; new->next_free = cur->next_free; if (new->prev_free != NULL) { new->prev_free->next_free = new; } else { heap.first_free = new; } if (new->next_free != NULL) { new->next_free->prev_free = new; } cur->alloc = 1; cur->size = len; cur->next = new; cur->prev_free = NULL; cur->next_free = NULL; #if defined(MBEDTLS_MEMORY_DEBUG) heap.header_count++; if (heap.header_count > heap.maximum_header_count) { heap.maximum_header_count = heap.header_count; } heap.total_used += cur->size; if (heap.total_used > heap.maximum_used) { heap.maximum_used = heap.total_used; } #endif #if defined(MBEDTLS_MEMORY_BACKTRACE) trace_cnt = backtrace(trace_buffer, MAX_BT); cur->trace = backtrace_symbols(trace_buffer, trace_cnt); cur->trace_count = trace_cnt; #endif if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) { mbedtls_exit(1); } ret = (unsigned char *) cur + sizeof(memory_header); memset(ret, 0, original_len); return ret; } static void buffer_alloc_free(void *ptr) { memory_header *hdr, *old = NULL; unsigned char *p = (unsigned char *) ptr; if (ptr == NULL || heap.buf == NULL || heap.first == NULL) { return; } if (p < heap.buf || p >= heap.buf + heap.len) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: mbedtls_free() outside of managed " "space\n"); #endif mbedtls_exit(1); } p -= sizeof(memory_header); hdr = (memory_header *) p; if (verify_header(hdr) != 0) { mbedtls_exit(1); } if (hdr->alloc != 1) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: mbedtls_free() on unallocated " "data\n"); #endif mbedtls_exit(1); } hdr->alloc = 0; #if defined(MBEDTLS_MEMORY_DEBUG) heap.free_count++; heap.total_used -= hdr->size; #endif #if defined(MBEDTLS_MEMORY_BACKTRACE) free(hdr->trace); hdr->trace = NULL; hdr->trace_count = 0; #endif // Regroup with block before // if (hdr->prev != NULL && hdr->prev->alloc == 0) { #if defined(MBEDTLS_MEMORY_DEBUG) heap.header_count--; #endif hdr->prev->size += sizeof(memory_header) + hdr->size; hdr->prev->next = hdr->next; old = hdr; hdr = hdr->prev; if (hdr->next != NULL) { hdr->next->prev = hdr; } memset(old, 0, sizeof(memory_header)); } // Regroup with block after // if (hdr->next != NULL && hdr->next->alloc == 0) { #if defined(MBEDTLS_MEMORY_DEBUG) heap.header_count--; #endif hdr->size += sizeof(memory_header) + hdr->next->size; old = hdr->next; hdr->next = hdr->next->next; if (hdr->prev_free != NULL || hdr->next_free != NULL) { if (hdr->prev_free != NULL) { hdr->prev_free->next_free = hdr->next_free; } else { heap.first_free = hdr->next_free; } if (hdr->next_free != NULL) { hdr->next_free->prev_free = hdr->prev_free; } } hdr->prev_free = old->prev_free; hdr->next_free = old->next_free; if (hdr->prev_free != NULL) { hdr->prev_free->next_free = hdr; } else { heap.first_free = hdr; } if (hdr->next_free != NULL) { hdr->next_free->prev_free = hdr; } if (hdr->next != NULL) { hdr->next->prev = hdr; } memset(old, 0, sizeof(memory_header)); } // Prepend to free_list if we have not merged // (Does not have to stay in same order as prev / next list) // if (old == NULL) { hdr->next_free = heap.first_free; if (heap.first_free != NULL) { heap.first_free->prev_free = hdr; } heap.first_free = hdr; } if ((heap.verify & MBEDTLS_MEMORY_VERIFY_FREE) && verify_chain() != 0) { mbedtls_exit(1); } } void mbedtls_memory_buffer_set_verify(int verify) { heap.verify = verify; } int mbedtls_memory_buffer_alloc_verify(void) { return verify_chain(); } #if defined(MBEDTLS_MEMORY_DEBUG) void mbedtls_memory_buffer_alloc_status(void) { mbedtls_fprintf(stderr, "Current use: %zu blocks / %zu bytes, max: %zu blocks / " "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", heap.header_count, heap.total_used, heap.maximum_header_count, heap.maximum_used, heap.maximum_header_count * sizeof(memory_header) + heap.maximum_used, heap.alloc_count, heap.free_count); if (heap.first->next == NULL) { mbedtls_fprintf(stderr, "All memory de-allocated in stack buffer\n"); } else { mbedtls_fprintf(stderr, "Memory currently allocated:\n"); debug_chain(); } } void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count) { *alloc_count = heap.alloc_count; *free_count = heap.free_count; } void mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks) { *max_used = heap.maximum_used; *max_blocks = heap.maximum_header_count; } void mbedtls_memory_buffer_alloc_max_reset(void) { heap.maximum_used = 0; heap.maximum_header_count = 0; } void mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks) { *cur_used = heap.total_used; *cur_blocks = heap.header_count; } #endif /* MBEDTLS_MEMORY_DEBUG */ #if defined(MBEDTLS_THREADING_C) static void *buffer_alloc_calloc_mutexed(size_t n, size_t size) { void *buf; if (mbedtls_mutex_lock(&heap.mutex) != 0) { return NULL; } buf = buffer_alloc_calloc(n, size); if (mbedtls_mutex_unlock(&heap.mutex)) { return NULL; } return buf; } static void buffer_alloc_free_mutexed(void *ptr) { /* We have no good option here, but corrupting the heap seems * worse than losing memory. */ if (mbedtls_mutex_lock(&heap.mutex)) { return; } buffer_alloc_free(ptr); (void) mbedtls_mutex_unlock(&heap.mutex); } #endif /* MBEDTLS_THREADING_C */ void mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len) { memset(&heap, 0, sizeof(buffer_alloc_ctx)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&heap.mutex); mbedtls_platform_set_calloc_free(buffer_alloc_calloc_mutexed, buffer_alloc_free_mutexed); #else mbedtls_platform_set_calloc_free(buffer_alloc_calloc, buffer_alloc_free); #endif if (len < sizeof(memory_header) + MBEDTLS_MEMORY_ALIGN_MULTIPLE) { return; } else if ((size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE) { /* Adjust len first since buf is used in the computation */ len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; } memset(buf, 0, len); heap.buf = buf; heap.len = len; heap.first = (memory_header *) buf; heap.first->size = len - sizeof(memory_header); heap.first->magic1 = MAGIC1; heap.first->magic2 = MAGIC2; heap.first_free = heap.first; } void mbedtls_memory_buffer_alloc_free(void) { #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&heap.mutex); #endif mbedtls_platform_zeroize(&heap, sizeof(buffer_alloc_ctx)); } #if defined(MBEDTLS_SELF_TEST) static int check_pointer(void *p) { if (p == NULL) { return -1; } if ((size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0) { return -1; } return 0; } static int check_all_free(void) { if ( #if defined(MBEDTLS_MEMORY_DEBUG) heap.total_used != 0 || #endif heap.first != heap.first_free || (void *) heap.first != (void *) heap.buf) { return -1; } return 0; } #define TEST_ASSERT(condition) \ if (!(condition)) \ { \ if (verbose != 0) \ mbedtls_printf("failed\n"); \ \ ret = 1; \ goto cleanup; \ } int mbedtls_memory_buffer_alloc_self_test(int verbose) { unsigned char buf[1024]; unsigned char *p, *q, *r, *end; int ret = 0; if (verbose != 0) { mbedtls_printf(" MBA test #1 (basic alloc-free cycle): "); } mbedtls_memory_buffer_alloc_init(buf, sizeof(buf)); p = mbedtls_calloc(1, 1); q = mbedtls_calloc(1, 128); r = mbedtls_calloc(1, 16); TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0 && check_pointer(r) == 0); mbedtls_free(r); mbedtls_free(q); mbedtls_free(p); TEST_ASSERT(check_all_free() == 0); /* Memorize end to compare with the next test */ end = heap.buf + heap.len; mbedtls_memory_buffer_alloc_free(); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf(" MBA test #2 (buf not aligned): "); } mbedtls_memory_buffer_alloc_init(buf + 1, sizeof(buf) - 1); TEST_ASSERT(heap.buf + heap.len == end); p = mbedtls_calloc(1, 1); q = mbedtls_calloc(1, 128); r = mbedtls_calloc(1, 16); TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0 && check_pointer(r) == 0); mbedtls_free(r); mbedtls_free(q); mbedtls_free(p); TEST_ASSERT(check_all_free() == 0); mbedtls_memory_buffer_alloc_free(); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf(" MBA test #3 (full): "); } mbedtls_memory_buffer_alloc_init(buf, sizeof(buf)); p = mbedtls_calloc(1, sizeof(buf) - sizeof(memory_header)); TEST_ASSERT(check_pointer(p) == 0); TEST_ASSERT(mbedtls_calloc(1, 1) == NULL); mbedtls_free(p); p = mbedtls_calloc(1, sizeof(buf) - 2 * sizeof(memory_header) - 16); q = mbedtls_calloc(1, 16); TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0); TEST_ASSERT(mbedtls_calloc(1, 1) == NULL); mbedtls_free(q); TEST_ASSERT(mbedtls_calloc(1, 17) == NULL); mbedtls_free(p); TEST_ASSERT(check_all_free() == 0); mbedtls_memory_buffer_alloc_free(); if (verbose != 0) { mbedtls_printf("passed\n"); } cleanup: mbedtls_memory_buffer_alloc_free(); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ webfakes/src/mbedtls/library/psa_crypto_rsa.c0000644000176200001440000006306314740737024021142 0ustar liggesusers/* * PSA RSA layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa/crypto_values.h" #include "psa_crypto_core.h" #include "psa_crypto_random_impl.h" #include "psa_crypto_rsa.h" #include "psa_crypto_hash.h" #include "mbedtls/psa_util.h" #include #include #include "mbedtls/platform.h" #include #include #include "rsa_internal.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) /* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes * that are not a multiple of 8) well. For example, there is only * mbedtls_rsa_get_len(), which returns a number of bytes, and no * way to return the exact bit size of a key. * To keep things simple, reject non-byte-aligned key sizes. */ static psa_status_t psa_check_rsa_key_byte_aligned( const mbedtls_rsa_context *rsa) { mbedtls_mpi n; psa_status_t status; mbedtls_mpi_init(&n); status = mbedtls_to_psa_error( mbedtls_rsa_export(rsa, &n, NULL, NULL, NULL, NULL)); if (status == PSA_SUCCESS) { if (mbedtls_mpi_bitlen(&n) % 8 != 0) { status = PSA_ERROR_NOT_SUPPORTED; } } mbedtls_mpi_free(&n); return status; } psa_status_t mbedtls_psa_rsa_load_representation( psa_key_type_t type, const uint8_t *data, size_t data_length, mbedtls_rsa_context **p_rsa) { psa_status_t status; size_t bits; *p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); if (*p_rsa == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } mbedtls_rsa_init(*p_rsa); /* Parse the data. */ if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) { status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length)); } else { status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length)); } if (status != PSA_SUCCESS) { goto exit; } /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS * supports non-byte-aligned key sizes, but not well. For example, * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa)); if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = psa_check_rsa_key_byte_aligned(*p_rsa); if (status != PSA_SUCCESS) { goto exit; } exit: return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ #if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) psa_status_t mbedtls_psa_rsa_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits) { psa_status_t status; mbedtls_rsa_context *rsa = NULL; /* Parse input */ status = mbedtls_psa_rsa_load_representation(attributes->type, data, data_length, &rsa); if (status != PSA_SUCCESS) { goto exit; } *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(rsa)); /* Re-export the data to PSA export format, such that we can store export * representation in the key slot. Export representation in case of RSA is * the smallest representation that's allowed as input, so a straight-up * allocation of the same size as the input buffer will be large enough. */ status = mbedtls_psa_rsa_export_key(attributes->type, rsa, key_buffer, key_buffer_size, key_buffer_length); exit: /* Always free the RSA object */ mbedtls_rsa_free(rsa); mbedtls_free(rsa); return status; } #endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type, mbedtls_rsa_context *rsa, uint8_t *data, size_t data_size, size_t *data_length) { int ret; uint8_t *end = data + data_size; /* PSA Crypto API defines the format of an RSA key as a DER-encoded * representation of the non-encrypted PKCS#1 RSAPrivateKey for a * private key and of the RFC3279 RSAPublicKey for a public key. */ if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) { ret = mbedtls_rsa_write_key(rsa, data, &end); } else { ret = mbedtls_rsa_write_pubkey(rsa, data, &end); } if (ret < 0) { /* Clean up in case pk_write failed halfway through. */ memset(data, 0, data_size); return mbedtls_to_psa_error(ret); } /* The mbedtls_pk_xxx functions write to the end of the buffer. * Move the data to the beginning and erase remaining data * at the original location. */ if (2 * (size_t) ret <= data_size) { memcpy(data, data + data_size - ret, ret); memset(data + data_size - ret, 0, ret); } else if ((size_t) ret < data_size) { memmove(data, data + data_size - ret, ret); memset(data + ret, 0, data_size - ret); } *data_length = ret; return PSA_SUCCESS; } psa_status_t mbedtls_psa_rsa_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_rsa_context *rsa = NULL; status = mbedtls_psa_rsa_load_representation( attributes->type, key_buffer, key_buffer_size, &rsa); if (status == PSA_SUCCESS) { status = mbedtls_psa_rsa_export_key(PSA_KEY_TYPE_RSA_PUBLIC_KEY, rsa, data, data_size, data_length); } mbedtls_rsa_free(rsa); mbedtls_free(rsa); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) static psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes, size_t e_length, int *exponent) { size_t i; uint32_t acc = 0; /* Mbed TLS encodes the public exponent as an int. For simplicity, only * support values that fit in a 32-bit integer, which is larger than * int on just about every platform anyway. */ if (e_length > sizeof(acc)) { return PSA_ERROR_NOT_SUPPORTED; } for (i = 0; i < e_length; i++) { acc = (acc << 8) | e_bytes[i]; } if (acc > INT_MAX) { return PSA_ERROR_NOT_SUPPORTED; } *exponent = acc; return PSA_SUCCESS; } psa_status_t mbedtls_psa_rsa_generate_key( const psa_key_attributes_t *attributes, const uint8_t *custom_data, size_t custom_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { psa_status_t status; mbedtls_rsa_context rsa; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int exponent = 65537; if (custom_data_length != 0) { status = psa_rsa_read_exponent(custom_data, custom_data_length, &exponent); if (status != PSA_SUCCESS) { return status; } } mbedtls_rsa_init(&rsa); ret = mbedtls_rsa_gen_key(&rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, (unsigned int) attributes->bits, exponent); if (ret != 0) { mbedtls_rsa_free(&rsa); return mbedtls_to_psa_error(ret); } status = mbedtls_psa_rsa_export_key(attributes->type, &rsa, key_buffer, key_buffer_size, key_buffer_length); mbedtls_rsa_free(&rsa); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ /****************************************************************/ /* Sign/verify hashes */ /****************************************************************/ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) /* Decode the hash algorithm from alg and store the mbedtls encoding in * md_alg. Verify that the hash length is acceptable. */ static psa_status_t psa_rsa_decode_md_type(psa_algorithm_t alg, size_t hash_length, mbedtls_md_type_t *md_alg) { psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); *md_alg = mbedtls_md_type_from_psa_alg(hash_alg); /* The Mbed TLS RSA module uses an unsigned int for hash length * parameters. Validate that it fits so that we don't risk an * overflow later. */ #if SIZE_MAX > UINT_MAX if (hash_length > UINT_MAX) { return PSA_ERROR_INVALID_ARGUMENT; } #endif /* For signatures using a hash, the hash length must be correct. */ if (alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) { if (*md_alg == MBEDTLS_MD_NONE) { return PSA_ERROR_NOT_SUPPORTED; } if (mbedtls_md_get_size_from_type(*md_alg) != hash_length) { return PSA_ERROR_INVALID_ARGUMENT; } } return PSA_SUCCESS; } psa_status_t mbedtls_psa_rsa_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_rsa_context *rsa = NULL; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_alg; status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { goto exit; } status = psa_rsa_decode_md_type(alg, hash_length, &md_alg); if (status != PSA_SUCCESS) { goto exit; } if (signature_size < mbedtls_rsa_get_len(rsa)) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); if (ret == 0) { ret = mbedtls_rsa_pkcs1_sign(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, md_alg, (unsigned int) hash_length, hash, signature); } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) if (PSA_ALG_IS_RSA_PSS(alg)) { ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); if (ret == 0) { ret = mbedtls_rsa_rsassa_pss_sign(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, MBEDTLS_MD_NONE, (unsigned int) hash_length, hash, signature); } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } if (ret == 0) { *signature_length = mbedtls_rsa_get_len(rsa); } status = mbedtls_to_psa_error(ret); exit: mbedtls_rsa_free(rsa); mbedtls_free(rsa); return status; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) static int rsa_pss_expected_salt_len(psa_algorithm_t alg, const mbedtls_rsa_context *rsa, size_t hash_length) { if (PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) { return MBEDTLS_RSA_SALT_LEN_ANY; } /* Otherwise: standard salt length, i.e. largest possible salt length * up to the hash length. */ int klen = (int) mbedtls_rsa_get_len(rsa); // known to fit int hlen = (int) hash_length; // known to fit int room = klen - 2 - hlen; if (room < 0) { return 0; // there is no valid signature in this case anyway } else if (room > hlen) { return hlen; } else { return room; } } #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ psa_status_t mbedtls_psa_rsa_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_rsa_context *rsa = NULL; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_alg; status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { goto exit; } status = psa_rsa_decode_md_type(alg, hash_length, &md_alg); if (status != PSA_SUCCESS) { goto exit; } if (signature_length != mbedtls_rsa_get_len(rsa)) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); if (ret == 0) { ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg, (unsigned int) hash_length, hash, signature); } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) if (PSA_ALG_IS_RSA_PSS(alg)) { ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); if (ret == 0) { int slen = rsa_pss_expected_salt_len(alg, rsa, hash_length); ret = mbedtls_rsa_rsassa_pss_verify_ext(rsa, md_alg, (unsigned) hash_length, hash, md_alg, slen, signature); } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } /* Mbed TLS distinguishes "invalid padding" from "valid padding but * the rest of the signature is invalid". This has little use in * practice and PSA doesn't report this distinction. */ status = (ret == MBEDTLS_ERR_RSA_INVALID_PADDING) ? PSA_ERROR_INVALID_SIGNATURE : mbedtls_to_psa_error(ret); exit: mbedtls_rsa_free(rsa); mbedtls_free(rsa); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ /****************************************************************/ /* Asymmetric cryptography */ /****************************************************************/ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) static int psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg, mbedtls_rsa_context *rsa) { psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH(alg); mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); /* Just to get the error status right, as rsa_set_padding() doesn't * distinguish between "bad RSA algorithm" and "unknown hash". */ if (mbedtls_md_info_from_type(md_alg) == NULL) { return PSA_ERROR_NOT_SUPPORTED; } return mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; (void) key_buffer; (void) key_buffer_size; (void) input; (void) input_length; (void) salt; (void) salt_length; (void) output; (void) output_size; (void) output_length; if (PSA_KEY_TYPE_IS_RSA(attributes->type)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) mbedtls_rsa_context *rsa = NULL; status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { goto rsa_exit; } if (output_size < mbedtls_rsa_get_len(rsa)) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto rsa_exit; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) status = mbedtls_to_psa_error( mbedtls_rsa_pkcs1_encrypt(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, input_length, input, output)); #else status = PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ } else if (PSA_ALG_IS_RSA_OAEP(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) status = mbedtls_to_psa_error( psa_rsa_oaep_set_padding_mode(alg, rsa)); if (status != PSA_SUCCESS) { goto rsa_exit; } status = mbedtls_to_psa_error( mbedtls_rsa_rsaes_oaep_encrypt(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, salt, salt_length, input_length, input, output)); #else status = PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ } else { status = PSA_ERROR_INVALID_ARGUMENT; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) rsa_exit: if (status == PSA_SUCCESS) { *output_length = mbedtls_rsa_get_len(rsa); } mbedtls_rsa_free(rsa); mbedtls_free(rsa); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ } else { status = PSA_ERROR_NOT_SUPPORTED; } return status; } psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; (void) key_buffer; (void) key_buffer_size; (void) input; (void) input_length; (void) salt; (void) salt_length; (void) output; (void) output_size; (void) output_length; *output_length = 0; if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) mbedtls_rsa_context *rsa = NULL; status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { goto rsa_exit; } if (input_length != mbedtls_rsa_get_len(rsa)) { status = PSA_ERROR_INVALID_ARGUMENT; goto rsa_exit; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) status = mbedtls_to_psa_error( mbedtls_rsa_pkcs1_decrypt(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, output_length, input, output, output_size)); #else status = PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ } else if (PSA_ALG_IS_RSA_OAEP(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) status = mbedtls_to_psa_error( psa_rsa_oaep_set_padding_mode(alg, rsa)); if (status != PSA_SUCCESS) { goto rsa_exit; } status = mbedtls_to_psa_error( mbedtls_rsa_rsaes_oaep_decrypt(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, salt, salt_length, output_length, input, output, output_size)); #else status = PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ } else { status = PSA_ERROR_INVALID_ARGUMENT; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) rsa_exit: mbedtls_rsa_free(rsa); mbedtls_free(rsa); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ } else { status = PSA_ERROR_NOT_SUPPORTED; } return status; } #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/x509write_csr.c0000644000176200001440000002533114740737024020535 0ustar liggesusers/* * X.509 Certificate Signing Request writing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * - CSRs: PKCS#10 v1.7 aka RFC 2986 * - attributes: PKCS#9 v2.0 aka RFC 2985 */ #include "common.h" #if defined(MBEDTLS_X509_CSR_WRITE_C) #include "x509_internal.h" #include "mbedtls/x509_csr.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "psa_util_internal.h" #include "mbedtls/psa_util.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ #include #include #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif #include "mbedtls/platform.h" void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx) { memset(ctx, 0, sizeof(mbedtls_x509write_csr)); } void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx) { if (ctx == NULL) { return; } mbedtls_asn1_free_named_data_list(&ctx->subject); mbedtls_asn1_free_named_data_list(&ctx->extensions); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr)); } void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg) { ctx->md_alg = md_alg; } void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key) { ctx->key = key; } int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, const char *subject_name) { return mbedtls_x509_string_to_names(&ctx->subject, subject_name); } int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len) { return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, critical, val, val_len); } int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, const mbedtls_x509_san_list *san_list) { return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); } int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage) { unsigned char buf[4] = { 0 }; unsigned char *c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; c = buf + 4; ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8); if (ret < 3 || ret > 4) { return ret; } ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), 0, c, (size_t) ret); if (ret != 0) { return ret; } return 0; } int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, unsigned char ns_cert_type) { unsigned char buf[4] = { 0 }; unsigned char *c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; c = buf + 4; ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); if (ret < 3 || ret > 4) { return ret; } ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), 0, c, (size_t) ret); if (ret != 0) { return ret; } return 0; } static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, unsigned char *sig, size_t sig_size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; mbedtls_pk_type_t pk_alg; #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t hash_len; psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg); #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Write the CSR backwards starting from the end of buf */ c = buf + size; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf, ctx->extensions)); if (len) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid( &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ))); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key, buf, (size_t) (c - buf))); c -= pub_len; len += pub_len; /* * Subject ::= Name */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, ctx->subject)); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* * Sign the written CSR data into the sig buffer * Note: hash errors can happen only after an internal error */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if (psa_hash_compute(hash_alg, c, len, hash, sizeof(hash), &hash_len) != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } #else /* MBEDTLS_USE_PSA_CRYPTO */ ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash); if (ret != 0) { return ret; } #endif if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, sig, sig_size, &sig_len, f_rng, p_rng)) != 0) { return ret; } if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) { pk_alg = MBEDTLS_PK_RSA; } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) { pk_alg = MBEDTLS_PK_ECDSA; } else { return MBEDTLS_ERR_X509_INVALID_ALG; } if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len)) != 0) { return ret; } /* * Move the written CSR data to the start of buf to create space for * writing the signature into buf. */ memmove(buf, c, len); /* * Write sig and its OID into buf backwards from the end of buf. * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. */ c2 = buf + size; MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len, sig, sig_len, pk_alg)); /* * Compact the space between the CSR data and signature by moving the * CSR data to the start of the signature. */ c2 -= len; memmove(c2, buf, len); /* ASN encode the total size and tag the CSR data with it. */ len += sig_and_oid_len; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* Zero the unused bytes at the start of buf */ memset(buf, 0, (size_t) (c2 - buf)); return (int) len; } int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; unsigned char *sig; if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } ret = x509write_csr_der_internal(ctx, buf, size, sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE, f_rng, p_rng); mbedtls_free(sig); return ret; } #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" #if defined(MBEDTLS_PEM_WRITE_C) int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen = 0; if ((ret = mbedtls_x509write_csr_der(ctx, buf, size, f_rng, p_rng)) < 0) { return ret; } if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR, buf + size - ret, ret, buf, size, &olen)) != 0) { return ret; } return 0; } #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CSR_WRITE_C */ webfakes/src/mbedtls/library/sha512.c0000644000176200001440000011120714740737024017107 0ustar liggesusers/* * FIPS-180-2 compliant SHA-384/512 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-512 Secure Hash Standard was published by NIST in 2002. * * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ #if defined(__aarch64__) && !defined(__ARM_FEATURE_SHA512) && \ defined(__clang__) && __clang_major__ >= 7 /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. * * The intrinsic declaration are guarded by predefined ACLE macros in clang: * these are normally only enabled by the -march option on the command line. * By defining the macros ourselves we gain access to those declarations without * requiring -march on the command line. * * `arm_neon.h` is included by common.h, so we put these defines * at the top of this file, before any includes. */ #define __ARM_FEATURE_SHA512 1 #define MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG #endif #include "common.h" #if defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA384_C) #include "mbedtls/sha512.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #if defined(_MSC_VER) || defined(__WATCOMC__) #define UL64(x) x##ui64 #else #define UL64(x) x##ULL #endif #include #include "mbedtls/platform.h" #if defined(__aarch64__) # if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) /* *INDENT-OFF* */ # if !defined(MBEDTLS_HAVE_NEON_INTRINSICS) # error "Target does not support NEON instructions" # endif /* * Best performance comes from most recent compilers, with intrinsics and -O3. * Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and * can't always detect __ARM_FEATURE_SHA512 (notably clang 7-12). * * GCC < 8 won't work at all (lacks the sha512 instructions) * GCC >= 8 uses intrinsics, sets __ARM_FEATURE_SHA512 * * Clang < 7 won't work at all (lacks the sha512 instructions) * Clang 7-12 don't have intrinsics (but we work around that with inline * assembler) or __ARM_FEATURE_SHA512 * Clang == 13.0.0 same as clang 12 (only seen on macOS) * Clang >= 13.0.1 has __ARM_FEATURE_SHA512 and intrinsics */ # if !defined(__ARM_FEATURE_SHA512) || defined(MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG) /* Test Clang first, as it defines __GNUC__ */ # if defined(__ARMCOMPILER_VERSION) # if __ARMCOMPILER_VERSION < 6090000 # error "A more recent armclang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # elif __ARMCOMPILER_VERSION == 6090000 # error "Must use minimum -march=armv8.2-a+sha3 for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # else # pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # endif # elif defined(__clang__) # if __clang_major__ < 7 # error "A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # else # pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # endif # elif defined(__GNUC__) # if __GNUC__ < 8 # error "A more recent GCC is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # else # pragma GCC push_options # pragma GCC target ("arch=armv8.2-a+sha3") # define MBEDTLS_POP_TARGET_PRAGMA # endif # else # error "Only GCC and Clang supported for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # endif # endif /* *INDENT-ON* */ # endif # if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) # if defined(__unix__) # if defined(__linux__) /* Our preferred method of detection is getauxval() */ # include # if !defined(HWCAP_SHA512) /* The same header that declares getauxval() should provide the HWCAP_xxx * constants to analyze its return value. However, the libc may be too * old to have the constant that we need. So if it's missing, assume that * the value is the same one used by the Linux kernel ABI. */ # define HWCAP_SHA512 (1 << 21) # endif # endif /* Use SIGILL on Unix, and fall back to it on Linux */ # include # endif # endif #elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) # undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY # undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT #endif #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) /* * Capability detection code comes early, so we can disable * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found */ #if defined(HWCAP_SHA512) static int mbedtls_a64_crypto_sha512_determine_support(void) { return (getauxval(AT_HWCAP) & HWCAP_SHA512) ? 1 : 0; } #elif defined(__APPLE__) #include #include static int mbedtls_a64_crypto_sha512_determine_support(void) { int value = 0; size_t value_len = sizeof(value); int ret = sysctlbyname("hw.optional.armv8_2_sha512", &value, &value_len, NULL, 0); return ret == 0 && value != 0; } #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) /* * As of March 2022, there don't appear to be any PF_ARM_V8_* flags * available to pass to IsProcessorFeaturePresent() to check for * SHA-512 support. So we fall back to the C code only. */ #if defined(_MSC_VER) #pragma message "No mechanism to detect A64_CRYPTO found, using C code only" #else #warning "No mechanism to detect A64_CRYPTO found, using C code only" #endif #elif defined(__unix__) && defined(SIG_SETMASK) /* Detection with SIGILL, setjmp() and longjmp() */ #include #include static jmp_buf return_from_sigill; /* * A64 SHA512 support detection via SIGILL */ static void sigill_handler(int signal) { (void) signal; longjmp(return_from_sigill, 1); } static int mbedtls_a64_crypto_sha512_determine_support(void) { struct sigaction old_action, new_action; sigset_t old_mask; if (sigprocmask(0, NULL, &old_mask)) { return 0; } sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; new_action.sa_handler = sigill_handler; sigaction(SIGILL, &new_action, &old_action); static int ret = 0; if (setjmp(return_from_sigill) == 0) { /* First return only */ /* If this traps, we will return a second time from setjmp() with 1 */ asm ("sha512h q0, q0, v0.2d" : : : "v0"); ret = 1; } sigaction(SIGILL, &old_action, NULL); sigprocmask(SIG_SETMASK, &old_mask, NULL); return ret; } #else #warning "No mechanism to detect A64_CRYPTO found, using C code only" #undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT #endif /* HWCAP_SHA512, __APPLE__, __unix__ && SIG_SETMASK */ #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ #if !defined(MBEDTLS_SHA512_ALT) #define SHA512_BLOCK_SIZE 128 #if defined(MBEDTLS_SHA512_SMALLER) static void sha512_put_uint64_be(uint64_t n, unsigned char *b, uint8_t i) { MBEDTLS_PUT_UINT64_BE(n, b, i); } #else #define sha512_put_uint64_be MBEDTLS_PUT_UINT64_BE #endif /* MBEDTLS_SHA512_SMALLER */ void mbedtls_sha512_init(mbedtls_sha512_context *ctx) { memset(ctx, 0, sizeof(mbedtls_sha512_context)); } void mbedtls_sha512_free(mbedtls_sha512_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha512_context)); } void mbedtls_sha512_clone(mbedtls_sha512_context *dst, const mbedtls_sha512_context *src) { *dst = *src; } /* * SHA-512 context setup */ int mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384) { #if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) if (is384 != 0 && is384 != 1) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #elif defined(MBEDTLS_SHA512_C) if (is384 != 0) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #else /* defined MBEDTLS_SHA384_C only */ if (is384 == 0) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #endif ctx->total[0] = 0; ctx->total[1] = 0; if (is384 == 0) { #if defined(MBEDTLS_SHA512_C) ctx->state[0] = UL64(0x6A09E667F3BCC908); ctx->state[1] = UL64(0xBB67AE8584CAA73B); ctx->state[2] = UL64(0x3C6EF372FE94F82B); ctx->state[3] = UL64(0xA54FF53A5F1D36F1); ctx->state[4] = UL64(0x510E527FADE682D1); ctx->state[5] = UL64(0x9B05688C2B3E6C1F); ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); ctx->state[7] = UL64(0x5BE0CD19137E2179); #endif /* MBEDTLS_SHA512_C */ } else { #if defined(MBEDTLS_SHA384_C) ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); ctx->state[1] = UL64(0x629A292A367CD507); ctx->state[2] = UL64(0x9159015A3070DD17); ctx->state[3] = UL64(0x152FECD8F70E5939); ctx->state[4] = UL64(0x67332667FFC00B31); ctx->state[5] = UL64(0x8EB44A8768581511); ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); ctx->state[7] = UL64(0x47B5481DBEFA4FA4); #endif /* MBEDTLS_SHA384_C */ } #if defined(MBEDTLS_SHA384_C) ctx->is384 = is384; #endif return 0; } #if !defined(MBEDTLS_SHA512_PROCESS_ALT) /* * Round constants */ static const uint64_t K[80] = { UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) }; #endif #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) # define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many # define mbedtls_internal_sha512_process_a64_crypto mbedtls_internal_sha512_process #endif /* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY, * under the MIT licence; dual-licensed as Apache 2 with his kind permission. */ #if defined(__clang__) && \ (__clang_major__ < 13 || \ (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0)) static inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y) { asm ("sha512su0 %0.2D,%1.2D" : "+w" (x) : "w" (y)); return x; } static inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) { asm ("sha512su1 %0.2D,%1.2D,%2.2D" : "+w" (x) : "w" (y), "w" (z)); return x; } static inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) { asm ("sha512h %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z)); return x; } static inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) { asm ("sha512h2 %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z)); return x; } #endif /* __clang__ etc */ static size_t mbedtls_internal_sha512_process_many_a64_crypto( mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len) { uint64x2_t ab = vld1q_u64(&ctx->state[0]); uint64x2_t cd = vld1q_u64(&ctx->state[2]); uint64x2_t ef = vld1q_u64(&ctx->state[4]); uint64x2_t gh = vld1q_u64(&ctx->state[6]); size_t processed = 0; for (; len >= SHA512_BLOCK_SIZE; processed += SHA512_BLOCK_SIZE, msg += SHA512_BLOCK_SIZE, len -= SHA512_BLOCK_SIZE) { uint64x2_t initial_sum, sum, intermed; uint64x2_t ab_orig = ab; uint64x2_t cd_orig = cd; uint64x2_t ef_orig = ef; uint64x2_t gh_orig = gh; uint64x2_t s0 = (uint64x2_t) vld1q_u8(msg + 16 * 0); uint64x2_t s1 = (uint64x2_t) vld1q_u8(msg + 16 * 1); uint64x2_t s2 = (uint64x2_t) vld1q_u8(msg + 16 * 2); uint64x2_t s3 = (uint64x2_t) vld1q_u8(msg + 16 * 3); uint64x2_t s4 = (uint64x2_t) vld1q_u8(msg + 16 * 4); uint64x2_t s5 = (uint64x2_t) vld1q_u8(msg + 16 * 5); uint64x2_t s6 = (uint64x2_t) vld1q_u8(msg + 16 * 6); uint64x2_t s7 = (uint64x2_t) vld1q_u8(msg + 16 * 7); #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* assume LE if these not defined; untested on BE */ s0 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s0))); s1 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s1))); s2 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s2))); s3 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s3))); s4 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s4))); s5 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s5))); s6 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s6))); s7 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s7))); #endif /* Rounds 0 and 1 */ initial_sum = vaddq_u64(s0, vld1q_u64(&K[0])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); gh = vsha512h2q_u64(intermed, cd, ab); cd = vaddq_u64(cd, intermed); /* Rounds 2 and 3 */ initial_sum = vaddq_u64(s1, vld1q_u64(&K[2])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); ef = vsha512h2q_u64(intermed, ab, gh); ab = vaddq_u64(ab, intermed); /* Rounds 4 and 5 */ initial_sum = vaddq_u64(s2, vld1q_u64(&K[4])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); cd = vsha512h2q_u64(intermed, gh, ef); gh = vaddq_u64(gh, intermed); /* Rounds 6 and 7 */ initial_sum = vaddq_u64(s3, vld1q_u64(&K[6])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); ab = vsha512h2q_u64(intermed, ef, cd); ef = vaddq_u64(ef, intermed); /* Rounds 8 and 9 */ initial_sum = vaddq_u64(s4, vld1q_u64(&K[8])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); gh = vsha512h2q_u64(intermed, cd, ab); cd = vaddq_u64(cd, intermed); /* Rounds 10 and 11 */ initial_sum = vaddq_u64(s5, vld1q_u64(&K[10])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); ef = vsha512h2q_u64(intermed, ab, gh); ab = vaddq_u64(ab, intermed); /* Rounds 12 and 13 */ initial_sum = vaddq_u64(s6, vld1q_u64(&K[12])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); cd = vsha512h2q_u64(intermed, gh, ef); gh = vaddq_u64(gh, intermed); /* Rounds 14 and 15 */ initial_sum = vaddq_u64(s7, vld1q_u64(&K[14])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); ab = vsha512h2q_u64(intermed, ef, cd); ef = vaddq_u64(ef, intermed); for (unsigned int t = 16; t < 80; t += 16) { /* Rounds t and t + 1 */ s0 = vsha512su1q_u64(vsha512su0q_u64(s0, s1), s7, vextq_u64(s4, s5, 1)); initial_sum = vaddq_u64(s0, vld1q_u64(&K[t])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); gh = vsha512h2q_u64(intermed, cd, ab); cd = vaddq_u64(cd, intermed); /* Rounds t + 2 and t + 3 */ s1 = vsha512su1q_u64(vsha512su0q_u64(s1, s2), s0, vextq_u64(s5, s6, 1)); initial_sum = vaddq_u64(s1, vld1q_u64(&K[t + 2])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); ef = vsha512h2q_u64(intermed, ab, gh); ab = vaddq_u64(ab, intermed); /* Rounds t + 4 and t + 5 */ s2 = vsha512su1q_u64(vsha512su0q_u64(s2, s3), s1, vextq_u64(s6, s7, 1)); initial_sum = vaddq_u64(s2, vld1q_u64(&K[t + 4])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); cd = vsha512h2q_u64(intermed, gh, ef); gh = vaddq_u64(gh, intermed); /* Rounds t + 6 and t + 7 */ s3 = vsha512su1q_u64(vsha512su0q_u64(s3, s4), s2, vextq_u64(s7, s0, 1)); initial_sum = vaddq_u64(s3, vld1q_u64(&K[t + 6])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); ab = vsha512h2q_u64(intermed, ef, cd); ef = vaddq_u64(ef, intermed); /* Rounds t + 8 and t + 9 */ s4 = vsha512su1q_u64(vsha512su0q_u64(s4, s5), s3, vextq_u64(s0, s1, 1)); initial_sum = vaddq_u64(s4, vld1q_u64(&K[t + 8])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); gh = vsha512h2q_u64(intermed, cd, ab); cd = vaddq_u64(cd, intermed); /* Rounds t + 10 and t + 11 */ s5 = vsha512su1q_u64(vsha512su0q_u64(s5, s6), s4, vextq_u64(s1, s2, 1)); initial_sum = vaddq_u64(s5, vld1q_u64(&K[t + 10])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); ef = vsha512h2q_u64(intermed, ab, gh); ab = vaddq_u64(ab, intermed); /* Rounds t + 12 and t + 13 */ s6 = vsha512su1q_u64(vsha512su0q_u64(s6, s7), s5, vextq_u64(s2, s3, 1)); initial_sum = vaddq_u64(s6, vld1q_u64(&K[t + 12])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); cd = vsha512h2q_u64(intermed, gh, ef); gh = vaddq_u64(gh, intermed); /* Rounds t + 14 and t + 15 */ s7 = vsha512su1q_u64(vsha512su0q_u64(s7, s0), s6, vextq_u64(s3, s4, 1)); initial_sum = vaddq_u64(s7, vld1q_u64(&K[t + 14])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); ab = vsha512h2q_u64(intermed, ef, cd); ef = vaddq_u64(ef, intermed); } ab = vaddq_u64(ab, ab_orig); cd = vaddq_u64(cd, cd_orig); ef = vaddq_u64(ef, ef_orig); gh = vaddq_u64(gh, gh_orig); } vst1q_u64(&ctx->state[0], ab); vst1q_u64(&ctx->state[2], cd); vst1q_u64(&ctx->state[4], ef); vst1q_u64(&ctx->state[6], gh); return processed; } #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) /* * This function is for internal use only if we are building both C and A64 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process() */ static #endif int mbedtls_internal_sha512_process_a64_crypto(mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_SIZE]) { return (mbedtls_internal_sha512_process_many_a64_crypto(ctx, data, SHA512_BLOCK_SIZE) == SHA512_BLOCK_SIZE) ? 0 : -1; } #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_POP_TARGET_PRAGMA) #if defined(__clang__) #pragma clang attribute pop #elif defined(__GNUC__) #pragma GCC pop_options #endif #undef MBEDTLS_POP_TARGET_PRAGMA #endif #if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) #define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many #define mbedtls_internal_sha512_process_c mbedtls_internal_sha512_process #endif #if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) /* * This function is for internal use only if we are building both C and A64 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process() */ static #endif int mbedtls_internal_sha512_process_c(mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_SIZE]) { int i; struct { uint64_t temp1, temp2, W[80]; uint64_t A[8]; } local; #define SHR(x, n) ((x) >> (n)) #define ROTR(x, n) (SHR((x), (n)) | ((x) << (64 - (n)))) #define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) #define S1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6)) #define S2(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) #define S3(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) #define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y)))) #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define P(a, b, c, d, e, f, g, h, x, K) \ do \ { \ local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x); \ local.temp2 = S2(a) + F0((a), (b), (c)); \ (d) += local.temp1; (h) = local.temp1 + local.temp2; \ } while (0) for (i = 0; i < 8; i++) { local.A[i] = ctx->state[i]; } #if defined(MBEDTLS_SHA512_SMALLER) for (i = 0; i < 80; i++) { if (i < 16) { local.W[i] = MBEDTLS_GET_UINT64_BE(data, i << 3); } else { local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + S0(local.W[i - 15]) + local.W[i - 16]; } P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i], K[i]); local.temp1 = local.A[7]; local.A[7] = local.A[6]; local.A[6] = local.A[5]; local.A[5] = local.A[4]; local.A[4] = local.A[3]; local.A[3] = local.A[2]; local.A[2] = local.A[1]; local.A[1] = local.A[0]; local.A[0] = local.temp1; } #else /* MBEDTLS_SHA512_SMALLER */ for (i = 0; i < 16; i++) { local.W[i] = MBEDTLS_GET_UINT64_BE(data, i << 3); } for (; i < 80; i++) { local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + S0(local.W[i - 15]) + local.W[i - 16]; } i = 0; do { P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i], K[i]); i++; P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.W[i], K[i]); i++; P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.W[i], K[i]); i++; P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.W[i], K[i]); i++; P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.W[i], K[i]); i++; P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.W[i], K[i]); i++; P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.W[i], K[i]); i++; P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.W[i], K[i]); i++; } while (i < 80); #endif /* MBEDTLS_SHA512_SMALLER */ for (i = 0; i < 8; i++) { ctx->state[i] += local.A[i]; } /* Zeroise buffers and variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) static size_t mbedtls_internal_sha512_process_many_c( mbedtls_sha512_context *ctx, const uint8_t *data, size_t len) { size_t processed = 0; while (len >= SHA512_BLOCK_SIZE) { if (mbedtls_internal_sha512_process_c(ctx, data) != 0) { return 0; } data += SHA512_BLOCK_SIZE; len -= SHA512_BLOCK_SIZE; processed += SHA512_BLOCK_SIZE; } return processed; } #endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) static int mbedtls_a64_crypto_sha512_has_support(void) { static int done = 0; static int supported = 0; if (!done) { supported = mbedtls_a64_crypto_sha512_determine_support(); done = 1; } return supported; } static size_t mbedtls_internal_sha512_process_many(mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len) { if (mbedtls_a64_crypto_sha512_has_support()) { return mbedtls_internal_sha512_process_many_a64_crypto(ctx, msg, len); } else { return mbedtls_internal_sha512_process_many_c(ctx, msg, len); } } int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_SIZE]) { if (mbedtls_a64_crypto_sha512_has_support()) { return mbedtls_internal_sha512_process_a64_crypto(ctx, data); } else { return mbedtls_internal_sha512_process_c(ctx, data); } } #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ /* * SHA-512 process buffer */ int mbedtls_sha512_update(mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; unsigned int left; if (ilen == 0) { return 0; } left = (unsigned int) (ctx->total[0] & 0x7F); fill = SHA512_BLOCK_SIZE - left; ctx->total[0] += (uint64_t) ilen; if (ctx->total[0] < (uint64_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= SHA512_BLOCK_SIZE) { size_t processed = mbedtls_internal_sha512_process_many(ctx, input, ilen); if (processed < SHA512_BLOCK_SIZE) { return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } input += processed; ilen -= processed; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } /* * SHA-512 final digest */ int mbedtls_sha512_finish(mbedtls_sha512_context *ctx, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned used; uint64_t high, low; int truncated = 0; /* * Add padding: 0x80 then 0x00 until 16 bytes remain for the length */ used = ctx->total[0] & 0x7F; ctx->buffer[used++] = 0x80; if (used <= 112) { /* Enough room for padding + length in current block */ memset(ctx->buffer + used, 0, 112 - used); } else { /* We'll need an extra block */ memset(ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used); if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) { goto exit; } memset(ctx->buffer, 0, 112); } /* * Add message length */ high = (ctx->total[0] >> 61) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); sha512_put_uint64_be(high, ctx->buffer, 112); sha512_put_uint64_be(low, ctx->buffer, 120); if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) { goto exit; } /* * Output final state */ sha512_put_uint64_be(ctx->state[0], output, 0); sha512_put_uint64_be(ctx->state[1], output, 8); sha512_put_uint64_be(ctx->state[2], output, 16); sha512_put_uint64_be(ctx->state[3], output, 24); sha512_put_uint64_be(ctx->state[4], output, 32); sha512_put_uint64_be(ctx->state[5], output, 40); #if defined(MBEDTLS_SHA384_C) truncated = ctx->is384; #endif if (!truncated) { sha512_put_uint64_be(ctx->state[6], output, 48); sha512_put_uint64_be(ctx->state[7], output, 56); } ret = 0; exit: mbedtls_sha512_free(ctx); return ret; } #endif /* !MBEDTLS_SHA512_ALT */ /* * output = SHA-512( input buffer ) */ int mbedtls_sha512(const unsigned char *input, size_t ilen, unsigned char *output, int is384) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha512_context ctx; #if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) if (is384 != 0 && is384 != 1) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #elif defined(MBEDTLS_SHA512_C) if (is384 != 0) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #else /* defined MBEDTLS_SHA384_C only */ if (is384 == 0) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #endif mbedtls_sha512_init(&ctx); if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) { goto exit; } if ((ret = mbedtls_sha512_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_sha512_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_sha512_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors */ static const unsigned char sha_test_buf[3][113] = { { "abc" }, { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, { "" } }; static const size_t sha_test_buflen[3] = { 3, 112, 1000 }; typedef const unsigned char (sha_test_sum_t)[64]; /* * SHA-384 test vectors */ #if defined(MBEDTLS_SHA384_C) static sha_test_sum_t sha384_test_sum[] = { { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 } }; #endif /* MBEDTLS_SHA384_C */ /* * SHA-512 test vectors */ #if defined(MBEDTLS_SHA512_C) static sha_test_sum_t sha512_test_sum[] = { { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } }; #endif /* MBEDTLS_SHA512_C */ static int mbedtls_sha512_common_self_test(int verbose, int is384) { int i, buflen, ret = 0; unsigned char *buf; unsigned char sha512sum[64]; mbedtls_sha512_context ctx; #if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) sha_test_sum_t *sha_test_sum = (is384) ? sha384_test_sum : sha512_test_sum; #elif defined(MBEDTLS_SHA512_C) sha_test_sum_t *sha_test_sum = sha512_test_sum; #else sha_test_sum_t *sha_test_sum = sha384_test_sum; #endif buf = mbedtls_calloc(1024, sizeof(unsigned char)); if (NULL == buf) { if (verbose != 0) { mbedtls_printf("Buffer allocation failed\n"); } return 1; } mbedtls_sha512_init(&ctx); for (i = 0; i < 3; i++) { if (verbose != 0) { mbedtls_printf(" SHA-%d test #%d: ", 512 - is384 * 128, i + 1); } if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) { goto fail; } if (i == 2) { memset(buf, 'a', buflen = 1000); for (int j = 0; j < 1000; j++) { ret = mbedtls_sha512_update(&ctx, buf, buflen); if (ret != 0) { goto fail; } } } else { ret = mbedtls_sha512_update(&ctx, sha_test_buf[i], sha_test_buflen[i]); if (ret != 0) { goto fail; } } if ((ret = mbedtls_sha512_finish(&ctx, sha512sum)) != 0) { goto fail; } if (memcmp(sha512sum, sha_test_sum[i], 64 - is384 * 16) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } goto exit; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } exit: mbedtls_sha512_free(&ctx); mbedtls_free(buf); return ret; } #if defined(MBEDTLS_SHA512_C) int mbedtls_sha512_self_test(int verbose) { return mbedtls_sha512_common_self_test(verbose, 0); } #endif /* MBEDTLS_SHA512_C */ #if defined(MBEDTLS_SHA384_C) int mbedtls_sha384_self_test(int verbose) { return mbedtls_sha512_common_self_test(verbose, 1); } #endif /* MBEDTLS_SHA384_C */ #undef ARRAY_LENGTH #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SHA512_C || MBEDTLS_SHA384_C */ webfakes/src/mbedtls/library/pkcs7.c0000644000176200001440000005431114740737024017135 0ustar liggesusers/* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "mbedtls/build_info.h" #if defined(MBEDTLS_PKCS7_C) #include "mbedtls/pkcs7.h" #include "x509_internal.h" #include "mbedtls/asn1.h" #include "mbedtls/x509_crt.h" #include "mbedtls/x509_crl.h" #include "mbedtls/oid.h" #include "mbedtls/error.h" #if defined(MBEDTLS_FS_IO) #include #include #endif #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_HAVE_TIME_DATE) #include #endif /** * Initializes the mbedtls_pkcs7 structure. */ void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7) { memset(pkcs7, 0, sizeof(*pkcs7)); } static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end, size_t *len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); if (ret != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } else if ((size_t) (end - *p) != *len) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return ret; } /** * version Version * Version ::= INTEGER **/ static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_asn1_get_int(p, end, ver); if (ret != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret); } /* If version != 1, return invalid version */ if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) { ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION; } return ret; } /** * ContentInfo ::= SEQUENCE { * contentType ContentType, * content * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } **/ static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end, unsigned char **seq_end, mbedtls_pkcs7_buf *pkcs7) { size_t len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *start = *p; ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { *p = start; return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } *seq_end = *p + len; ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID); if (ret != 0) { *p = start; return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } pkcs7->tag = MBEDTLS_ASN1_OID; pkcs7->len = len; pkcs7->p = *p; *p += len; return ret; } /** * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * This is from x509.h **/ static int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end, mbedtls_x509_buf *alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); } return ret; } /** * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier **/ static int pkcs7_get_digest_algorithm_set(unsigned char **p, unsigned char *end, mbedtls_x509_buf *alg) { size_t len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); } end = *p + len; ret = mbedtls_asn1_get_alg_null(p, end, alg); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); } /** For now, it assumes there is only one digest algorithm specified **/ if (*p != end) { return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; } return 0; } /** * certificates :: SET OF ExtendedCertificateOrCertificate, * ExtendedCertificateOrCertificate ::= CHOICE { * certificate Certificate -- x509, * extendedCertificate[0] IMPLICIT ExtendedCertificate } * Return number of certificates added to the signed data, * 0 or higher is valid. * Return negative error code for failure. **/ static int pkcs7_get_certificates(unsigned char **p, unsigned char *end, mbedtls_x509_crt *certs) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len1 = 0; size_t len2 = 0; unsigned char *end_set, *end_cert, *start; ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return 0; } if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); } start = *p; end_set = *p + len1; ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret); } end_cert = *p + len2; /* * This is to verify that there is only one signer certificate. It seems it is * not easy to differentiate between the chain vs different signer's certificate. * So, we support only the root certificate and the single signer. * The behaviour would be improved with addition of multiple signer support. */ if (end_cert != end_set) { return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; } if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) { return MBEDTLS_ERR_PKCS7_INVALID_CERT; } *p = end_cert; /* * Since in this version we strictly support single certificate, and reaching * here implies we have parsed successfully, we return 1. */ return 1; } /** * EncryptedDigest ::= OCTET STRING **/ static int pkcs7_get_signature(unsigned char **p, unsigned char *end, mbedtls_pkcs7_buf *signature) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING); if (ret != 0) { return ret; } signature->tag = MBEDTLS_ASN1_OCTET_STRING; signature->len = len; signature->p = *p; *p = *p + len; return 0; } static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer) { mbedtls_x509_name *name_cur; mbedtls_x509_name *name_prv; if (signer == NULL) { return; } name_cur = signer->issuer.next; while (name_cur != NULL) { name_prv = name_cur; name_cur = name_cur->next; mbedtls_free(name_prv); } signer->issuer.next = NULL; } /** * SignerInfo ::= SEQUENCE { * version Version; * issuerAndSerialNumber IssuerAndSerialNumber, * digestAlgorithm DigestAlgorithmIdentifier, * authenticatedAttributes * [0] IMPLICIT Attributes OPTIONAL, * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, * encryptedDigest EncryptedDigest, * unauthenticatedAttributes * [1] IMPLICIT Attributes OPTIONAL, * Returns 0 if the signerInfo is valid. * Return negative error code for failure. * Structure must not contain vales for authenticatedAttributes * and unauthenticatedAttributes. **/ static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end, mbedtls_pkcs7_signer_info *signer, mbedtls_x509_buf *alg) { unsigned char *end_signer, *end_issuer_and_sn; int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (asn1_ret != 0) { goto out; } end_signer = *p + len; ret = pkcs7_get_version(p, end_signer, &signer->version); if (ret != 0) { goto out; } asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (asn1_ret != 0) { goto out; } end_issuer_and_sn = *p + len; /* Parsing IssuerAndSerialNumber */ signer->issuer_raw.p = *p; asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (asn1_ret != 0) { goto out; } ret = mbedtls_x509_get_name(p, *p + len, &signer->issuer); if (ret != 0) { goto out; } signer->issuer_raw.len = (size_t) (*p - signer->issuer_raw.p); ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial); if (ret != 0) { goto out; } /* ensure no extra or missing bytes */ if (*p != end_issuer_and_sn) { ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; goto out; } ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier); if (ret != 0) { goto out; } /* Check that the digest algorithm used matches the one provided earlier */ if (signer->alg_identifier.tag != alg->tag || signer->alg_identifier.len != alg->len || memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) { ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; goto out; } /* Assume authenticatedAttributes is nonexistent */ ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier); if (ret != 0) { goto out; } ret = pkcs7_get_signature(p, end_signer, &signer->sig); if (ret != 0) { goto out; } /* Do not permit any unauthenticated attributes */ if (*p != end_signer) { ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; } out: if (asn1_ret != 0 || ret != 0) { pkcs7_free_signer_info(signer); ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, asn1_ret); } return ret; } /** * SignerInfos ::= SET of SignerInfo * Return number of signers added to the signed data, * 0 or higher is valid. * Return negative error code for failure. **/ static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end, mbedtls_pkcs7_signer_info *signers_set, mbedtls_x509_buf *digest_alg) { unsigned char *end_set; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int count = 0; size_t len = 0; ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret); } /* Detect zero signers */ if (len == 0) { return 0; } end_set = *p + len; ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg); if (ret != 0) { return ret; } count++; mbedtls_pkcs7_signer_info *prev = signers_set; while (*p != end_set) { mbedtls_pkcs7_signer_info *signer = mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info)); if (!signer) { ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; goto cleanup; } ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg); if (ret != 0) { mbedtls_free(signer); goto cleanup; } prev->next = signer; prev = signer; count++; } return count; cleanup: pkcs7_free_signer_info(signers_set); mbedtls_pkcs7_signer_info *signer = signers_set->next; while (signer != NULL) { prev = signer; signer = signer->next; pkcs7_free_signer_info(prev); mbedtls_free(prev); } signers_set->next = NULL; return ret; } /** * SignedData ::= SEQUENCE { * version Version, * digestAlgorithms DigestAlgorithmIdentifiers, * contentInfo ContentInfo, * certificates * [0] IMPLICIT ExtendedCertificatesAndCertificates * OPTIONAL, * crls * [0] IMPLICIT CertificateRevocationLists OPTIONAL, * signerInfos SignerInfos } */ static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen, mbedtls_pkcs7_signed_data *signed_data) { unsigned char *p = buf; unsigned char *end = buf + buflen; unsigned char *end_content_info = NULL; size_t len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_alg; ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); } if (p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* Get version of signed data */ ret = pkcs7_get_version(&p, end, &signed_data->version); if (ret != 0) { return ret; } /* Get digest algorithm */ ret = pkcs7_get_digest_algorithm_set(&p, end, &signed_data->digest_alg_identifiers); if (ret != 0) { return ret; } ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg); if (ret != 0) { return MBEDTLS_ERR_PKCS7_INVALID_ALG; } mbedtls_pkcs7_buf content_type; memset(&content_type, 0, sizeof(content_type)); ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type); if (ret != 0) { return ret; } if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) { return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO; } if (p != end_content_info) { /* Determine if valid content is present */ ret = mbedtls_asn1_get_tag(&p, end_content_info, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } p += len; if (p != end_content_info) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } /* Valid content is present - this is not supported */ return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; } /* Look for certificates, there may or may not be any */ mbedtls_x509_crt_init(&signed_data->certs); ret = pkcs7_get_certificates(&p, end, &signed_data->certs); if (ret < 0) { return ret; } signed_data->no_of_certs = ret; /* * Currently CRLs are not supported. If CRL exist, the parsing will fail * at next step of getting signers info and return error as invalid * signer info. */ signed_data->no_of_crls = 0; /* Get signers info */ ret = pkcs7_get_signers_info_set(&p, end, &signed_data->signers, &signed_data->digest_alg_identifiers); if (ret < 0) { return ret; } signed_data->no_of_signers = ret; /* Don't permit trailing data */ if (p != end) { return MBEDTLS_ERR_PKCS7_INVALID_FORMAT; } return 0; } int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, const size_t buflen) { unsigned char *p; unsigned char *end; size_t len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (pkcs7 == NULL) { return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; } /* make an internal copy of the buffer for parsing */ pkcs7->raw.p = p = mbedtls_calloc(1, buflen); if (pkcs7->raw.p == NULL) { ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; goto out; } memcpy(p, buf, buflen); pkcs7->raw.len = buflen; end = p + buflen; ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); goto out; } if ((size_t) (end - p) != len) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); goto out; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { goto out; } p = pkcs7->raw.p; len = buflen; goto try_data; } if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) { /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */ if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len) || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len) || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len) || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len) || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) { /* OID is valid according to the spec, but unsupported */ ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; } else { /* OID is invalid according to the spec */ ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; } goto out; } p += len; ret = pkcs7_get_next_content_len(&p, end, &len); if (ret != 0) { goto out; } /* ensure no extra/missing data */ if (p + len != end) { ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; goto out; } try_data: ret = pkcs7_get_signed_data(p, len, &pkcs7->signed_data); if (ret != 0) { goto out; } ret = MBEDTLS_PKCS7_SIGNED_DATA; out: if (ret < 0) { mbedtls_pkcs7_free(pkcs7); } return ret; } static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *data, size_t datalen, const int is_data_hash) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *hash; mbedtls_pk_context pk_cxt = cert->pk; const mbedtls_md_info_t *md_info; mbedtls_md_type_t md_alg; mbedtls_pkcs7_signer_info *signer; if (pkcs7->signed_data.no_of_signers == 0) { return MBEDTLS_ERR_PKCS7_INVALID_CERT; } if (mbedtls_x509_time_is_past(&cert->valid_to) || mbedtls_x509_time_is_future(&cert->valid_from)) { return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID; } ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg); if (ret != 0) { return ret; } md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; } hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1); if (hash == NULL) { return MBEDTLS_ERR_PKCS7_ALLOC_FAILED; } /* BEGIN must free hash before jumping out */ if (is_data_hash) { if (datalen != mbedtls_md_get_size(md_info)) { ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; } else { memcpy(hash, data, datalen); } } else { ret = mbedtls_md(md_info, data, datalen, hash); } if (ret != 0) { mbedtls_free(hash); return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; } /* assume failure */ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; /* * Potential TODOs * Currently we iterate over all signers and return success if any of them * verify. * * However, we could make this better by checking against the certificate's * identification and SignerIdentifier fields first. That would also allow * us to distinguish between 'no signature for key' and 'signature for key * failed to validate'. */ for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) { ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash, mbedtls_md_get_size(md_info), signer->sig.p, signer->sig.len); if (ret == 0) { break; } } mbedtls_free(hash); /* END must free hash before jumping out */ return ret; } int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *data, size_t datalen) { if (data == NULL) { return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; } return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0); } int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *hash, size_t hashlen) { if (hash == NULL) { return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; } return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1); } /* * Unallocate all pkcs7 data */ void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7) { mbedtls_pkcs7_signer_info *signer_cur; mbedtls_pkcs7_signer_info *signer_prev; if (pkcs7 == NULL || pkcs7->raw.p == NULL) { return; } mbedtls_free(pkcs7->raw.p); mbedtls_x509_crt_free(&pkcs7->signed_data.certs); mbedtls_x509_crl_free(&pkcs7->signed_data.crl); signer_cur = pkcs7->signed_data.signers.next; pkcs7_free_signer_info(&pkcs7->signed_data.signers); while (signer_cur != NULL) { signer_prev = signer_cur; signer_cur = signer_prev->next; pkcs7_free_signer_info(signer_prev); mbedtls_free(signer_prev); } pkcs7->raw.p = NULL; } #endif webfakes/src/mbedtls/library/aria.c0000644000176200001440000010410114740737024017013 0ustar liggesusers/* * ARIA implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * This implementation is based on the following standards: * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf * [2] https://tools.ietf.org/html/rfc5794 */ #include "common.h" #if defined(MBEDTLS_ARIA_C) #include "mbedtls/aria.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_ARIA_ALT) #include "mbedtls/platform_util.h" /* * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes * * This is submatrix P1 in [1] Appendix B.1 * * Common compilers fail to translate this to minimal number of instructions, * so let's provide asm versions for common platforms with C fallback. */ #if defined(MBEDTLS_HAVE_ASM) #if defined(__arm__) /* rev16 available from v6 up */ /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(__GNUC__) && \ (!defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000) && \ __ARM_ARCH >= 6 static inline uint32_t aria_p1(uint32_t x) { uint32_t r; __asm("rev16 %0, %1" : "=l" (r) : "l" (x)); return r; } #define ARIA_P1 aria_p1 #elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ (__TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3) static inline uint32_t aria_p1(uint32_t x) { uint32_t r; __asm("rev16 r, x"); return r; } #define ARIA_P1 aria_p1 #endif #endif /* arm */ #if defined(__GNUC__) && \ defined(__i386__) || defined(__amd64__) || defined(__x86_64__) /* I couldn't find an Intel equivalent of rev16, so two instructions */ #define ARIA_P1(x) ARIA_P2(ARIA_P3(x)) #endif /* x86 gnuc */ #endif /* MBEDTLS_HAVE_ASM && GNUC */ #if !defined(ARIA_P1) #define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) #endif /* * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits * * This is submatrix P2 in [1] Appendix B.1 * * Common compilers will translate this to a single instruction. */ #define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16)) /* * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness * * This is submatrix P3 in [1] Appendix B.1 */ #define ARIA_P3(x) MBEDTLS_BSWAP32(x) /* * ARIA Affine Transform * (a, b, c, d) = state in/out * * If we denote the first byte of input by 0, ..., the last byte by f, * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef. * * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple * rearrangements on adjacent pairs, output is: * * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe * = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd * = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe * = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef * = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef * * Note: another presentation of the A transform can be found as the first * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4. * The implementation below uses only P1 and P2 as they are sufficient. */ static inline void aria_a(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) { uint32_t ta, tb, tc; ta = *b; // 4567 *b = *a; // 0123 *a = ARIA_P2(ta); // 6745 tb = ARIA_P2(*d); // efcd *d = ARIA_P1(*c); // 98ba *c = ARIA_P1(tb); // fedc ta ^= *d; // 4567+98ba tc = ARIA_P2(*b); // 2301 ta = ARIA_P1(ta) ^ tc ^ *c; // 2301+5476+89ab+fedc tb ^= ARIA_P2(*d); // ba98+efcd tc ^= ARIA_P1(*a); // 2301+7654 *b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT tb = ARIA_P2(tb) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc *a ^= ARIA_P1(tb); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT ta = ARIA_P2(ta); // 0123+7654+ab89+dcfe *d ^= ARIA_P1(ta) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT tc = ARIA_P2(tc); // 0123+5476 *c ^= ARIA_P1(tc) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT } /* * ARIA Substitution Layer SL1 / SL2 * (a, b, c, d) = state in/out * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below) * * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1 * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2 */ static inline void aria_sl(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, const uint8_t sa[256], const uint8_t sb[256], const uint8_t sc[256], const uint8_t sd[256]) { *a = ((uint32_t) sa[MBEDTLS_BYTE_0(*a)]) ^ (((uint32_t) sb[MBEDTLS_BYTE_1(*a)]) << 8) ^ (((uint32_t) sc[MBEDTLS_BYTE_2(*a)]) << 16) ^ (((uint32_t) sd[MBEDTLS_BYTE_3(*a)]) << 24); *b = ((uint32_t) sa[MBEDTLS_BYTE_0(*b)]) ^ (((uint32_t) sb[MBEDTLS_BYTE_1(*b)]) << 8) ^ (((uint32_t) sc[MBEDTLS_BYTE_2(*b)]) << 16) ^ (((uint32_t) sd[MBEDTLS_BYTE_3(*b)]) << 24); *c = ((uint32_t) sa[MBEDTLS_BYTE_0(*c)]) ^ (((uint32_t) sb[MBEDTLS_BYTE_1(*c)]) << 8) ^ (((uint32_t) sc[MBEDTLS_BYTE_2(*c)]) << 16) ^ (((uint32_t) sd[MBEDTLS_BYTE_3(*c)]) << 24); *d = ((uint32_t) sa[MBEDTLS_BYTE_0(*d)]) ^ (((uint32_t) sb[MBEDTLS_BYTE_1(*d)]) << 8) ^ (((uint32_t) sc[MBEDTLS_BYTE_2(*d)]) << 16) ^ (((uint32_t) sd[MBEDTLS_BYTE_3(*d)]) << 24); } /* * S-Boxes */ static const uint8_t aria_sb1[256] = { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; static const uint8_t aria_sb2[256] = { 0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46, 0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B, 0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B, 0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB, 0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA, 0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91, 0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38, 0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53, 0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74, 0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26, 0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD, 0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC, 0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E, 0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A, 0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5, 0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8, 0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24, 0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F, 0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33, 0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D, 0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A, 0xAF, 0xBA, 0xB5, 0x81 }; static const uint8_t aria_is1[256] = { 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D }; static const uint8_t aria_is2[256] = { 0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1, 0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3, 0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89, 0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D, 0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98, 0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58, 0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F, 0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE, 0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23, 0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19, 0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55, 0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A, 0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE, 0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0, 0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6, 0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5, 0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13, 0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73, 0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94, 0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3, 0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33, 0x03, 0xA2, 0xAC, 0x60 }; /* * Helper for key schedule: r = FO( p, k ) ^ x */ static void aria_fo_xor(uint32_t r[4], const uint32_t p[4], const uint32_t k[4], const uint32_t x[4]) { uint32_t a, b, c, d; a = p[0] ^ k[0]; b = p[1] ^ k[1]; c = p[2] ^ k[2]; d = p[3] ^ k[3]; aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2); aria_a(&a, &b, &c, &d); r[0] = a ^ x[0]; r[1] = b ^ x[1]; r[2] = c ^ x[2]; r[3] = d ^ x[3]; } /* * Helper for key schedule: r = FE( p, k ) ^ x */ static void aria_fe_xor(uint32_t r[4], const uint32_t p[4], const uint32_t k[4], const uint32_t x[4]) { uint32_t a, b, c, d; a = p[0] ^ k[0]; b = p[1] ^ k[1]; c = p[2] ^ k[2]; d = p[3] ^ k[3]; aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2); aria_a(&a, &b, &c, &d); r[0] = a ^ x[0]; r[1] = b ^ x[1]; r[2] = c ^ x[2]; r[3] = d ^ x[3]; } /* * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup. * * We chose to store bytes into 32-bit words in little-endian format (see * MBEDTLS_GET_UINT32_LE / MBEDTLS_PUT_UINT32_LE ) so we need to reverse * bytes here. */ static void aria_rot128(uint32_t r[4], const uint32_t a[4], const uint32_t b[4], uint8_t n) { uint8_t i, j; uint32_t t, u; const uint8_t n1 = n % 32; // bit offset const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset j = (n / 32) % 4; // initial word offset t = ARIA_P3(b[j]); // big endian for (i = 0; i < 4; i++) { j = (j + 1) % 4; // get next word, big endian u = ARIA_P3(b[j]); t <<= n1; // rotate t |= u >> n2; t = ARIA_P3(t); // back to little endian r[i] = a[i] ^ t; // store t = u; // move to next word } } /* * Set encryption key */ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits) { /* round constant masks */ const uint32_t rc[3][4] = { { 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA }, { 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF }, { 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 } }; int i; uint32_t w[4][4], *w2; if (keybits != 128 && keybits != 192 && keybits != 256) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } /* Copy key to W0 (and potential remainder to W1) */ w[0][0] = MBEDTLS_GET_UINT32_LE(key, 0); w[0][1] = MBEDTLS_GET_UINT32_LE(key, 4); w[0][2] = MBEDTLS_GET_UINT32_LE(key, 8); w[0][3] = MBEDTLS_GET_UINT32_LE(key, 12); memset(w[1], 0, 16); if (keybits >= 192) { w[1][0] = MBEDTLS_GET_UINT32_LE(key, 16); // 192 bit key w[1][1] = MBEDTLS_GET_UINT32_LE(key, 20); } if (keybits == 256) { w[1][2] = MBEDTLS_GET_UINT32_LE(key, 24); // 256 bit key w[1][3] = MBEDTLS_GET_UINT32_LE(key, 28); } i = (keybits - 128) >> 6; // index: 0, 1, 2 ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16 aria_fo_xor(w[1], w[0], rc[i], w[1]); // W1 = FO(W0, CK1) ^ KR i = i < 2 ? i + 1 : 0; aria_fe_xor(w[2], w[1], rc[i], w[0]); // W2 = FE(W1, CK2) ^ W0 i = i < 2 ? i + 1 : 0; aria_fo_xor(w[3], w[2], rc[i], w[1]); // W3 = FO(W2, CK3) ^ W1 for (i = 0; i < 4; i++) { // create round keys w2 = w[(i + 1) & 3]; aria_rot128(ctx->rk[i], w[i], w2, 128 - 19); aria_rot128(ctx->rk[i + 4], w[i], w2, 128 - 31); aria_rot128(ctx->rk[i + 8], w[i], w2, 61); aria_rot128(ctx->rk[i + 12], w[i], w2, 31); } aria_rot128(ctx->rk[16], w[0], w[1], 19); /* w holds enough info to reconstruct the round keys */ mbedtls_platform_zeroize(w, sizeof(w)); return 0; } /* * Set decryption key */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits) { int i, j, k, ret; ret = mbedtls_aria_setkey_enc(ctx, key, keybits); if (ret != 0) { return ret; } /* flip the order of round keys */ for (i = 0, j = ctx->nr; i < j; i++, j--) { for (k = 0; k < 4; k++) { uint32_t t = ctx->rk[i][k]; ctx->rk[i][k] = ctx->rk[j][k]; ctx->rk[j][k] = t; } } /* apply affine transform to middle keys */ for (i = 1; i < ctx->nr; i++) { aria_a(&ctx->rk[i][0], &ctx->rk[i][1], &ctx->rk[i][2], &ctx->rk[i][3]); } return 0; } #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /* * Encrypt a block */ int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx, const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], unsigned char output[MBEDTLS_ARIA_BLOCKSIZE]) { int i; uint32_t a, b, c, d; a = MBEDTLS_GET_UINT32_LE(input, 0); b = MBEDTLS_GET_UINT32_LE(input, 4); c = MBEDTLS_GET_UINT32_LE(input, 8); d = MBEDTLS_GET_UINT32_LE(input, 12); i = 0; while (1) { a ^= ctx->rk[i][0]; b ^= ctx->rk[i][1]; c ^= ctx->rk[i][2]; d ^= ctx->rk[i][3]; i++; aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2); aria_a(&a, &b, &c, &d); a ^= ctx->rk[i][0]; b ^= ctx->rk[i][1]; c ^= ctx->rk[i][2]; d ^= ctx->rk[i][3]; i++; aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2); if (i >= ctx->nr) { break; } aria_a(&a, &b, &c, &d); } /* final key mixing */ a ^= ctx->rk[i][0]; b ^= ctx->rk[i][1]; c ^= ctx->rk[i][2]; d ^= ctx->rk[i][3]; MBEDTLS_PUT_UINT32_LE(a, output, 0); MBEDTLS_PUT_UINT32_LE(b, output, 4); MBEDTLS_PUT_UINT32_LE(c, output, 8); MBEDTLS_PUT_UINT32_LE(d, output, 12); return 0; } /* Initialize context */ void mbedtls_aria_init(mbedtls_aria_context *ctx) { memset(ctx, 0, sizeof(mbedtls_aria_context)); } /* Clear context */ void mbedtls_aria_free(mbedtls_aria_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aria_context)); } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * ARIA-CBC buffer encryption/decryption */ int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx, int mode, size_t length, unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output) { unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } if (length % MBEDTLS_ARIA_BLOCKSIZE) { return MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH; } if (mode == MBEDTLS_ARIA_DECRYPT) { while (length > 0) { memcpy(temp, input, MBEDTLS_ARIA_BLOCKSIZE); mbedtls_aria_crypt_ecb(ctx, input, output); mbedtls_xor(output, output, iv, MBEDTLS_ARIA_BLOCKSIZE); memcpy(iv, temp, MBEDTLS_ARIA_BLOCKSIZE); input += MBEDTLS_ARIA_BLOCKSIZE; output += MBEDTLS_ARIA_BLOCKSIZE; length -= MBEDTLS_ARIA_BLOCKSIZE; } } else { while (length > 0) { mbedtls_xor(output, input, iv, MBEDTLS_ARIA_BLOCKSIZE); mbedtls_aria_crypt_ecb(ctx, output, output); memcpy(iv, output, MBEDTLS_ARIA_BLOCKSIZE); input += MBEDTLS_ARIA_BLOCKSIZE; output += MBEDTLS_ARIA_BLOCKSIZE; length -= MBEDTLS_ARIA_BLOCKSIZE; } } return 0; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * ARIA-CFB128 buffer encryption/decryption */ int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output) { unsigned char c; size_t n; if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } n = *iv_off; /* An overly large value of n can lead to an unlimited * buffer overflow. */ if (n >= MBEDTLS_ARIA_BLOCKSIZE) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } if (mode == MBEDTLS_ARIA_DECRYPT) { while (length--) { if (n == 0) { mbedtls_aria_crypt_ecb(ctx, iv, iv); } c = *input++; *output++ = c ^ iv[n]; iv[n] = c; n = (n + 1) & 0x0F; } } else { while (length--) { if (n == 0) { mbedtls_aria_crypt_ecb(ctx, iv, iv); } iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++); n = (n + 1) & 0x0F; } } *iv_off = n; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * ARIA-CTR buffer encryption/decryption */ int mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output) { int c, i; size_t n; n = *nc_off; /* An overly large value of n can lead to an unlimited * buffer overflow. */ if (n >= MBEDTLS_ARIA_BLOCKSIZE) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } while (length--) { if (n == 0) { mbedtls_aria_crypt_ecb(ctx, nonce_counter, stream_block); for (i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i--) { if (++nonce_counter[i - 1] != 0) { break; } } } c = *input++; *output++ = (unsigned char) (c ^ stream_block[n]); n = (n + 1) & 0x0F; } *nc_off = n; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* !MBEDTLS_ARIA_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * Basic ARIA ECB test vectors from RFC 5794 */ static const uint8_t aria_test1_ecb_key[32] = // test key { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit }; static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes }; static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext { { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit 0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 }, { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit 0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 }, { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit 0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC } }; /* * Mode tests from "Test Vectors for ARIA" Version 1.0 * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf */ #if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ defined(MBEDTLS_CIPHER_MODE_CTR)) static const uint8_t aria_test2_key[32] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit }; static const uint8_t aria_test2_pt[48] = { 0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all 0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb, 0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc, 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, 0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb, }; #endif #if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)) static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] = { 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV }; #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext { { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key 0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34, 0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64, 0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38, 0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c, 0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 }, { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key 0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f, 0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1, 0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5, 0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92, 0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e }, { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key 0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab, 0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef, 0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52, 0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5, 0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b } }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext { { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key 0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00, 0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a, 0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01, 0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96, 0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b }, { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key 0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c, 0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94, 0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59, 0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86, 0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b }, { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key 0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35, 0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70, 0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa, 0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c, 0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 } }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext { { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key 0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1, 0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1, 0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f, 0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71, 0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 }, { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key 0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce, 0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde, 0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79, 0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce, 0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf }, { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key 0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2, 0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89, 0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f, 0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7, 0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 } }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #define ARIA_SELF_TEST_ASSERT(cond) \ do { \ if (cond) { \ if (verbose) \ mbedtls_printf("failed\n"); \ goto exit; \ } else { \ if (verbose) \ mbedtls_printf("passed\n"); \ } \ } while (0) /* * Checkup routine */ int mbedtls_aria_self_test(int verbose) { int i; uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE]; mbedtls_aria_context ctx; int ret = 1; #if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR)) size_t j; #endif #if (defined(MBEDTLS_CIPHER_MODE_CBC) || \ defined(MBEDTLS_CIPHER_MODE_CFB) || \ defined(MBEDTLS_CIPHER_MODE_CTR)) uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE]; #endif mbedtls_aria_init(&ctx); /* * Test set 1 */ for (i = 0; i < 3; i++) { /* test ECB encryption */ if (verbose) { mbedtls_printf(" ARIA-ECB-%d (enc): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test1_ecb_key, 128 + 64 * i); mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_pt, blk); ARIA_SELF_TEST_ASSERT( memcmp(blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE) != 0); /* test ECB decryption */ if (verbose) { mbedtls_printf(" ARIA-ECB-%d (dec): ", 128 + 64 * i); #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) mbedtls_printf("skipped\n"); #endif } #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) mbedtls_aria_setkey_dec(&ctx, aria_test1_ecb_key, 128 + 64 * i); mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_ct[i], blk); ARIA_SELF_TEST_ASSERT( memcmp(blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE) != 0); #endif } if (verbose) { mbedtls_printf("\n"); } /* * Test set 2 */ #if defined(MBEDTLS_CIPHER_MODE_CBC) for (i = 0; i < 3; i++) { /* Test CBC encryption */ if (verbose) { mbedtls_printf(" ARIA-CBC-%d (enc): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE); memset(buf, 0x55, sizeof(buf)); mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv, aria_test2_pt, buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cbc_ct[i], 48) != 0); /* Test CBC decryption */ if (verbose) { mbedtls_printf(" ARIA-CBC-%d (dec): ", 128 + 64 * i); } mbedtls_aria_setkey_dec(&ctx, aria_test2_key, 128 + 64 * i); memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE); memset(buf, 0xAA, sizeof(buf)); mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_DECRYPT, 48, iv, aria_test2_cbc_ct[i], buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0); } if (verbose) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) for (i = 0; i < 3; i++) { /* Test CFB encryption */ if (verbose) { mbedtls_printf(" ARIA-CFB-%d (enc): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE); memset(buf, 0x55, sizeof(buf)); j = 0; mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv, aria_test2_pt, buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cfb_ct[i], 48) != 0); /* Test CFB decryption */ if (verbose) { mbedtls_printf(" ARIA-CFB-%d (dec): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE); memset(buf, 0xAA, sizeof(buf)); j = 0; mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, iv, aria_test2_cfb_ct[i], buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0); } if (verbose) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) for (i = 0; i < 3; i++) { /* Test CTR encryption */ if (verbose) { mbedtls_printf(" ARIA-CTR-%d (enc): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE); // IV = 0 memset(buf, 0x55, sizeof(buf)); j = 0; mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk, aria_test2_pt, buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_ctr_ct[i], 48) != 0); /* Test CTR decryption */ if (verbose) { mbedtls_printf(" ARIA-CTR-%d (dec): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE); // IV = 0 memset(buf, 0xAA, sizeof(buf)); j = 0; mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk, aria_test2_ctr_ct[i], buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0); } if (verbose) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ ret = 0; exit: mbedtls_aria_free(&ctx); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_ARIA_C */ webfakes/src/mbedtls/library/psa_crypto_storage.c0000644000176200001440000003752214740737024022022 0ustar liggesusers/* * PSA persistent key storage */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) #include #include #include "psa/crypto.h" #include "psa_crypto_storage.h" #include "mbedtls/platform_util.h" #if defined(MBEDTLS_PSA_ITS_FILE_C) #include "psa_crypto_its.h" #else /* Native ITS implementation */ #include "psa/error.h" #include "psa/internal_trusted_storage.h" #endif #include "mbedtls/platform.h" /****************************************************************/ /* Key storage */ /****************************************************************/ /* Determine a file name (ITS file identifier) for the given key identifier. * The file name must be distinct from any file that is used for a purpose * other than storing a key. Currently, the only such file is the random seed * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is * 0xFFFFFF52. */ static psa_storage_uid_t psa_its_identifier_of_slot(mbedtls_svc_key_id_t key) { #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) /* Encode the owner in the upper 32 bits. This means that if * owner values are nonzero (as they are on a PSA platform), * no key file will ever have a value less than 0x100000000, so * the whole range 0..0xffffffff is available for non-key files. */ uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key); return ((uint64_t) unsigned_owner_id << 32) | MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); #else /* Use the key id directly as a file name. * psa_is_key_id_valid() in psa_crypto_slot_management.c * is responsible for ensuring that key identifiers do not have a * value that is reserved for non-key files. */ return key; #endif } /** * \brief Load persistent data for the given key slot number. * * This function reads data from a storage backend and returns the data in a * buffer. * * \param key Persistent identifier of the key to be loaded. This * should be an occupied storage location. * \param[out] data Buffer where the data is to be written. * \param data_size Size of the \c data buffer in bytes. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription */ static psa_status_t psa_crypto_storage_load( const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size) { psa_status_t status; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; size_t data_length = 0; status = psa_its_get_info(data_identifier, &data_identifier_info); if (status != PSA_SUCCESS) { return status; } status = psa_its_get(data_identifier, 0, (uint32_t) data_size, data, &data_length); if (data_size != data_length) { return PSA_ERROR_DATA_INVALID; } return status; } int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key) { psa_status_t ret; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; ret = psa_its_get_info(data_identifier, &data_identifier_info); if (ret == PSA_ERROR_DOES_NOT_EXIST) { return 0; } return 1; } /** * \brief Store persistent data for the given key slot number. * * This function stores the given data buffer to a persistent storage. * * \param key Persistent identifier of the key to be stored. This * should be an unoccupied storage location. * \param[in] data Buffer containing the data to be stored. * \param data_length The number of bytes * that make up the data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ static psa_status_t psa_crypto_storage_store(const mbedtls_svc_key_id_t key, const uint8_t *data, size_t data_length) { psa_status_t status; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; if (psa_is_key_present_in_storage(key) == 1) { return PSA_ERROR_ALREADY_EXISTS; } status = psa_its_set(data_identifier, (uint32_t) data_length, data, 0); if (status != PSA_SUCCESS) { return PSA_ERROR_DATA_INVALID; } status = psa_its_get_info(data_identifier, &data_identifier_info); if (status != PSA_SUCCESS) { goto exit; } if (data_identifier_info.size != data_length) { status = PSA_ERROR_DATA_INVALID; goto exit; } exit: if (status != PSA_SUCCESS) { /* Remove the file in case we managed to create it but something * went wrong. It's ok if the file doesn't exist. If the file exists * but the removal fails, we're already reporting an error so there's * nothing else we can do. */ (void) psa_its_remove(data_identifier); } return status; } psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key) { psa_status_t ret; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; ret = psa_its_get_info(data_identifier, &data_identifier_info); if (ret == PSA_ERROR_DOES_NOT_EXIST) { return PSA_SUCCESS; } if (psa_its_remove(data_identifier) != PSA_SUCCESS) { return PSA_ERROR_DATA_INVALID; } ret = psa_its_get_info(data_identifier, &data_identifier_info); if (ret != PSA_ERROR_DOES_NOT_EXIST) { return PSA_ERROR_DATA_INVALID; } return PSA_SUCCESS; } /** * \brief Get data length for given key slot number. * * \param key Persistent identifier whose stored data length * is to be obtained. * \param[out] data_length The number of bytes that make up the data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ static psa_status_t psa_crypto_storage_get_data_length( const mbedtls_svc_key_id_t key, size_t *data_length) { psa_status_t status; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; status = psa_its_get_info(data_identifier, &data_identifier_info); if (status != PSA_SUCCESS) { return status; } *data_length = (size_t) data_identifier_info.size; return PSA_SUCCESS; } /** * Persistent key storage magic header. */ #define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY" #define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH (sizeof(PSA_KEY_STORAGE_MAGIC_HEADER)) typedef struct { uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; uint8_t version[4]; uint8_t lifetime[sizeof(psa_key_lifetime_t)]; uint8_t type[2]; uint8_t bits[2]; uint8_t policy[sizeof(psa_key_policy_t)]; uint8_t data_len[4]; uint8_t key_data[]; } psa_persistent_key_storage_format; void psa_format_key_data_for_storage(const uint8_t *data, const size_t data_length, const psa_key_attributes_t *attr, uint8_t *storage_data) { psa_persistent_key_storage_format *storage_format = (psa_persistent_key_storage_format *) storage_data; memcpy(storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH); MBEDTLS_PUT_UINT32_LE(0, storage_format->version, 0); MBEDTLS_PUT_UINT32_LE(attr->lifetime, storage_format->lifetime, 0); MBEDTLS_PUT_UINT16_LE((uint16_t) attr->type, storage_format->type, 0); MBEDTLS_PUT_UINT16_LE((uint16_t) attr->bits, storage_format->bits, 0); MBEDTLS_PUT_UINT32_LE(attr->policy.usage, storage_format->policy, 0); MBEDTLS_PUT_UINT32_LE(attr->policy.alg, storage_format->policy, sizeof(uint32_t)); MBEDTLS_PUT_UINT32_LE(attr->policy.alg2, storage_format->policy, 2 * sizeof(uint32_t)); MBEDTLS_PUT_UINT32_LE(data_length, storage_format->data_len, 0); memcpy(storage_format->key_data, data, data_length); } static psa_status_t check_magic_header(const uint8_t *data) { if (memcmp(data, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH) != 0) { return PSA_ERROR_DATA_INVALID; } return PSA_SUCCESS; } psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data, size_t storage_data_length, uint8_t **key_data, size_t *key_data_length, psa_key_attributes_t *attr) { psa_status_t status; const psa_persistent_key_storage_format *storage_format = (const psa_persistent_key_storage_format *) storage_data; uint32_t version; if (storage_data_length < sizeof(*storage_format)) { return PSA_ERROR_DATA_INVALID; } status = check_magic_header(storage_data); if (status != PSA_SUCCESS) { return status; } version = MBEDTLS_GET_UINT32_LE(storage_format->version, 0); if (version != 0) { return PSA_ERROR_DATA_INVALID; } *key_data_length = MBEDTLS_GET_UINT32_LE(storage_format->data_len, 0); if (*key_data_length > (storage_data_length - sizeof(*storage_format)) || *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) { return PSA_ERROR_DATA_INVALID; } if (*key_data_length == 0) { *key_data = NULL; } else { *key_data = mbedtls_calloc(1, *key_data_length); if (*key_data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(*key_data, storage_format->key_data, *key_data_length); } attr->lifetime = MBEDTLS_GET_UINT32_LE(storage_format->lifetime, 0); attr->type = MBEDTLS_GET_UINT16_LE(storage_format->type, 0); attr->bits = MBEDTLS_GET_UINT16_LE(storage_format->bits, 0); attr->policy.usage = MBEDTLS_GET_UINT32_LE(storage_format->policy, 0); attr->policy.alg = MBEDTLS_GET_UINT32_LE(storage_format->policy, sizeof(uint32_t)); attr->policy.alg2 = MBEDTLS_GET_UINT32_LE(storage_format->policy, 2 * sizeof(uint32_t)); return PSA_SUCCESS; } psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr, const uint8_t *data, const size_t data_length) { size_t storage_data_length; uint8_t *storage_data; psa_status_t status; /* All keys saved to persistent storage always have a key context */ if (data == NULL || data_length == 0) { return PSA_ERROR_INVALID_ARGUMENT; } if (data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) { return PSA_ERROR_INSUFFICIENT_STORAGE; } storage_data_length = data_length + sizeof(psa_persistent_key_storage_format); storage_data = mbedtls_calloc(1, storage_data_length); if (storage_data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } psa_format_key_data_for_storage(data, data_length, attr, storage_data); status = psa_crypto_storage_store(attr->id, storage_data, storage_data_length); mbedtls_zeroize_and_free(storage_data, storage_data_length); return status; } void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length) { mbedtls_zeroize_and_free(key_data, key_data_length); } psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr, uint8_t **data, size_t *data_length) { psa_status_t status = PSA_SUCCESS; uint8_t *loaded_data; size_t storage_data_length = 0; mbedtls_svc_key_id_t key = attr->id; status = psa_crypto_storage_get_data_length(key, &storage_data_length); if (status != PSA_SUCCESS) { return status; } loaded_data = mbedtls_calloc(1, storage_data_length); if (loaded_data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } status = psa_crypto_storage_load(key, loaded_data, storage_data_length); if (status != PSA_SUCCESS) { goto exit; } status = psa_parse_key_data_from_storage(loaded_data, storage_data_length, data, data_length, attr); /* All keys saved to persistent storage always have a key context */ if (status == PSA_SUCCESS && (*data == NULL || *data_length == 0)) { status = PSA_ERROR_STORAGE_FAILURE; } exit: mbedtls_zeroize_and_free(loaded_data, storage_data_length); return status; } /****************************************************************/ /* Transactions */ /****************************************************************/ #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) psa_crypto_transaction_t psa_crypto_transaction; psa_status_t psa_crypto_save_transaction(void) { struct psa_storage_info_t p_info; psa_status_t status; status = psa_its_get_info(PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info); if (status == PSA_SUCCESS) { /* This shouldn't happen: we're trying to start a transaction while * there is still a transaction that hasn't been replayed. */ return PSA_ERROR_CORRUPTION_DETECTED; } else if (status != PSA_ERROR_DOES_NOT_EXIST) { return status; } return psa_its_set(PSA_CRYPTO_ITS_TRANSACTION_UID, sizeof(psa_crypto_transaction), &psa_crypto_transaction, 0); } psa_status_t psa_crypto_load_transaction(void) { psa_status_t status; size_t length; status = psa_its_get(PSA_CRYPTO_ITS_TRANSACTION_UID, 0, sizeof(psa_crypto_transaction), &psa_crypto_transaction, &length); if (status != PSA_SUCCESS) { return status; } if (length != sizeof(psa_crypto_transaction)) { return PSA_ERROR_DATA_INVALID; } return PSA_SUCCESS; } psa_status_t psa_crypto_stop_transaction(void) { psa_status_t status = psa_its_remove(PSA_CRYPTO_ITS_TRANSACTION_UID); /* Whether or not updating the storage succeeded, the transaction is * finished now. It's too late to go back, so zero out the in-memory * data. */ memset(&psa_crypto_transaction, 0, sizeof(psa_crypto_transaction)); return status; } #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ /****************************************************************/ /* Random generator state */ /****************************************************************/ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed, size_t seed_size) { psa_status_t status; struct psa_storage_info_t p_info; status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info); if (PSA_ERROR_DOES_NOT_EXIST == status) { /* No seed exists */ status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0); } else if (PSA_SUCCESS == status) { /* You should not be here. Seed needs to be injected only once */ status = PSA_ERROR_NOT_PERMITTED; } return status; } #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ /****************************************************************/ /* The end */ /****************************************************************/ #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ webfakes/src/mbedtls/library/psa_crypto_hash.h0000644000176200001440000002163414740737024021303 0ustar liggesusers/* * PSA hashing layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_HASH_H #define PSA_CRYPTO_HASH_H #include /** Calculate the hash (digest) of a message using Mbed TLS routines. * * \note The signature of this function is that of a PSA driver hash_compute * entry point. This function behaves as a hash_compute entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * \param[in] input Buffer containing the message to hash. * \param input_length Size of the \p input buffer in bytes. * \param[out] hash Buffer where the hash is to be written. * \param hash_size Size of the \p hash buffer in bytes. * \param[out] hash_length On success, the number of bytes * that make up the hash value. This is always * #PSA_HASH_LENGTH(\p alg). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p hash_size is too small * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length); /** Set up a multipart hash operation using Mbed TLS routines. * * \note The signature of this function is that of a PSA driver hash_setup * entry point. This function behaves as a hash_setup entry point as * defined in the PSA driver interface specification for transparent * drivers. * * If an error occurs at any step after a call to mbedtls_psa_hash_setup(), the * operation will need to be reset by a call to mbedtls_psa_hash_abort(). The * core may call mbedtls_psa_hash_abort() at any time after the operation * has been initialized. * * After a successful call to mbedtls_psa_hash_setup(), the core must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to mbedtls_psa_hash_finish() or mbedtls_psa_hash_verify(). * - A call to mbedtls_psa_hash_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized to all-zero and not yet be in use. * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_setup( mbedtls_psa_hash_operation_t *operation, psa_algorithm_t alg); /** Clone an Mbed TLS hash operation. * * \note The signature of this function is that of a PSA driver hash_clone * entry point. This function behaves as a hash_clone entry point as * defined in the PSA driver interface specification for transparent * drivers. * * This function copies the state of an ongoing hash operation to * a new operation object. In other words, this function is equivalent * to calling mbedtls_psa_hash_setup() on \p target_operation with the same * algorithm that \p source_operation was set up for, then * mbedtls_psa_hash_update() on \p target_operation with the same input that * that was passed to \p source_operation. After this function returns, the * two objects are independent, i.e. subsequent calls involving one of * the objects do not affect the other object. * * \param[in] source_operation The active hash operation to clone. * \param[in,out] target_operation The operation object to set up. * It must be initialized but not active. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BAD_STATE * The \p source_operation state is not valid (it must be active). * \retval #PSA_ERROR_BAD_STATE * The \p target_operation state is not valid (it must be inactive). * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_hash_clone( const mbedtls_psa_hash_operation_t *source_operation, mbedtls_psa_hash_operation_t *target_operation); /** Add a message fragment to a multipart Mbed TLS hash operation. * * \note The signature of this function is that of a PSA driver hash_update * entry point. This function behaves as a hash_update entry point as * defined in the PSA driver interface specification for transparent * drivers. * * The application must call mbedtls_psa_hash_setup() before calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling mbedtls_psa_hash_abort(). * * \param[in,out] operation Active hash operation. * \param[in] input Buffer containing the message fragment to hash. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_update( mbedtls_psa_hash_operation_t *operation, const uint8_t *input, size_t input_length); /** Finish the calculation of the Mbed TLS-calculated hash of a message. * * \note The signature of this function is that of a PSA driver hash_finish * entry point. This function behaves as a hash_finish entry point as * defined in the PSA driver interface specification for transparent * drivers. * * The application must call mbedtls_psa_hash_setup() before calling this function. * This function calculates the hash of the message formed by concatenating * the inputs passed to preceding calls to mbedtls_psa_hash_update(). * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling mbedtls_psa_hash_abort(). * * \param[in,out] operation Active hash operation. * \param[out] hash Buffer where the hash is to be written. * \param hash_size Size of the \p hash buffer in bytes. * \param[out] hash_length On success, the number of bytes * that make up the hash value. This is always * #PSA_HASH_LENGTH(\c alg) where \c alg is the * hash algorithm that is calculated. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p hash buffer is too small. You can determine a * sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg) * where \c alg is the hash algorithm that is calculated. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_finish( mbedtls_psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length); /** Abort an Mbed TLS hash operation. * * \note The signature of this function is that of a PSA driver hash_abort * entry point. This function behaves as a hash_abort entry point as * defined in the PSA driver interface specification for transparent * drivers. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * mbedtls_psa_hash_setup() again. * * You may call this function any time after the operation object has * been initialized by one of the methods described in #psa_hash_operation_t. * * In particular, calling mbedtls_psa_hash_abort() after the operation has been * terminated by a call to mbedtls_psa_hash_abort(), mbedtls_psa_hash_finish() or * mbedtls_psa_hash_verify() is safe and has no effect. * * \param[in,out] operation Initialized hash operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_abort( mbedtls_psa_hash_operation_t *operation); #endif /* PSA_CRYPTO_HASH_H */ webfakes/src/mbedtls/library/mps_trace.c0000644000176200001440000000433614740737024020065 0ustar liggesusers/* * Message Processing Stack, Trace module * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "mps_common.h" #if defined(MBEDTLS_MPS_ENABLE_TRACE) #include "mps_trace.h" #include static int trace_depth = 0; #define color_default "\x1B[0m" #define color_red "\x1B[1;31m" #define color_green "\x1B[1;32m" #define color_yellow "\x1B[1;33m" #define color_blue "\x1B[1;34m" #define color_magenta "\x1B[1;35m" #define color_cyan "\x1B[1;36m" #define color_white "\x1B[1;37m" static char const *colors[] = { color_default, color_green, color_yellow, color_magenta, color_cyan, color_blue, color_white }; #define MPS_TRACE_BUF_SIZE 100 void mbedtls_mps_trace_print_msg(int id, int line, const char *format, ...) { int ret; char str[MPS_TRACE_BUF_SIZE]; va_list argp; va_start(argp, format); ret = mbedtls_vsnprintf(str, MPS_TRACE_BUF_SIZE, format, argp); va_end(argp); if (ret >= 0 && ret < MPS_TRACE_BUF_SIZE) { str[ret] = '\0'; mbedtls_printf("[%d|L%d]: %s\n", id, line, str); } } int mbedtls_mps_trace_get_depth() { return trace_depth; } void mbedtls_mps_trace_dec_depth() { trace_depth--; } void mbedtls_mps_trace_inc_depth() { trace_depth++; } void mbedtls_mps_trace_color(int id) { if (id > (int) (sizeof(colors) / sizeof(*colors))) { return; } printf("%s", colors[id]); } void mbedtls_mps_trace_indent(int level, mbedtls_mps_trace_type ty) { if (level > 0) { while (--level) { printf("| "); } printf("| "); } switch (ty) { case MBEDTLS_MPS_TRACE_TYPE_COMMENT: mbedtls_printf("@ "); break; case MBEDTLS_MPS_TRACE_TYPE_CALL: mbedtls_printf("+--> "); break; case MBEDTLS_MPS_TRACE_TYPE_ERROR: mbedtls_printf("E "); break; case MBEDTLS_MPS_TRACE_TYPE_RETURN: mbedtls_printf("< "); break; default: break; } } #endif /* MBEDTLS_MPS_ENABLE_TRACE */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ webfakes/src/mbedtls/library/pk_wrap.c0000644000176200001440000014664114740737024017561 0ustar liggesusers/* * Public Key abstraction layer: wrapper functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "mbedtls/platform_util.h" #if defined(MBEDTLS_PK_C) #include "pk_wrap.h" #include "pk_internal.h" #include "mbedtls/error.h" #include "mbedtls/psa_util.h" /* Even if RSA not activated, for the sake of RSA-alt */ #include "mbedtls/rsa.h" #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa_util_internal.h" #include "psa/crypto.h" #include "mbedtls/psa_util.h" #if defined(MBEDTLS_RSA_C) #include "pkwrite.h" #include "rsa_internal.h" #endif #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) #include "mbedtls/asn1write.h" #include "mbedtls/asn1.h" #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ #include "mbedtls/platform.h" #include #include #include #if defined(MBEDTLS_RSA_C) static int rsa_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_RSA || type == MBEDTLS_PK_RSASSA_PSS; } static size_t rsa_get_bitlen(mbedtls_pk_context *pk) { const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) pk->pk_ctx; return mbedtls_rsa_get_bitlen(rsa); } #if defined(MBEDTLS_USE_PSA_CRYPTO) static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_status_t status; int key_len; unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; unsigned char *p = buf + sizeof(buf); psa_algorithm_t psa_alg_md; size_t rsa_len = mbedtls_rsa_get_len(rsa); #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { psa_alg_md = PSA_ALG_RSA_PSS(mbedtls_md_psa_alg_from_type(md_alg)); } else { psa_alg_md = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg)); } if (sig_len < rsa_len) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p); if (key_len <= 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_algorithm(&attributes, psa_alg_md); psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); status = psa_import_key(&attributes, buf + sizeof(buf) - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len, sig, sig_len); if (status != PSA_SUCCESS) { ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; size_t rsa_len = mbedtls_rsa_get_len(rsa); #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif if (sig_len < rsa_len) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } if ((ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg, (unsigned int) hash_len, hash, sig)) != 0) { return ret; } /* The buffer contains a valid signature followed by extra data. * We have a special error code for that so that so that callers can * use mbedtls_pk_verify() to check "Does the buffer start with a * valid signature?" and not just "Does the buffer contain a valid * signature?". */ if (sig_len > rsa_len) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg, mbedtls_rsa_context *rsa_ctx, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_status_t status; int key_len; unsigned char *buf = NULL; unsigned char *p; buf = mbedtls_calloc(1, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES); if (buf == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } p = buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES; *sig_len = mbedtls_rsa_get_len(rsa_ctx); if (sig_size < *sig_len) { mbedtls_free(buf); return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } key_len = mbedtls_rsa_write_key(rsa_ctx, buf, &p); if (key_len <= 0) { mbedtls_free(buf); return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); status = psa_import_key(&attributes, buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } status = psa_sign_hash(key_id, alg, hash, hash_len, sig, sig_size, sig_len); if (status != PSA_SUCCESS) { ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: mbedtls_free(buf); status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { ((void) f_rng); ((void) p_rng); psa_algorithm_t psa_md_alg; psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); if (psa_md_alg == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_algorithm_t psa_alg; if (mbedtls_rsa_get_padding_mode(mbedtls_pk_rsa(*pk)) == MBEDTLS_RSA_PKCS_V21) { psa_alg = PSA_ALG_RSA_PSS(psa_md_alg); } else { psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg); } return mbedtls_pk_psa_rsa_sign_ext(psa_alg, pk->pk_ctx, hash, hash_len, sig, sig_size, sig_len); } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif *sig_len = mbedtls_rsa_get_len(rsa); if (sig_size < *sig_len) { return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng, md_alg, (unsigned int) hash_len, hash, sig); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static int rsa_decrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_algorithm_t psa_md_alg, decrypt_alg; psa_status_t status; int key_len; unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; unsigned char *p = buf + sizeof(buf); ((void) f_rng); ((void) p_rng); if (ilen != mbedtls_rsa_get_len(rsa)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } key_len = mbedtls_rsa_write_key(rsa, buf, &p); if (key_len <= 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa)); decrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg); } else { decrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT; } psa_set_key_algorithm(&attributes, decrypt_alg); status = psa_import_key(&attributes, buf + sizeof(buf) - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } status = psa_asymmetric_decrypt(key_id, decrypt_alg, input, ilen, NULL, 0, output, osize, olen); if (status != PSA_SUCCESS) { ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_decrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; if (ilen != mbedtls_rsa_get_len(rsa)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng, olen, input, output, osize); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static int rsa_encrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_algorithm_t psa_md_alg, psa_encrypt_alg; psa_status_t status; int key_len; unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; unsigned char *p = buf + sizeof(buf); ((void) f_rng); ((void) p_rng); if (mbedtls_rsa_get_len(rsa) > osize) { return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; } key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p); if (key_len <= 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa)); psa_encrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg); } else { psa_encrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT; } psa_set_key_algorithm(&attributes, psa_encrypt_alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); status = psa_import_key(&attributes, buf + sizeof(buf) - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } status = psa_asymmetric_encrypt(key_id, psa_encrypt_alg, input, ilen, NULL, 0, output, osize, olen); if (status != PSA_SUCCESS) { ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_encrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; *olen = mbedtls_rsa_get_len(rsa); if (*olen > osize) { return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; } return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng, ilen, input, output); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { (void) f_rng; (void) p_rng; return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub->pk_ctx, (const mbedtls_rsa_context *) prv->pk_ctx); } static void *rsa_alloc_wrap(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); if (ctx != NULL) { mbedtls_rsa_init((mbedtls_rsa_context *) ctx); } return ctx; } static void rsa_free_wrap(void *ctx) { mbedtls_rsa_free((mbedtls_rsa_context *) ctx); mbedtls_free(ctx); } static void rsa_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) { #if defined(MBEDTLS_RSA_ALT) /* Not supported */ (void) pk; (void) items; #else mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; items->type = MBEDTLS_PK_DEBUG_MPI; items->name = "rsa.N"; items->value = &(rsa->N); items++; items->type = MBEDTLS_PK_DEBUG_MPI; items->name = "rsa.E"; items->value = &(rsa->E); #endif } const mbedtls_pk_info_t mbedtls_rsa_info = { .type = MBEDTLS_PK_RSA, .name = "RSA", .get_bitlen = rsa_get_bitlen, .can_do = rsa_can_do, .verify_func = rsa_verify_wrap, .sign_func = rsa_sign_wrap, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, .rs_alloc_func = NULL, .rs_free_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = rsa_decrypt_wrap, .encrypt_func = rsa_encrypt_wrap, .check_pair_func = rsa_check_pair_wrap, .ctx_alloc_func = rsa_alloc_wrap, .ctx_free_func = rsa_free_wrap, .debug_func = rsa_debug, }; #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * Generic EC key */ static int eckey_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECKEY_DH || type == MBEDTLS_PK_ECDSA; } static size_t eckey_get_bitlen(mbedtls_pk_context *pk) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) return pk->ec_bits; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; return ecp->grp.pbits; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Common helper for ECDSA verify using PSA functions. */ static int ecdsa_verify_psa(unsigned char *key, size_t key_len, psa_ecc_family_t curve, size_t curve_bits, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; size_t signature_len = PSA_ECDSA_SIGNATURE_SIZE(curve_bits); size_t converted_sig_len; unsigned char extracted_sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE]; unsigned char *p; psa_status_t status; if (curve == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_algorithm(&attributes, psa_sig_md); status = psa_import_key(&attributes, key, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } if (signature_len > sizeof(extracted_sig)) { ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; goto cleanup; } p = (unsigned char *) sig; ret = mbedtls_ecdsa_der_to_raw(curve_bits, p, sig_len, extracted_sig, sizeof(extracted_sig), &converted_sig_len); if (ret != 0) { goto cleanup; } if (converted_sig_len != signature_len) { ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; goto cleanup; } status = psa_verify_hash(key_id, psa_sig_md, hash, hash_len, extracted_sig, signature_len); if (status != PSA_SUCCESS) { ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } static int ecdsa_opaque_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { (void) md_alg; unsigned char key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; size_t key_len; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_ecc_family_t curve; size_t curve_bits; psa_status_t status; status = psa_get_key_attributes(pk->priv_id, &key_attr); if (status != PSA_SUCCESS) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } curve = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attr)); curve_bits = psa_get_key_bits(&key_attr); psa_reset_key_attributes(&key_attr); status = psa_export_public_key(pk->priv_id, key, sizeof(key), &key_len); if (status != PSA_SUCCESS) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } return ecdsa_verify_psa(key, key_len, curve, curve_bits, hash, hash_len, sig, sig_len); } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { (void) md_alg; psa_ecc_family_t curve = pk->ec_family; size_t curve_bits = pk->ec_bits; return ecdsa_verify_psa(pk->pub_raw, pk->pub_raw_len, curve, curve_bits, hash, hash_len, sig, sig_len); } #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { (void) md_alg; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ctx = pk->pk_ctx; unsigned char key[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t key_len; size_t curve_bits; psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &key_len, key, sizeof(key)); if (ret != 0) { return ret; } return ecdsa_verify_psa(key, key_len, curve, curve_bits, hash, hash_len, sig, sig_len); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #else /* MBEDTLS_USE_PSA_CRYPTO */ static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ((void) md_alg); ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) pk->pk_ctx, hash, hash_len, sig, sig_len); if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Common helper for ECDSA sign using PSA functions. * Instead of extracting key's properties in order to check which kind of ECDSA * signature it supports, we try both deterministic and non-deterministic. */ static int ecdsa_sign_psa(mbedtls_svc_key_id_t key_id, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; size_t key_bits = 0; status = psa_get_key_attributes(key_id, &key_attr); if (status != PSA_SUCCESS) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } key_bits = psa_get_key_bits(&key_attr); psa_reset_key_attributes(&key_attr); status = psa_sign_hash(key_id, PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)), hash, hash_len, sig, sig_size, sig_len); if (status == PSA_SUCCESS) { goto done; } else if (status != PSA_ERROR_NOT_PERMITTED) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } status = psa_sign_hash(key_id, PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)), hash, hash_len, sig, sig_size, sig_len); if (status != PSA_SUCCESS) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } done: ret = mbedtls_ecdsa_raw_to_der(key_bits, sig, *sig_len, sig, sig_size, sig_len); return ret; } static int ecdsa_opaque_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { ((void) f_rng); ((void) p_rng); return ecdsa_sign_psa(pk->priv_id, md_alg, hash, hash_len, sig, sig_size, sig_len); } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up * using the same function. */ #define ecdsa_sign_wrap ecdsa_opaque_sign_wrap #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_status_t status; mbedtls_ecp_keypair *ctx = pk->pk_ctx; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; size_t curve_bits; psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); size_t key_len = PSA_BITS_TO_BYTES(curve_bits); psa_algorithm_t psa_hash = mbedtls_md_psa_alg_from_type(md_alg); psa_algorithm_t psa_sig_md = MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(psa_hash); ((void) f_rng); ((void) p_rng); if (curve == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (key_len > sizeof(buf)) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len); if (ret != 0) { goto cleanup; } psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); psa_set_key_algorithm(&attributes, psa_sig_md); status = psa_import_key(&attributes, buf, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } ret = ecdsa_sign_psa(key_id, md_alg, hash, hash_len, sig, sig_size, sig_len); cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #else /* MBEDTLS_USE_PSA_CRYPTO */ static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) pk->pk_ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* Forward declarations */ static int ecdsa_verify_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx); static int ecdsa_sign_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx); /* * Restart context for ECDSA operations with ECKEY context * * We need to store an actual ECDSA context, as we need to pass the same to * the underlying ecdsa function, so we can't create it on the fly every time. */ typedef struct { mbedtls_ecdsa_restart_ctx ecdsa_rs; mbedtls_ecdsa_context ecdsa_ctx; } eckey_restart_ctx; static void *eckey_rs_alloc(void) { eckey_restart_ctx *rs_ctx; void *ctx = mbedtls_calloc(1, sizeof(eckey_restart_ctx)); if (ctx != NULL) { rs_ctx = ctx; mbedtls_ecdsa_restart_init(&rs_ctx->ecdsa_rs); mbedtls_ecdsa_init(&rs_ctx->ecdsa_ctx); } return ctx; } static void eckey_rs_free(void *ctx) { eckey_restart_ctx *rs_ctx; if (ctx == NULL) { return; } rs_ctx = ctx; mbedtls_ecdsa_restart_free(&rs_ctx->ecdsa_rs); mbedtls_ecdsa_free(&rs_ctx->ecdsa_ctx); mbedtls_free(ctx); } static int eckey_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; eckey_restart_ctx *rs = rs_ctx; /* Should never happen */ if (rs == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } /* set up our own sub-context if needed (that is, on first run) */ if (rs->ecdsa_ctx.grp.pbits == 0) { MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); } MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(pk, md_alg, hash, hash_len, sig, sig_len, &rs->ecdsa_rs)); cleanup: return ret; } static int eckey_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; eckey_restart_ctx *rs = rs_ctx; /* Should never happen */ if (rs == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } /* set up our own sub-context if needed (that is, on first run) */ if (rs->ecdsa_ctx.grp.pbits == 0) { MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); } MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(pk, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, &rs->ecdsa_rs)); cleanup: return ret; } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t prv_key_len; mbedtls_svc_key_id_t key_id = prv->priv_id; status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), &prv_key_len); ret = PSA_PK_TO_MBEDTLS_ERR(status); if (ret != 0) { return ret; } if (memcmp(prv_key_buf, pub->pub_raw, pub->pub_raw_len) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return 0; } #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t prv_key_len; psa_status_t destruction_status; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; uint8_t pub_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t pub_key_len; size_t curve_bits; const psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(mbedtls_pk_ec_ro(*prv)->grp.id, &curve_bits); const size_t curve_bytes = PSA_BITS_TO_BYTES(curve_bits); if (curve == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); ret = mbedtls_mpi_write_binary(&mbedtls_pk_ec_ro(*prv)->d, prv_key_buf, curve_bytes); if (ret != 0) { mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); return ret; } status = psa_import_key(&key_attr, prv_key_buf, curve_bytes, &key_id); mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); ret = PSA_PK_TO_MBEDTLS_ERR(status); if (ret != 0) { return ret; } // From now on prv_key_buf is used to store the public key of prv. status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), &prv_key_len); ret = PSA_PK_TO_MBEDTLS_ERR(status); destruction_status = psa_destroy_key(key_id); if (ret != 0) { return ret; } else if (destruction_status != PSA_SUCCESS) { return PSA_PK_TO_MBEDTLS_ERR(destruction_status); } ret = mbedtls_ecp_point_write_binary(&mbedtls_pk_ec_rw(*pub)->grp, &mbedtls_pk_ec_rw(*pub)->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &pub_key_len, pub_key_buf, sizeof(pub_key_buf)); if (ret != 0) { return ret; } if (memcmp(prv_key_buf, pub_key_buf, curve_bytes) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return 0; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { (void) f_rng; (void) p_rng; return eckey_check_pair_psa(pub, prv); } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub->pk_ctx, (const mbedtls_ecp_keypair *) prv->pk_ctx, f_rng, p_rng); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up * using the same function. */ #define ecdsa_opaque_check_pair_wrap eckey_check_pair_wrap #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int ecdsa_opaque_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { psa_status_t status; uint8_t exp_pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; size_t exp_pub_key_len = 0; uint8_t pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; size_t pub_key_len = 0; int ret; (void) f_rng; (void) p_rng; status = psa_export_public_key(prv->priv_id, exp_pub_key, sizeof(exp_pub_key), &exp_pub_key_len); if (status != PSA_SUCCESS) { ret = psa_pk_status_to_mbedtls(status); return ret; } ret = mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec_ro(*pub)->grp), &(mbedtls_pk_ec_ro(*pub)->Q), MBEDTLS_ECP_PF_UNCOMPRESSED, &pub_key_len, pub_key, sizeof(pub_key)); if (ret != 0) { return ret; } if ((exp_pub_key_len != pub_key_len) || memcmp(exp_pub_key, pub_key, exp_pub_key_len)) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return 0; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) static void *eckey_alloc_wrap(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); if (ctx != NULL) { mbedtls_ecp_keypair_init(ctx); } return ctx; } static void eckey_free_wrap(void *ctx) { mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx); mbedtls_free(ctx); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ static void eckey_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) items->type = MBEDTLS_PK_DEBUG_PSA_EC; items->name = "eckey.Q"; items->value = pk; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; items->type = MBEDTLS_PK_DEBUG_ECP; items->name = "eckey.Q"; items->value = &(ecp->Q); #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } const mbedtls_pk_info_t mbedtls_eckey_info = { .type = MBEDTLS_PK_ECKEY, .name = "EC", .get_bitlen = eckey_get_bitlen, .can_do = eckey_can_do, #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ #else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ .verify_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ #else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ .sign_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = eckey_verify_rs_wrap, .sign_rs_func = eckey_sign_rs_wrap, .rs_alloc_func = eckey_rs_alloc, .rs_free_func = eckey_rs_free, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = NULL, .encrypt_func = NULL, .check_pair_func = eckey_check_pair_wrap, #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) .ctx_alloc_func = NULL, .ctx_free_func = NULL, #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ .ctx_alloc_func = eckey_alloc_wrap, .ctx_free_func = eckey_free_wrap, #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ .debug_func = eckey_debug, }; /* * EC key restricted to ECDH */ static int eckeydh_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECKEY_DH; } const mbedtls_pk_info_t mbedtls_eckeydh_info = { .type = MBEDTLS_PK_ECKEY_DH, .name = "EC_DH", .get_bitlen = eckey_get_bitlen, /* Same underlying key structure */ .can_do = eckeydh_can_do, .verify_func = NULL, .sign_func = NULL, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = NULL, .encrypt_func = NULL, .check_pair_func = eckey_check_pair_wrap, #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) .ctx_alloc_func = NULL, .ctx_free_func = NULL, #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ .ctx_alloc_func = eckey_alloc_wrap, /* Same underlying key structure */ .ctx_free_func = eckey_free_wrap, /* Same underlying key structure */ #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ .debug_func = eckey_debug, /* Same underlying key structure */ }; #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) static int ecdsa_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_ECDSA; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) static int ecdsa_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ((void) md_alg); ret = mbedtls_ecdsa_read_signature_restartable( (mbedtls_ecdsa_context *) pk->pk_ctx, hash, hash_len, sig, sig_len, (mbedtls_ecdsa_restart_ctx *) rs_ctx); if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } return ret; } static int ecdsa_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx) { return mbedtls_ecdsa_write_signature_restartable( (mbedtls_ecdsa_context *) pk->pk_ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, (mbedtls_ecdsa_restart_ctx *) rs_ctx); } static void *ecdsa_rs_alloc(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx)); if (ctx != NULL) { mbedtls_ecdsa_restart_init(ctx); } return ctx; } static void ecdsa_rs_free(void *ctx) { mbedtls_ecdsa_restart_free(ctx); mbedtls_free(ctx); } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ const mbedtls_pk_info_t mbedtls_ecdsa_info = { .type = MBEDTLS_PK_ECDSA, .name = "ECDSA", .get_bitlen = eckey_get_bitlen, /* Compatible key structures */ .can_do = ecdsa_can_do, #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ #else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ .verify_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ #else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ .sign_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = ecdsa_verify_rs_wrap, .sign_rs_func = ecdsa_sign_rs_wrap, .rs_alloc_func = ecdsa_rs_alloc, .rs_free_func = ecdsa_rs_free, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = NULL, .encrypt_func = NULL, .check_pair_func = eckey_check_pair_wrap, /* Compatible key structures */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) .ctx_alloc_func = NULL, .ctx_free_func = NULL, #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ .ctx_alloc_func = eckey_alloc_wrap, /* Compatible key structures */ .ctx_free_func = eckey_free_wrap, /* Compatible key structures */ #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ .debug_func = eckey_debug, /* Compatible key structures */ }; #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* * Support for alternative RSA-private implementations */ static int rsa_alt_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_RSA; } static size_t rsa_alt_get_bitlen(mbedtls_pk_context *pk) { const mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; return 8 * rsa_alt->key_len_func(rsa_alt->key); } static int rsa_alt_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; #if SIZE_MAX > UINT_MAX if (UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif *sig_len = rsa_alt->key_len_func(rsa_alt->key); if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (*sig_len > sig_size) { return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng, md_alg, (unsigned int) hash_len, hash, sig); } static int rsa_alt_decrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; ((void) f_rng); ((void) p_rng); if (ilen != rsa_alt->key_len_func(rsa_alt->key)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return rsa_alt->decrypt_func(rsa_alt->key, olen, input, output, osize); } #if defined(MBEDTLS_RSA_C) static int rsa_alt_check_pair(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; unsigned char hash[32]; size_t sig_len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (rsa_alt_get_bitlen(prv) != rsa_get_bitlen(pub)) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } memset(hash, 0x2a, sizeof(hash)); if ((ret = rsa_alt_sign_wrap(prv, MBEDTLS_MD_NONE, hash, sizeof(hash), sig, sizeof(sig), &sig_len, f_rng, p_rng)) != 0) { return ret; } if (rsa_verify_wrap(pub, MBEDTLS_MD_NONE, hash, sizeof(hash), sig, sig_len) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } return 0; } #endif /* MBEDTLS_RSA_C */ static void *rsa_alt_alloc_wrap(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_alt_context)); if (ctx != NULL) { memset(ctx, 0, sizeof(mbedtls_rsa_alt_context)); } return ctx; } static void rsa_alt_free_wrap(void *ctx) { mbedtls_zeroize_and_free(ctx, sizeof(mbedtls_rsa_alt_context)); } const mbedtls_pk_info_t mbedtls_rsa_alt_info = { .type = MBEDTLS_PK_RSA_ALT, .name = "RSA-alt", .get_bitlen = rsa_alt_get_bitlen, .can_do = rsa_alt_can_do, .verify_func = NULL, .sign_func = rsa_alt_sign_wrap, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, .rs_alloc_func = NULL, .rs_free_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = rsa_alt_decrypt_wrap, .encrypt_func = NULL, #if defined(MBEDTLS_RSA_C) .check_pair_func = rsa_alt_check_pair, #else .check_pair_func = NULL, #endif .ctx_alloc_func = rsa_alt_alloc_wrap, .ctx_free_func = rsa_alt_free_wrap, .debug_func = NULL, }; #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static size_t opaque_get_bitlen(mbedtls_pk_context *pk) { size_t bits; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; if (PSA_SUCCESS != psa_get_key_attributes(pk->priv_id, &attributes)) { return 0; } bits = psa_get_key_bits(&attributes); psa_reset_key_attributes(&attributes); return bits; } #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) static int ecdsa_opaque_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECDSA; } const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info = { .type = MBEDTLS_PK_OPAQUE, .name = "Opaque", .get_bitlen = opaque_get_bitlen, .can_do = ecdsa_opaque_can_do, #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) .verify_func = ecdsa_opaque_verify_wrap, #else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ .verify_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) .sign_func = ecdsa_opaque_sign_wrap, #else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ .sign_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, .rs_alloc_func = NULL, .rs_free_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = NULL, .encrypt_func = NULL, .check_pair_func = ecdsa_opaque_check_pair_wrap, .ctx_alloc_func = NULL, .ctx_free_func = NULL, .debug_func = NULL, }; #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ static int rsa_opaque_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_RSA || type == MBEDTLS_PK_RSASSA_PSS; } #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) static int rsa_opaque_decrypt(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t alg; psa_key_type_t type; psa_status_t status; /* PSA has its own RNG */ (void) f_rng; (void) p_rng; status = psa_get_key_attributes(pk->priv_id, &attributes); if (status != PSA_SUCCESS) { return PSA_PK_TO_MBEDTLS_ERR(status); } type = psa_get_key_type(&attributes); alg = psa_get_key_algorithm(&attributes); psa_reset_key_attributes(&attributes); if (!PSA_KEY_TYPE_IS_RSA(type)) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } status = psa_asymmetric_decrypt(pk->priv_id, alg, input, ilen, NULL, 0, output, osize, olen); if (status != PSA_SUCCESS) { return PSA_PK_RSA_TO_MBEDTLS_ERR(status); } return 0; } #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ static int rsa_opaque_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_RSA_C) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t alg; psa_key_type_t type; psa_status_t status; /* PSA has its own RNG */ (void) f_rng; (void) p_rng; status = psa_get_key_attributes(pk->priv_id, &attributes); if (status != PSA_SUCCESS) { return PSA_PK_TO_MBEDTLS_ERR(status); } type = psa_get_key_type(&attributes); alg = psa_get_key_algorithm(&attributes); psa_reset_key_attributes(&attributes); if (PSA_KEY_TYPE_IS_RSA(type)) { alg = (alg & ~PSA_ALG_HASH_MASK) | mbedtls_md_psa_alg_from_type(md_alg); } else { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } status = psa_sign_hash(pk->priv_id, alg, hash, hash_len, sig, sig_size, sig_len); if (status != PSA_SUCCESS) { if (PSA_KEY_TYPE_IS_RSA(type)) { return PSA_PK_RSA_TO_MBEDTLS_ERR(status); } else { return PSA_PK_TO_MBEDTLS_ERR(status); } } return 0; #else /* !MBEDTLS_RSA_C */ ((void) pk); ((void) md_alg); ((void) hash); ((void) hash_len); ((void) sig); ((void) sig_size); ((void) sig_len); ((void) f_rng); ((void) p_rng); return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; #endif /* !MBEDTLS_RSA_C */ } const mbedtls_pk_info_t mbedtls_rsa_opaque_info = { .type = MBEDTLS_PK_OPAQUE, .name = "Opaque", .get_bitlen = opaque_get_bitlen, .can_do = rsa_opaque_can_do, .verify_func = NULL, .sign_func = rsa_opaque_sign_wrap, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, .rs_alloc_func = NULL, .rs_free_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) .decrypt_func = rsa_opaque_decrypt, #else /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ .decrypt_func = NULL, #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ .encrypt_func = NULL, .check_pair_func = NULL, .ctx_alloc_func = NULL, .ctx_free_func = NULL, .debug_func = NULL, }; #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_C */ webfakes/src/mbedtls/library/psa_crypto_ffdh.c0000644000176200001440000002512714740737024021263 0ustar liggesusers/* * PSA FFDH layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) /* This header is only needed because it defines * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module * only uses bignum functions for arithmetic. */ #include #include #include "psa_crypto_core.h" #include "psa_crypto_ffdh.h" #include "psa_crypto_random_impl.h" #include "mbedtls/platform.h" #include "mbedtls/error.h" #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size, mbedtls_mpi *P, mbedtls_mpi *G) { const unsigned char *dhm_P = NULL; const unsigned char *dhm_G = NULL; size_t dhm_size_P = 0; size_t dhm_size_G = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (P == NULL && G == NULL) { return PSA_ERROR_INVALID_ARGUMENT; } #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) static const unsigned char dhm_P_2048[] = MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN; static const unsigned char dhm_G_2048[] = MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) static const unsigned char dhm_P_3072[] = MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN; static const unsigned char dhm_G_3072[] = MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) static const unsigned char dhm_P_4096[] = MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN; static const unsigned char dhm_G_4096[] = MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) static const unsigned char dhm_P_6144[] = MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN; static const unsigned char dhm_G_6144[] = MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) static const unsigned char dhm_P_8192[] = MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN; static const unsigned char dhm_G_8192[] = MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ switch (key_size) { #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) case sizeof(dhm_P_2048): dhm_P = dhm_P_2048; dhm_G = dhm_G_2048; dhm_size_P = sizeof(dhm_P_2048); dhm_size_G = sizeof(dhm_G_2048); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) case sizeof(dhm_P_3072): dhm_P = dhm_P_3072; dhm_G = dhm_G_3072; dhm_size_P = sizeof(dhm_P_3072); dhm_size_G = sizeof(dhm_G_3072); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) case sizeof(dhm_P_4096): dhm_P = dhm_P_4096; dhm_G = dhm_G_4096; dhm_size_P = sizeof(dhm_P_4096); dhm_size_G = sizeof(dhm_G_4096); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) case sizeof(dhm_P_6144): dhm_P = dhm_P_6144; dhm_G = dhm_G_6144; dhm_size_P = sizeof(dhm_P_6144); dhm_size_G = sizeof(dhm_G_6144); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) case sizeof(dhm_P_8192): dhm_P = dhm_P_8192; dhm_G = dhm_G_8192; dhm_size_P = sizeof(dhm_P_8192); dhm_size_G = sizeof(dhm_G_8192); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ default: return PSA_ERROR_INVALID_ARGUMENT; } if (P != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P, dhm_size_P)); } if (G != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G, dhm_size_G)); } cleanup: if (ret != 0) { return mbedtls_to_psa_error(ret); } return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE || MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || MBEDTLS_PSA_BUILTIN_ALG_FFDH */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) psa_status_t mbedtls_psa_ffdh_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_mpi GX, G, X, P; psa_key_type_t type = attributes->type; if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { if (key_buffer_size > data_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(data, key_buffer, key_buffer_size); memset(data + key_buffer_size, 0, data_size - key_buffer_size); *data_length = key_buffer_size; return PSA_SUCCESS; } mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G); mbedtls_mpi_init(&X); mbedtls_mpi_init(&P); size_t key_len = PSA_BITS_TO_BYTES(attributes->bits); status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G); if (status != PSA_SUCCESS) { goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, key_buffer_size)); MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len)); *data_length = key_len; ret = 0; cleanup: mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX); if (status == PSA_SUCCESS && ret != 0) { status = mbedtls_to_psa_error(ret); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) psa_status_t mbedtls_psa_ffdh_generate_key( const psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { mbedtls_mpi X, P; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_init(&P); mbedtls_mpi_init(&X); (void) attributes; status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL); if (status != PSA_SUCCESS) { goto cleanup; } /* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their secret exponent from the range [2, P-2]. Select random value in range [3, P-1] and decrease it by 1. */ MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size)); *key_buffer_length = key_buffer_size; cleanup: mbedtls_mpi_free(&P); mbedtls_mpi_free(&X); if (status == PSA_SUCCESS && ret != 0) { return mbedtls_to_psa_error(ret); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) psa_status_t mbedtls_psa_ffdh_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits) { (void) attributes; if (key_buffer_size < data_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(key_buffer, data, data_length); *key_buffer_length = data_length; *bits = PSA_BYTES_TO_BITS(data_length); return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) psa_status_t mbedtls_psa_ffdh_key_agreement( const psa_key_attributes_t *attributes, const uint8_t *peer_key, size_t peer_key_length, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_mpi P, G, X, GY, K; const size_t calculated_shared_secret_size = peer_key_length; if (peer_key_length != key_buffer_size || calculated_shared_secret_size > shared_secret_size) { return PSA_ERROR_INVALID_ARGUMENT; } if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) { return PSA_ERROR_INVALID_ARGUMENT; } mbedtls_mpi_init(&P); mbedtls_mpi_init(&G); mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY); mbedtls_mpi_init(&K); status = mbedtls_psa_ffdh_set_prime_generator( PSA_BITS_TO_BYTES(attributes->bits), &P, &G); if (status != PSA_SUCCESS) { goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, key_buffer_size)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key, peer_key_length)); /* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret, calculated_shared_secret_size)); *shared_secret_length = calculated_shared_secret_size; ret = 0; cleanup: mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY); mbedtls_mpi_free(&K); if (status == PSA_SUCCESS && ret != 0) { status = mbedtls_to_psa_error(ret); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */ #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/ssl_tls12_client.c0000644000176200001440000040040314740737024021267 0ustar liggesusers/* * TLS client-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "ssl_client.h" #include "ssl_misc.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa_util_internal.h" #include "psa/crypto.h" #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #include #include #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) #include "mbedtls/platform_util.h" #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; *olen = 0; /* We're always including a TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the * initial ClientHello, in which case also adding the renegotiation * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding renegotiation extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + ssl->verify_data_len); /* * Secure renegotiation */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0); p += 2; *p++ = 0x00; *p++ = MBEDTLS_BYTE_0(ssl->verify_data_len + 1); *p++ = MBEDTLS_BYTE_0(ssl->verify_data_len); memcpy(p, ssl->own_verify_data, ssl->verify_data_len); *olen = 5 + ssl->verify_data_len; return 0; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; (void) ssl; /* ssl used for debugging only */ *olen = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported_point_formats extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0); p += 2; *p++ = 0x00; *p++ = 2; *p++ = 1; *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; *olen = 6; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t kkpp_len = 0; *olen = 0; /* Skip costly extension if we can't use EC J-PAKE anyway */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if (ssl->handshake->psa_pake_ctx_is_ok != 1) { return 0; } #else if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) { return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding ecjpake_kkpp extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0); p += 2; /* * We may need to send ClientHello multiple times for Hello verification. * We don't want to compute fresh values every time (both for performance * and consistency reasons), so cache the extension content. */ if (ssl->handshake->ecjpake_cache == NULL || ssl->handshake->ecjpake_cache_len == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("generating new ecjpake parameters")); #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, p + 2, end - p - 2, &kkpp_len, MBEDTLS_ECJPAKE_ROUND_ONE); if (ret != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); return ret; } #else ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx, p + 2, end - p - 2, &kkpp_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_one", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ ssl->handshake->ecjpake_cache = mbedtls_calloc(1, kkpp_len); if (ssl->handshake->ecjpake_cache == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("allocation failed")); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ssl->handshake->ecjpake_cache, p + 2, kkpp_len); ssl->handshake->ecjpake_cache_len = kkpp_len; } else { MBEDTLS_SSL_DEBUG_MSG(3, ("re-using cached ecjpake parameters")); kkpp_len = ssl->handshake->ecjpake_cache_len; MBEDTLS_SSL_CHK_BUF_PTR(p + 2, end, kkpp_len); memcpy(p + 2, ssl->handshake->ecjpake_cache, kkpp_len); } MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0); p += 2; *olen = kkpp_len + 4; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_cid_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; size_t ext_len; /* * struct { * opaque cid<0..2^8-1>; * } ConnectionId; */ *olen = 0; if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding CID extension")); /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX * which is at most 255, so the increment cannot overflow. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, (unsigned) (ssl->own_cid_len + 5)); /* Add extension ID + size */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_CID, p, 0); p += 2; ext_len = (size_t) ssl->own_cid_len + 1; MBEDTLS_PUT_UINT16_BE(ext_len, p, 0); p += 2; *p++ = (uint8_t) ssl->own_cid_len; memcpy(p, ssl->own_cid, ssl->own_cid_len); *olen = ssl->own_cid_len + 5; return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; *olen = 0; if (ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding max_fragment_length extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0); p += 2; *p++ = 0x00; *p++ = 1; *p++ = ssl->conf->mfl_code; *olen = 5; return 0; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; *olen = 0; if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding encrypt_then_mac extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; return 0; } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; *olen = 0; if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding extended_master_secret extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; return 0; } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; size_t tlen = ssl->session_negotiate->ticket_len; *olen = 0; if (mbedtls_ssl_conf_get_session_tickets(ssl->conf) == MBEDTLS_SSL_SESSION_TICKETS_DISABLED) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding session ticket extension")); /* The addition is safe here since the ticket length is 16 bit. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + tlen); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0); p += 2; MBEDTLS_PUT_UINT16_BE(tlen, p, 0); p += 2; *olen = 4; if (ssl->session_negotiate->ticket == NULL || tlen == 0) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("sending session ticket of length %" MBEDTLS_PRINTF_SIZET, tlen)); memcpy(p, ssl->session_negotiate->ticket, tlen); *olen += tlen; return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_DTLS_SRTP) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; size_t protection_profiles_index = 0, ext_len = 0; uint16_t mki_len = 0, profile_value = 0; *olen = 0; if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->conf->dtls_srtp_profile_list == NULL) || (ssl->conf->dtls_srtp_profile_list_len == 0)) { return 0; } /* RFC 5764 section 4.1.1 * uint8 SRTPProtectionProfile[2]; * * struct { * SRTPProtectionProfiles SRTPProtectionProfiles; * opaque srtp_mki<0..255>; * } UseSRTPData; * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; */ if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) { mki_len = ssl->dtls_srtp_info.mki_len; } /* Extension length = 2 bytes for profiles length, * ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ), * 1 byte for srtp_mki vector length and the mki_len value */ ext_len = 2 + 2 * (ssl->conf->dtls_srtp_profile_list_len) + 1 + mki_len; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding use_srtp extension")); /* Check there is room in the buffer for the extension + 4 bytes * - the extension tag (2 bytes) * - the extension length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, ext_len + 4); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, p, 0); p += 2; MBEDTLS_PUT_UINT16_BE(ext_len, p, 0); p += 2; /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */ /* micro-optimization: * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH * which is lower than 127, so the upper byte of the length is always 0 * For the documentation, the more generic code is left in comments * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len ) * >> 8 ) & 0xFF ); */ *p++ = 0; *p++ = MBEDTLS_BYTE_0(2 * ssl->conf->dtls_srtp_profile_list_len); for (protection_profiles_index = 0; protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len; protection_profiles_index++) { profile_value = mbedtls_ssl_check_srtp_profile_value (ssl->conf->dtls_srtp_profile_list[protection_profiles_index]); if (profile_value != MBEDTLS_TLS_SRTP_UNSET) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_write_use_srtp_ext, add profile: %04x", profile_value)); MBEDTLS_PUT_UINT16_BE(profile_value, p, 0); p += 2; } else { /* * Note: we shall never arrive here as protection profiles * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function */ MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, " "illegal DTLS-SRTP protection profile %d", ssl->conf->dtls_srtp_profile_list[protection_profiles_index] )); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } } *p++ = mki_len & 0xFF; if (mki_len != 0) { memcpy(p, ssl->dtls_srtp_info.mki_value, mki_len); /* * Increment p to point to the current position. */ p += mki_len; MBEDTLS_SSL_DEBUG_BUF(3, "sending mki", ssl->dtls_srtp_info.mki_value, ssl->dtls_srtp_info.mki_len); } /* * total extension length: extension type (2 bytes) * + extension length (2 bytes) * + protection profile length (2 bytes) * + 2 * number of protection profiles * + srtp_mki vector length(1 byte) * + mki value */ *olen = p - buf; return 0; } #endif /* MBEDTLS_SSL_DTLS_SRTP */ int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, int uses_ec, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t ext_len = 0; (void) ssl; (void) end; (void) uses_ec; (void) ret; (void) ext_len; *out_len = 0; /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if ((ret = ssl_write_renegotiation_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_renegotiation_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (uses_ec) { if ((ret = ssl_write_supported_point_formats_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_supported_point_formats_ext", ret); return ret; } p += ext_len; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if ((ret = ssl_write_ecjpake_kkpp_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_ecjpake_kkpp_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if ((ret = ssl_write_cid_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_cid_ext", ret); return ret; } p += ext_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) if ((ret = ssl_write_max_fragment_length_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_max_fragment_length_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if ((ret = ssl_write_encrypt_then_mac_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_encrypt_then_mac_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) if ((ret = ssl_write_extended_ms_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_extended_ms_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) if ((ret = ssl_write_use_srtp_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_use_srtp_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) if ((ret = ssl_write_session_ticket_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_session_ticket_ext", ret); return ret; } p += ext_len; #endif *out_len = (size_t) (p - buf); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { /* Check verify-data in constant-time. The length OTOH is no secret */ if (len != 1 + ssl->verify_data_len * 2 || buf[0] != ssl->verify_data_len * 2 || mbedtls_ct_memcmp(buf + 1, ssl->own_verify_data, ssl->verify_data_len) != 0 || mbedtls_ct_memcmp(buf + 1 + ssl->verify_data_len, ssl->peer_verify_data, ssl->verify_data_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching renegotiation info")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ { if (len != 1 || buf[0] != 0x00) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-zero length renegotiation info")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; } return 0; } #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { /* * server should use the extension only if we did, * and if so the server's value should match ours (and len is always 1) */ if (ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || len != 1 || buf[0] != ssl->conf->mfl_code) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching max fragment length extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } return 0; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t peer_cid_len; if ( /* CID extension only makes sense in DTLS */ ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || /* The server must only send the CID extension if we have offered it. */ ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension unexpected")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } if (len == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } peer_cid_len = *buf++; len--; if (peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } if (len != peer_cid_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; memcpy(ssl->handshake->peer_cid, buf, peer_cid_len); MBEDTLS_SSL_DEBUG_MSG(3, ("Use of CID extension negotiated")); MBEDTLS_SSL_DEBUG_BUF(3, "Server CID", buf, peer_cid_len); return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching encrypt-then-MAC extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } ((void) buf); ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; return 0; } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching extended master secret extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } ((void) buf); ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; return 0; } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if ((mbedtls_ssl_conf_get_session_tickets(ssl->conf) == MBEDTLS_SSL_SESSION_TICKETS_DISABLED) || len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching session ticket extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } ((void) buf); ssl->handshake->new_session_ticket = 1; return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t list_size; const unsigned char *p; if (len == 0 || (size_t) (buf[0] + 1) != len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_size = buf[0]; p = buf + 1; while (list_size > 0) { if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || p[0] == MBEDTLS_ECP_PF_COMPRESSED) { #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) ssl->handshake->ecdh_ctx.point_format = p[0]; #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx, p[0]); #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(4, ("point format selected: %d", p[0])); return 0; } list_size--; p++; } MBEDTLS_SSL_DEBUG_MSG(1, ("no point format in common")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl->handshake->ciphersuite_info->key_exchange != MBEDTLS_KEY_EXCHANGE_ECJPAKE) { MBEDTLS_SSL_DEBUG_MSG(3, ("skip ecjpake kkpp extension")); return 0; } /* If we got here, we no longer need our cached extension */ mbedtls_free(ssl->handshake->ecjpake_cache); ssl->handshake->ecjpake_cache = NULL; ssl->handshake->ecjpake_cache_len = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_psa_ecjpake_read_round( &ssl->handshake->psa_pake_ctx, buf, len, MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return ret; } return 0; #else if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx, buf, len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_one", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return ret; } return 0; #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t list_len, name_len; const char **p; /* If we didn't send it, the server shouldn't send it */ if (ssl->conf->alpn_list == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching ALPN extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } /* * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; * * the "ProtocolNameList" MUST contain exactly one "ProtocolName" */ /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ if (len < 4) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_len = MBEDTLS_GET_UINT16_BE(buf, 0); if (list_len != len - 2) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } name_len = buf[2]; if (name_len != list_len - 1) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Check that the server chosen protocol was in our list and save it */ for (p = ssl->conf->alpn_list; *p != NULL; p++) { if (name_len == strlen(*p) && memcmp(buf + 3, *p, name_len) == 0) { ssl->alpn_chosen = *p; return 0; } } MBEDTLS_SSL_DEBUG_MSG(1, ("ALPN extension: no matching protocol")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET; size_t i, mki_len = 0; uint16_t server_protection_profile_value = 0; /* If use_srtp is not configured, just ignore the extension */ if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->conf->dtls_srtp_profile_list == NULL) || (ssl->conf->dtls_srtp_profile_list_len == 0)) { return 0; } /* RFC 5764 section 4.1.1 * uint8 SRTPProtectionProfile[2]; * * struct { * SRTPProtectionProfiles SRTPProtectionProfiles; * opaque srtp_mki<0..255>; * } UseSRTPData; * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; * */ if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) { mki_len = ssl->dtls_srtp_info.mki_len; } /* * Length is 5 + optional mki_value : one protection profile length (2 bytes) * + protection profile (2 bytes) * + mki_len(1 byte) * and optional srtp_mki */ if ((len < 5) || (len != (buf[4] + 5u))) { return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * get the server protection profile */ /* * protection profile length must be 0x0002 as we must have only * one protection profile in server Hello */ if ((buf[0] != 0) || (buf[1] != 2)) { return MBEDTLS_ERR_SSL_DECODE_ERROR; } server_protection_profile_value = (buf[2] << 8) | buf[3]; server_protection = mbedtls_ssl_check_srtp_profile_value( server_protection_profile_value); if (server_protection != MBEDTLS_TLS_SRTP_UNSET) { MBEDTLS_SSL_DEBUG_MSG(3, ("found srtp profile: %s", mbedtls_ssl_get_srtp_profile_as_string( server_protection))); } ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; /* * Check we have the server profile in our list */ for (i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) { if (server_protection == ssl->conf->dtls_srtp_profile_list[i]) { ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; MBEDTLS_SSL_DEBUG_MSG(3, ("selected srtp profile: %s", mbedtls_ssl_get_srtp_profile_as_string( server_protection))); break; } } /* If no match was found : server problem, it shall never answer with incompatible profile */ if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* If server does not use mki in its reply, make sure the client won't keep * one as negotiated */ if (len == 5) { ssl->dtls_srtp_info.mki_len = 0; } /* * RFC5764: * If the client detects a nonzero-length MKI in the server's response * that is different than the one the client offered, then the client * MUST abort the handshake and SHOULD send an invalid_parameter alert. */ if (len > 5 && (buf[4] != mki_len || (memcmp(ssl->dtls_srtp_info.mki_value, &buf[5], mki_len)))) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if defined(MBEDTLS_DEBUG_C) if (len > 5) { MBEDTLS_SSL_DEBUG_BUF(3, "received mki", ssl->dtls_srtp_info.mki_value, ssl->dtls_srtp_info.mki_len); } #endif return 0; } #endif /* MBEDTLS_SSL_DTLS_SRTP */ /* * Parse HelloVerifyRequest. Only called after verifying the HS type. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); uint16_t dtls_legacy_version; #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) uint8_t cookie_len; #else uint16_t cookie_len; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse hello verify request")); /* Check that there is enough room for: * - 2 bytes of version * - 1 byte of cookie_len */ if (mbedtls_ssl_hs_hdr_len(ssl) + 3 > ssl->in_msglen) { MBEDTLS_SSL_DEBUG_MSG(1, ("incoming HelloVerifyRequest message is too short")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * struct { * ProtocolVersion server_version; * opaque cookie<0..2^8-1>; * } HelloVerifyRequest; */ MBEDTLS_SSL_DEBUG_BUF(3, "server version", p, 2); dtls_legacy_version = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* * Since the RFC is not clear on this point, accept DTLS 1.0 (0xfeff) * The DTLS 1.3 (current draft) renames ProtocolVersion server_version to * legacy_version and locks the value of legacy_version to 0xfefd (DTLS 1.2) */ if (dtls_legacy_version != 0xfefd && dtls_legacy_version != 0xfeff) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server version")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } cookie_len = *p++; if ((ssl->in_msg + ssl->in_msglen) - p < cookie_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("cookie length does not match incoming message size")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "cookie", p, cookie_len); mbedtls_free(ssl->handshake->cookie); ssl->handshake->cookie = mbedtls_calloc(1, cookie_len); if (ssl->handshake->cookie == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc failed (%d bytes)", cookie_len)); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ssl->handshake->cookie, p, cookie_len); ssl->handshake->cookie_len = cookie_len; /* Start over at ClientHello */ ssl->state = MBEDTLS_SSL_CLIENT_HELLO; ret = mbedtls_ssl_reset_checksum(ssl); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_reset_checksum"), ret); return ret; } mbedtls_ssl_recv_flight_completed(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse hello verify request")); return 0; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) { int ret, i; size_t n; size_t ext_len; unsigned char *buf, *ext; unsigned char comp; #if defined(MBEDTLS_SSL_RENEGOTIATION) int renegotiation_info_seen = 0; #endif int handshake_failure = 0; const mbedtls_ssl_ciphersuite_t *suite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse server hello")); if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } buf = ssl->in_msg; if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { ssl->renego_records_seen++; if (ssl->conf->renego_max_records >= 0 && ssl->renego_records_seen > ssl->conf->renego_max_records) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation requested, but not honored by server")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } MBEDTLS_SSL_DEBUG_MSG(1, ("non-handshake message during renegotiation")); ssl->keep_current_message = 1; return MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { if (buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST) { MBEDTLS_SSL_DEBUG_MSG(2, ("received hello verify request")); MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello")); return ssl_parse_hello_verify_request(ssl); } else { /* We made it through the verification process */ mbedtls_free(ssl->handshake->cookie); ssl->handshake->cookie = NULL; ssl->handshake->cookie_len = 0; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ if (ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len(ssl) || buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * 0 . 1 server_version * 2 . 33 random (maybe including 4 bytes of Unix time) * 34 . 34 session_id length = n * 35 . 34+n session_id * 35+n . 36+n cipher_suite * 37+n . 37+n compression_method * * 38+n . 39+n extensions length (optional) * 40+n . .. extensions */ buf += mbedtls_ssl_hs_hdr_len(ssl); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", buf, 2); ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf, ssl->conf->transport); ssl->session_negotiate->tls_version = ssl->tls_version; ssl->session_negotiate->endpoint = ssl->conf->endpoint; if (ssl->tls_version < ssl->conf->min_tls_version || ssl->tls_version > ssl->conf->max_tls_version) { MBEDTLS_SSL_DEBUG_MSG(1, ( "server version out of bounds - min: [0x%x], server: [0x%x], max: [0x%x]", (unsigned) ssl->conf->min_tls_version, (unsigned) ssl->tls_version, (unsigned) ssl->conf->max_tls_version)); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, current time: %lu", ((unsigned long) buf[2] << 24) | ((unsigned long) buf[3] << 16) | ((unsigned long) buf[4] << 8) | ((unsigned long) buf[5]))); memcpy(ssl->handshake->randbytes + 32, buf + 2, 32); n = buf[34]; MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", buf + 2, 32); if (n > 32) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (ssl->in_hslen > mbedtls_ssl_hs_hdr_len(ssl) + 39 + n) { ext_len = MBEDTLS_GET_UINT16_BE(buf, 38 + n); if ((ext_len > 0 && ext_len < 4) || ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 40 + n + ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } else if (ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl) + 38 + n) { ext_len = 0; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* ciphersuite (used later) */ i = (int) MBEDTLS_GET_UINT16_BE(buf, n + 35); /* * Read and check compression */ comp = buf[37 + n]; if (comp != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("server hello, bad compression: %d", comp)); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } /* * Initialize update checksum functions */ ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(i); if (ssl->handshake->ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %04x not found", (unsigned int) i)); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } mbedtls_ssl_optimize_checksum(ssl, ssl->handshake->ciphersuite_info); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n)); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, session id", buf + 35, n); /* * Check if the session can be resumed */ if (ssl->handshake->resume == 0 || n == 0 || #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || #endif ssl->session_negotiate->ciphersuite != i || ssl->session_negotiate->id_len != n || memcmp(ssl->session_negotiate->id, buf + 35, n) != 0) { ssl->state++; ssl->handshake->resume = 0; #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); #endif ssl->session_negotiate->ciphersuite = i; ssl->session_negotiate->id_len = n; memcpy(ssl->session_negotiate->id, buf + 35, n); } else { ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; } MBEDTLS_SSL_DEBUG_MSG(3, ("%s session has been resumed", ssl->handshake->resume ? "a" : "no")); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %04x", (unsigned) i)); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, compress alg.: %d", buf[37 + n])); /* * Perform cipher suite validation in same way as in ssl_write_client_hello. */ i = 0; while (1) { if (ssl->conf->ciphersuite_list[i] == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } if (ssl->conf->ciphersuite_list[i++] == ssl->session_negotiate->ciphersuite) { break; } } suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite); if (mbedtls_ssl_validate_ciphersuite(ssl, suite_info, ssl->tls_version, ssl->tls_version) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %s", suite_info->name)); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { ssl->handshake->ecrs_enabled = 1; } #endif if (comp != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ext = buf + 40 + n; MBEDTLS_SSL_DEBUG_MSG(2, ("server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len)); while (ext_len) { unsigned int ext_id = MBEDTLS_GET_UINT16_BE(ext, 0); unsigned int ext_size = MBEDTLS_GET_UINT16_BE(ext, 2); if (ext_size + 4 > ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } switch (ext_id) { case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: MBEDTLS_SSL_DEBUG_MSG(3, ("found renegotiation extension")); #if defined(MBEDTLS_SSL_RENEGOTIATION) renegotiation_info_seen = 1; #endif if ((ret = ssl_parse_renegotiation_info(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: MBEDTLS_SSL_DEBUG_MSG(3, ("found max_fragment_length extension")); if ((ret = ssl_parse_max_fragment_length_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) case MBEDTLS_TLS_EXT_CID: MBEDTLS_SSL_DEBUG_MSG(3, ("found CID extension")); if ((ret = ssl_parse_cid_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: MBEDTLS_SSL_DEBUG_MSG(3, ("found encrypt_then_mac extension")); if ((ret = ssl_parse_encrypt_then_mac_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: MBEDTLS_SSL_DEBUG_MSG(3, ("found extended_master_secret extension")); if ((ret = ssl_parse_extended_ms_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_TLS_EXT_SESSION_TICKET: MBEDTLS_SSL_DEBUG_MSG(3, ("found session_ticket extension")); if ((ret = ssl_parse_session_ticket_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: MBEDTLS_SSL_DEBUG_MSG(3, ("found supported_point_formats extension")); if ((ret = ssl_parse_supported_point_formats_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: MBEDTLS_SSL_DEBUG_MSG(3, ("found ecjpake_kkpp extension")); if ((ret = ssl_parse_ecjpake_kkpp(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) case MBEDTLS_TLS_EXT_ALPN: MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); if ((ret = ssl_parse_alpn_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) case MBEDTLS_TLS_EXT_USE_SRTP: MBEDTLS_SSL_DEBUG_MSG(3, ("found use_srtp extension")); if ((ret = ssl_parse_use_srtp_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_DTLS_SRTP */ default: MBEDTLS_SSL_DEBUG_MSG(3, ("unknown extension found: %u (ignoring)", ext_id)); } ext_len -= 4 + ext_size; ext += 4 + ext_size; if (ext_len > 0 && ext_len < 4) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } /* * mbedtls_ssl_derive_keys() has to be called after the parsing of the * extensions. It sets the transform data for the resumed session which in * case of DTLS includes the server CID extracted from the CID extension. */ if (ssl->handshake->resume) { if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return ret; } } /* * Renegotiation security checks */ if (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation, breaking off handshake")); handshake_failure = 1; } #if defined(MBEDTLS_SSL_RENEGOTIATION) else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && renegotiation_info_seen == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension missing (secure)")); handshake_failure = 1; } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) { MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation not allowed")); handshake_failure = 1; } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && renegotiation_info_seen == 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension present (legacy)")); handshake_failure = 1; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ if (handshake_failure == 1) { mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello")); return 0; } #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_dh_params(mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t dhm_actual_bitlen; /* * Ephemeral DH parameters: * * struct { * opaque dh_p<1..2^16-1>; * opaque dh_g<1..2^16-1>; * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ if ((ret = mbedtls_dhm_read_params(&ssl->handshake->dhm_ctx, p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(2, ("mbedtls_dhm_read_params"), ret); return ret; } dhm_actual_bitlen = mbedtls_dhm_get_bitlen(&ssl->handshake->dhm_ctx); if (dhm_actual_bitlen < ssl->conf->dhm_min_bitlen) { MBEDTLS_SSL_DEBUG_MSG(1, ("DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u", dhm_actual_bitlen, ssl->conf->dhm_min_bitlen)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: P ", &ssl->handshake->dhm_ctx.P); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: G ", &ssl->handshake->dhm_ctx.G); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GY", &ssl->handshake->dhm_ctx.GY); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end) { uint16_t tls_id; size_t ecpoint_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; size_t ec_bits = 0; /* * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; * * 1 curve_type (must be "named_curve") * 2..3 NamedCurve * 4 ECPoint.len * 5+ ECPoint contents */ if (end - *p < 4) { return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* First byte is curve_type; only named_curve is handled */ if (*(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* Next two bytes are the namedcurve value */ tls_id = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; /* Check it's a curve we offered */ if (mbedtls_ssl_check_curve_tls_id(ssl, tls_id) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("bad server key exchange message (ECDHE curve): %u", (unsigned) tls_id)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* Convert EC's TLS ID to PSA key type. */ if (mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type, &ec_bits) == PSA_ERROR_NOT_SUPPORTED) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } handshake->xxdh_psa_type = key_type; handshake->xxdh_psa_bits = ec_bits; /* Keep a copy of the peer's public key */ ecpoint_len = *(*p)++; if ((size_t) (end - *p) < ecpoint_len) { return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } memcpy(handshake->xxdh_psa_peerkey, *p, ecpoint_len); handshake->xxdh_psa_peerkey_len = ecpoint_len; *p += ecpoint_len; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #else #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_server_ecdh_params(const mbedtls_ssl_context *ssl) { uint16_t tls_id; mbedtls_ecp_group_id grp_id; #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) grp_id = ssl->handshake->ecdh_ctx.grp.id; #else grp_id = ssl->handshake->ecdh_ctx.grp_id; #endif tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); if (tls_id == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH curve: %s", mbedtls_ssl_get_curve_name_from_tls_id(tls_id))); if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { return -1; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_QP); return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; /* * Ephemeral ECDH parameters: * * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ if ((ret = mbedtls_ecdh_read_params(&ssl->handshake->ecdh_ctx, (const unsigned char **) p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_read_params"), ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } if (ssl_check_server_ecdh_params(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message (ECDHE curve)")); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || \ MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \ MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #endif /* !MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; uint16_t len; ((void) ssl); /* * PSK parameters: * * opaque psk_identity_hint<0..2^16-1>; */ if (end - (*p) < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message (psk_identity_hint length)")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } len = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; if (end - (*p) < len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message (psk_identity_hint length)")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Note: we currently ignore the PSK identity hint, as we only allow one * PSK to be provisioned on the client. This could be changed later if * someone needs that feature. */ *p += len; ret = 0; return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) /* * Generate a pre-master secret and encrypt it with the server's RSA key */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_encrypted_pms(mbedtls_ssl_context *ssl, size_t offset, size_t *olen, size_t pms_offset) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len_bytes = 2; unsigned char *p = ssl->handshake->premaster + pms_offset; mbedtls_pk_context *peer_pk; if (offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small for encrypted pms")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } /* * Generate (part of) the pre-master as * struct { * ProtocolVersion client_version; * opaque random[46]; * } PreMasterSecret; */ mbedtls_ssl_write_version(p, ssl->conf->transport, MBEDTLS_SSL_VERSION_TLS1_2); if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p + 2, 46)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_rng", ret); return ret; } ssl->handshake->pmslen = 48; #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert == NULL) { /* Should never happen */ MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } peer_pk = &ssl->session_negotiate->peer_cert->pk; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* * Now write it out, encrypted */ if (!mbedtls_pk_can_do(peer_pk, MBEDTLS_PK_RSA)) { MBEDTLS_SSL_DEBUG_MSG(1, ("certificate key type mismatch")); return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } if ((ret = mbedtls_pk_encrypt(peer_pk, p, ssl->handshake->pmslen, ssl->out_msg + offset + len_bytes, olen, MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_rsa_pkcs1_encrypt", ret); return ret; } if (len_bytes == 2) { MBEDTLS_PUT_UINT16_BE(*olen, ssl->out_msg, offset); *olen += 2; } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* We don't need the peer's public key anymore. Free it. */ mbedtls_pk_free(peer_pk); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_pk_context *peer_pk; #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert == NULL) { /* Should never happen */ MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } peer_pk = &ssl->session_negotiate->peer_cert->pk; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* This is a public key, so it can't be opaque, so can_do() is a good * enough check to ensure pk_ec() is safe to use below. */ if (!mbedtls_pk_can_do(peer_pk, MBEDTLS_PK_ECKEY)) { MBEDTLS_SSL_DEBUG_MSG(1, ("server key not ECDH capable")); return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } #if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) const mbedtls_ecp_keypair *peer_key = mbedtls_pk_ec_ro(*peer_pk); #endif /* !defined(MBEDTLS_PK_USE_PSA_EC_DATA) */ #if defined(MBEDTLS_USE_PSA_CRYPTO) uint16_t tls_id = 0; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(peer_pk); if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)")); return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); if (tls_id == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("ECC group %u not suported", grp_id)); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* If the above conversion to TLS ID was fine, then also this one will be, so there is no need to check the return value here */ mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type, &ssl->handshake->xxdh_psa_bits); ssl->handshake->xxdh_psa_type = key_type; /* Store peer's public key in psa format. */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) memcpy(ssl->handshake->xxdh_psa_peerkey, peer_pk->pub_raw, peer_pk->pub_raw_len); ssl->handshake->xxdh_psa_peerkey_len = peer_pk->pub_raw_len; ret = 0; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ size_t olen = 0; ret = mbedtls_ecp_point_write_binary(&peer_key->grp, &peer_key->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, ssl->handshake->xxdh_psa_peerkey, sizeof(ssl->handshake->xxdh_psa_peerkey)); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecp_point_write_binary"), ret); return ret; } ssl->handshake->xxdh_psa_peerkey_len = olen; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #else /* MBEDTLS_USE_PSA_CRYPTO */ if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx, peer_key, MBEDTLS_ECDH_THEIRS)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret); return ret; } if (ssl_check_server_ecdh_params(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)")); return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* We don't need the peer's public key anymore. Free it, * so that more RAM is available for upcoming expensive * operations like ECDHE. */ mbedtls_pk_free(peer_pk); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; unsigned char *p = NULL, *end = NULL; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse server key exchange")); #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse server key exchange")); ssl->state++; return 0; } ((void) p); ((void) end); #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) { if ((ret = ssl_get_ecdh_params_from_cert(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_get_ecdh_params_from_cert", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse server key exchange")); ssl->state++; return 0; } ((void) p); ((void) end); #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing) { goto start_processing; } #endif if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server * doesn't use a psk_identity_hint */ if (ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE) { if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { /* Current message is probably either * CertificateRequest or ServerHelloDone */ ssl->keep_current_message = 1; goto exit; } MBEDTLS_SSL_DEBUG_MSG(1, ("server key exchange message must not be skipped")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; } start_processing: #endif p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); end = ssl->in_msg + ssl->in_hslen; MBEDTLS_SSL_DEBUG_BUF(3, "server key exchange", p, (size_t) (end - p)); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { if (ssl_parse_server_psk_hint(ssl, &p, end) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } /* FALLTHROUGH */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { ; /* nothing more to do */ } else #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { if (ssl_parse_server_dh_params(ssl, &p, end) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA) { if (ssl_parse_server_ecdh_params(ssl, &p, end) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { #if defined(MBEDTLS_USE_PSA_CRYPTO) /* * The first 3 bytes are: * [0] MBEDTLS_ECP_TLS_NAMED_CURVE * [1, 2] elliptic curve's TLS ID * * However since we only support secp256r1 for now, we check only * that TLS ID here */ uint16_t read_tls_id = MBEDTLS_GET_UINT16_BE(p, 1); uint16_t exp_tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( MBEDTLS_ECP_DP_SECP256R1); if (exp_tls_id == 0) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } if ((*p != MBEDTLS_ECP_TLS_NAMED_CURVE) || (read_tls_id != exp_tls_id)) { return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += 3; if ((ret = mbedtls_psa_ecjpake_read_round( &ssl->handshake->psa_pake_ctx, p, end - p, MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #else ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx, p, end - p); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_two", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) { size_t sig_len, hashlen; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); size_t params_len = (size_t) (p - params); void *rs_ctx = NULL; uint16_t sig_alg; mbedtls_pk_context *peer_pk; #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert == NULL) { /* Should never happen */ MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } peer_pk = &ssl->session_negotiate->peer_cert->pk; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* * Handle the digitally-signed structure */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( sig_alg, &pk_alg, &md_alg) != 0 && !mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) && !mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += 2; if (!mbedtls_pk_can_do(peer_pk, pk_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* * Read signature */ if (p > end - 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } sig_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; if (p != end - sig_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "signature", p, sig_len); /* * Compute the hash that has been signed */ if (md_alg != MBEDTLS_MD_NONE) { ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen, params, params_len, md_alg); if (ret != 0) { return ret; } } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "parameters hash", hash, hashlen); /* * Verify signature */ if (!mbedtls_pk_can_do(peer_pk, pk_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { rs_ctx = &ssl->handshake->ecrs_ctx.pk; } #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { mbedtls_pk_rsassa_pss_options rsassa_pss_options; rsassa_pss_options.mgf1_hash_id = md_alg; rsassa_pss_options.expected_salt_len = mbedtls_md_get_size_from_type(md_alg); if (rsassa_pss_options.expected_salt_len == 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ret = mbedtls_pk_verify_ext(pk_alg, &rsassa_pss_options, peer_pk, md_alg, hash, hashlen, p, sig_len); } else #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ ret = mbedtls_pk_verify_restartable(peer_pk, md_alg, hash, hashlen, p, sig_len, rs_ctx); if (ret != 0) { int send_alert_msg = 1; #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) send_alert_msg = (ret != MBEDTLS_ERR_ECP_IN_PROGRESS); #endif if (send_alert_msg) { mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR); } MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify", ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* We don't need the peer's public key anymore. Free it, * so that more RAM is available for upcoming expensive * operations like ECDHE. */ mbedtls_pk_free(peer_pk); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ exit: ssl->state++; MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server key exchange")); return 0; } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate request")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t n = 0; size_t cert_type_len = 0, dn_len = 0; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; size_t sig_alg_len; #if defined(MBEDTLS_DEBUG_C) unsigned char *sig_alg; unsigned char *dn; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate request")); ssl->state++; return 0; } if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } ssl->state++; ssl->handshake->client_auth = (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST); MBEDTLS_SSL_DEBUG_MSG(3, ("got %s certificate request", ssl->handshake->client_auth ? "a" : "no")); if (ssl->handshake->client_auth == 0) { /* Current message is probably the ServerHelloDone */ ssl->keep_current_message = 1; goto exit; } /* * struct { * ClientCertificateType certificate_types<1..2^8-1>; * SignatureAndHashAlgorithm * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only * DistinguishedName certificate_authorities<0..2^16-1>; * } CertificateRequest; * * Since we only support a single certificate on clients, let's just * ignore all the information that's supposed to help us pick a * certificate. * * We could check that our certificate matches the request, and bail out * if it doesn't, but it's simpler to just send the certificate anyway, * and give the server the opportunity to decide if it should terminate * the connection when it doesn't like our certificate. * * Same goes for the hash in TLS 1.2's signature_algorithms: at this * point we only have one hash available (see comments in * write_certificate_verify), so let's just use what we have. * * However, we still minimally parse the message to check it is at least * superficially sane. */ buf = ssl->in_msg; /* certificate_types */ if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } cert_type_len = buf[mbedtls_ssl_hs_hdr_len(ssl)]; n = cert_type_len; /* * In the subsequent code there are two paths that read from buf: * * the length of the signature algorithms field (if minor version of * SSL is 3), * * distinguished name length otherwise. * Both reach at most the index: * ...hdr_len + 2 + n, * therefore the buffer length at this point must be greater than that * regardless of the actual code path. */ if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) + 2 + n) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* supported_signature_algorithms */ sig_alg_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n); /* * The furthest access in buf is in the loop few lines below: * sig_alg[i + 1], * where: * sig_alg = buf + ...hdr_len + 3 + n, * max(i) = sig_alg_len - 1. * Therefore the furthest access is: * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], * which reduces to: * buf[...hdr_len + 3 + n + sig_alg_len], * which is one less than we need the buf to be. */ if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) + 3 + n + sig_alg_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } #if defined(MBEDTLS_DEBUG_C) sig_alg = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n; for (size_t i = 0; i < sig_alg_len; i += 2) { MBEDTLS_SSL_DEBUG_MSG(3, ("Supported Signature Algorithm found: %02x %02x", sig_alg[i], sig_alg[i + 1])); } #endif n += 2 + sig_alg_len; /* certificate_authorities */ dn_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n); n += dn_len; if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 3 + n) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } #if defined(MBEDTLS_DEBUG_C) dn = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n - dn_len; for (size_t i = 0, dni_len = 0; i < dn_len; i += 2 + dni_len) { unsigned char *p = dn + i + 2; mbedtls_x509_name name; size_t asn1_len; char s[MBEDTLS_X509_MAX_DN_NAME_SIZE]; memset(&name, 0, sizeof(name)); dni_len = MBEDTLS_GET_UINT16_BE(dn + i, 0); if (dni_len > dn_len - i - 2 || mbedtls_asn1_get_tag(&p, p + dni_len, &asn1_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0 || mbedtls_x509_get_name(&p, p + asn1_len, &name) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("DN hint: %.*s", mbedtls_x509_dn_gets(s, sizeof(s), &name), s)); mbedtls_asn1_free_named_data_list_shallow(name.next); } #endif exit: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate request")); return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_hello_done(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse server hello done")); if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello done message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) || ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello done message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->state++; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_recv_flight_completed(ssl); } #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello done")); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t header_len; size_t content_len; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write client key exchange")); #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA) { /* * DHM key exchange -- send G^X mod P */ content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx); MBEDTLS_PUT_UINT16_BE(content_len, ssl->out_msg, 4); header_len = 6; ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx, (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), &ssl->out_msg[header_len], content_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_public", ret); return ret; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: X ", &ssl->handshake->dhm_ctx.X); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GX", &ssl->handshake->dhm_ctx.GX); if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, ssl->handshake->premaster, MBEDTLS_PREMASTER_SIZE, &ssl->handshake->pmslen, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return ret; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t key_attributes; mbedtls_ssl_handshake_params *handshake = ssl->handshake; header_len = 4; MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); /* * Generate EC private key for ECDHE exchange. */ /* The master secret is obtained from the shared ECDH secret by * applying the TLS 1.2 PRF with a specific salt and label. While * the PSA Crypto API encourages combining key agreement schemes * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not * yet support the provisioning of salt + label to the KDF. * For the time being, we therefore need to split the computation * of the ECDH secret and the application of the TLS 1.2 PRF. */ key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); /* Generate ECDH private key. */ status = psa_generate_key(&key_attributes, &handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } /* Export the public part of the ECDH private key from PSA. * The export format is an ECPoint structure as expected by TLS, * but we just need to add a length byte before that. */ unsigned char *own_pubkey = ssl->out_msg + header_len + 1; unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t own_pubkey_max_len = (size_t) (end - own_pubkey); size_t own_pubkey_len; status = psa_export_public_key(handshake->xxdh_psa_privkey, own_pubkey, own_pubkey_max_len, &own_pubkey_len); if (status != PSA_SUCCESS) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } ssl->out_msg[header_len] = (unsigned char) own_pubkey_len; content_len = own_pubkey_len + 1; /* The ECDH secret is the premaster secret used for key derivation. */ /* Compute ECDH shared secret. */ status = psa_raw_key_agreement(PSA_ALG_ECDH, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, ssl->handshake->premaster, sizeof(ssl->handshake->premaster), &ssl->handshake->pmslen); destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; if (status != PSA_SUCCESS || destruction_status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } #else /* * ECDH key exchange -- send client public value */ header_len = 4; #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { if (ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret) { goto ecdh_calc_secret; } mbedtls_ecdh_enable_restart(&ssl->handshake->ecdh_ctx); } #endif ret = mbedtls_ecdh_make_public(&ssl->handshake->ecdh_ctx, &content_len, &ssl->out_msg[header_len], 1000, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_make_public", ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Q); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { ssl->handshake->ecrs_n = content_len; ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; } ecdh_calc_secret: if (ssl->handshake->ecrs_enabled) { content_len = ssl->handshake->ecrs_n; } #endif if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, ssl->handshake->premaster, MBEDTLS_MPI_MAX_SIZE, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Z); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t key_attributes; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* * opaque psk_identity<0..2^16-1>; */ if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { /* We don't offer PSK suites if we don't have a PSK, * and we check that the server's choice is among the * ciphersuites we offered, so this should never happen. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* uint16 to store content length */ const size_t content_len_size = 2; header_len = 4; if (header_len + content_len_size + ssl->conf->psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("psk identity too long or SSL buffer too short")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } unsigned char *p = ssl->out_msg + header_len; *p++ = MBEDTLS_BYTE_1(ssl->conf->psk_identity_len); *p++ = MBEDTLS_BYTE_0(ssl->conf->psk_identity_len); header_len += content_len_size; memcpy(p, ssl->conf->psk_identity, ssl->conf->psk_identity_len); p += ssl->conf->psk_identity_len; header_len += ssl->conf->psk_identity_len; MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); /* * Generate EC private key for ECDHE exchange. */ /* The master secret is obtained from the shared ECDH secret by * applying the TLS 1.2 PRF with a specific salt and label. While * the PSA Crypto API encourages combining key agreement schemes * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not * yet support the provisioning of salt + label to the KDF. * For the time being, we therefore need to split the computation * of the ECDH secret and the application of the TLS 1.2 PRF. */ key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); /* Generate ECDH private key. */ status = psa_generate_key(&key_attributes, &handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } /* Export the public part of the ECDH private key from PSA. * The export format is an ECPoint structure as expected by TLS, * but we just need to add a length byte before that. */ unsigned char *own_pubkey = p + 1; unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t own_pubkey_max_len = (size_t) (end - own_pubkey); size_t own_pubkey_len = 0; status = psa_export_public_key(handshake->xxdh_psa_privkey, own_pubkey, own_pubkey_max_len, &own_pubkey_len); if (status != PSA_SUCCESS) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return PSA_TO_MBEDTLS_ERR(status); } *p = (unsigned char) own_pubkey_len; content_len = own_pubkey_len + 1; /* As RFC 5489 section 2, the premaster secret is formed as follows: * - a uint16 containing the length (in octets) of the ECDH computation * - the octet string produced by the ECDH computation * - a uint16 containing the length (in octets) of the PSK * - the PSK itself */ unsigned char *pms = ssl->handshake->premaster; const unsigned char * const pms_end = pms + sizeof(ssl->handshake->premaster); /* uint16 to store length (in octets) of the ECDH computation */ const size_t zlen_size = 2; size_t zlen = 0; /* Perform ECDH computation after the uint16 reserved for the length */ status = psa_raw_key_agreement(PSA_ALG_ECDH, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, pms + zlen_size, pms_end - (pms + zlen_size), &zlen); destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } else if (destruction_status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(destruction_status); } /* Write the ECDH computation length before the ECDH computation */ MBEDTLS_PUT_UINT16_BE(zlen, pms, 0); pms += zlen_size + zlen; } else #endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (mbedtls_ssl_ciphersuite_uses_psk(ciphersuite_info)) { /* * opaque psk_identity<0..2^16-1>; */ if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { /* We don't offer PSK suites if we don't have a PSK, * and we check that the server's choice is among the * ciphersuites we offered, so this should never happen. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } header_len = 4; content_len = ssl->conf->psk_identity_len; if (header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("psk identity too long or SSL buffer too short")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } ssl->out_msg[header_len++] = MBEDTLS_BYTE_1(content_len); ssl->out_msg[header_len++] = MBEDTLS_BYTE_0(content_len); memcpy(ssl->out_msg + header_len, ssl->conf->psk_identity, ssl->conf->psk_identity_len); header_len += ssl->conf->psk_identity_len; #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK) { content_len = 0; } else #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { if ((ret = ssl_write_encrypted_pms(ssl, header_len, &content_len, 2)) != 0) { return ret; } } else #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { /* * ClientDiffieHellmanPublic public (DHM send G^X mod P) */ content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx); if (header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("psk identity or DHM size too long or SSL buffer too short")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } ssl->out_msg[header_len++] = MBEDTLS_BYTE_1(content_len); ssl->out_msg[header_len++] = MBEDTLS_BYTE_0(content_len); ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx, (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), &ssl->out_msg[header_len], content_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_public", ret); return ret; } #if defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char *pms = ssl->handshake->premaster; unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster); size_t pms_len; /* Write length only when we know the actual value */ if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, pms + 2, pms_end - (pms + 2), &pms_len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return ret; } MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0); pms += 2 + pms_len; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); #endif } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { /* * ClientECDiffieHellmanPublic public; */ ret = mbedtls_ecdh_make_public(&ssl->handshake->ecdh_ctx, &content_len, &ssl->out_msg[header_len], MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_make_public", ret); return ret; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Q); } else #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) { header_len = 4; if ((ret = ssl_write_encrypted_pms(ssl, header_len, &content_len, 0)) != 0) { return ret; } } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { header_len = 4; #if defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char *out_p = ssl->out_msg + header_len; unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - header_len; ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, out_p, end_p - out_p, &content_len, MBEDTLS_ECJPAKE_ROUND_TWO); if (ret != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); return ret; } #else ret = mbedtls_ecjpake_write_round_two(&ssl->handshake->ecjpake_ctx, ssl->out_msg + header_len, MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, &content_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_two", ret); return ret; } ret = mbedtls_ecjpake_derive_secret(&ssl->handshake->ecjpake_ctx, ssl->handshake->premaster, 32, &ssl->handshake->pmslen, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_derive_secret", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ { ((void) ciphersuite_info); MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->out_msglen = header_len + content_len; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client key exchange")); return 0; } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify")); if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); return ret; } if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; size_t n = 0, offset = 0; unsigned char hash[48]; unsigned char *hash_start = hash; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; size_t hashlen; void *rs_ctx = NULL; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf); #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf); #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify")); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign) { goto sign; } #endif if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); return ret; } if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); ssl->state++; return 0; } if (ssl->handshake->client_auth == 0 || mbedtls_ssl_own_cert(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); ssl->state++; return 0; } if (mbedtls_ssl_own_key(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no private key for certificate")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } /* * Make a signature of the handshake digests */ #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; } sign: #endif ret = ssl->handshake->calc_verify(ssl, hash, &hashlen); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret); return ret; } /* * digitally-signed struct { * opaque handshake_messages[handshake_messages_length]; * }; * * Taking shortcut here. We assume that the server always allows the * PRF Hash function and has sent it in the allowed signature * algorithms list received in the Certificate Request message. * * Until we encounter a server that does not, we will take this * shortcut. * * Reason: Otherwise we should have running hashes for SHA512 and * SHA224 in order to satisfy 'weird' needs from the server * side. */ if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) { md_alg = MBEDTLS_MD_SHA384; ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; } else { md_alg = MBEDTLS_MD_SHA256; ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; } ssl->out_msg[5] = mbedtls_ssl_sig_from_pk(mbedtls_ssl_own_key(ssl)); /* Info from md_alg will be used instead */ hashlen = 0; offset = 2; #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { rs_ctx = &ssl->handshake->ecrs_ctx.pk; } #endif if ((ret = mbedtls_pk_sign_restartable(mbedtls_ssl_own_key(ssl), md_alg, hash_start, hashlen, ssl->out_msg + 6 + offset, out_buf_len - 6 - offset, &n, ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_sign", ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } MBEDTLS_PUT_UINT16_BE(n, ssl->out_msg, offset + 4); ssl->out_msglen = 6 + n + offset; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate verify")); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_new_session_ticket(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t lifetime; size_t ticket_len; unsigned char *ticket; const unsigned char *msg; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket")); if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* * struct { * uint32 ticket_lifetime_hint; * opaque ticket<0..2^16-1>; * } NewSessionTicket; * * 0 . 3 ticket_lifetime_hint * 4 . 5 ticket_len (n) * 6 . 5+n ticket content */ if (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); lifetime = MBEDTLS_GET_UINT32_BE(msg, 0); ticket_len = MBEDTLS_GET_UINT16_BE(msg, 4); if (ticket_len + 6 + mbedtls_ssl_hs_hdr_len(ssl) != ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len)); /* We're not waiting for a NewSessionTicket message any more */ ssl->handshake->new_session_ticket = 0; ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; /* * Zero-length ticket means the server changed his mind and doesn't want * to send a ticket after all, so just forget it */ if (ticket_len == 0) { return 0; } if (ssl->session != NULL && ssl->session->ticket != NULL) { mbedtls_zeroize_and_free(ssl->session->ticket, ssl->session->ticket_len); ssl->session->ticket = NULL; ssl->session->ticket_len = 0; } mbedtls_zeroize_and_free(ssl->session_negotiate->ticket, ssl->session_negotiate->ticket_len); ssl->session_negotiate->ticket = NULL; ssl->session_negotiate->ticket_len = 0; if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ticket alloc failed")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ticket, msg + 6, ticket_len); ssl->session_negotiate->ticket = ticket; ssl->session_negotiate->ticket_len = ticket_len; ssl->session_negotiate->ticket_lifetime = lifetime; /* * RFC 5077 section 3.4: * "If the client receives a session ticket from the server, then it * discards any Session ID that was sent in the ServerHello." */ MBEDTLS_SSL_DEBUG_MSG(3, ("ticket in use, discarding session id")); ssl->session_negotiate->id_len = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse new session ticket")); return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * SSL handshake -- client side -- single step */ int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) { int ret = 0; /* Change state now, so that it is right in mbedtls_ssl_read_record(), used * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && ssl->handshake->new_session_ticket != 0) { ssl->state = MBEDTLS_SSL_NEW_SESSION_TICKET; } #endif switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: ssl->state = MBEDTLS_SSL_CLIENT_HELLO; break; /* * ==> ClientHello */ case MBEDTLS_SSL_CLIENT_HELLO: ret = mbedtls_ssl_write_client_hello(ssl); break; /* * <== ServerHello * Certificate * ( ServerKeyExchange ) * ( CertificateRequest ) * ServerHelloDone */ case MBEDTLS_SSL_SERVER_HELLO: ret = ssl_parse_server_hello(ssl); break; case MBEDTLS_SSL_SERVER_CERTIFICATE: ret = mbedtls_ssl_parse_certificate(ssl); break; case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: ret = ssl_parse_server_key_exchange(ssl); break; case MBEDTLS_SSL_CERTIFICATE_REQUEST: ret = ssl_parse_certificate_request(ssl); break; case MBEDTLS_SSL_SERVER_HELLO_DONE: ret = ssl_parse_server_hello_done(ssl); break; /* * ==> ( Certificate/Alert ) * ClientKeyExchange * ( CertificateVerify ) * ChangeCipherSpec * Finished */ case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = mbedtls_ssl_write_certificate(ssl); break; case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: ret = ssl_write_client_key_exchange(ssl); break; case MBEDTLS_SSL_CERTIFICATE_VERIFY: ret = ssl_write_certificate_verify(ssl); break; case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: ret = mbedtls_ssl_write_change_cipher_spec(ssl); break; case MBEDTLS_SSL_CLIENT_FINISHED: ret = mbedtls_ssl_write_finished(ssl); break; /* * <== ( NewSessionTicket ) * ChangeCipherSpec * Finished */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_SSL_NEW_SESSION_TICKET: ret = ssl_parse_new_session_ticket(ssl); break; #endif case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: ret = mbedtls_ssl_parse_change_cipher_spec(ssl); break; case MBEDTLS_SSL_SERVER_FINISHED: ret = mbedtls_ssl_parse_finished(ssl); break; case MBEDTLS_SSL_FLUSH_BUFFERS: MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: mbedtls_ssl_handshake_wrapup(ssl); break; default: MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return ret; } #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_2 */ webfakes/src/mbedtls/library/aesni.h0000644000176200001440000001306114740737024017207 0ustar liggesusers/** * \file aesni.h * * \brief AES-NI for hardware AES acceleration on some Intel processors * * \warning These functions are only for internal use by other library * functions; you must not call them directly. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_AESNI_H #define MBEDTLS_AESNI_H #include "mbedtls/build_info.h" #include "mbedtls/aes.h" #define MBEDTLS_AESNI_AES 0x02000000u #define MBEDTLS_AESNI_CLMUL 0x00000002u #if defined(MBEDTLS_AESNI_C) && \ (defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_X86)) /* Can we do AESNI with intrinsics? * (Only implemented with certain compilers, only for certain targets.) */ #undef MBEDTLS_AESNI_HAVE_INTRINSICS #if defined(_MSC_VER) && !defined(__clang__) /* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support * VS 2013 and up for other reasons anyway, so no need to check the version. */ #define MBEDTLS_AESNI_HAVE_INTRINSICS #endif /* GCC-like compilers: currently, we only support intrinsics if the requisite * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2` * or `clang -maes -mpclmul`). */ #if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__) #define MBEDTLS_AESNI_HAVE_INTRINSICS #endif /* For 32-bit, we only support intrinsics */ #if defined(MBEDTLS_ARCH_IS_X86) && (defined(__GNUC__) || defined(__clang__)) #define MBEDTLS_AESNI_HAVE_INTRINSICS #endif /* Choose the implementation of AESNI, if one is available. * * Favor the intrinsics-based implementation if it's available, for better * maintainability. * Performance is about the same (see #7380). * In the long run, we will likely remove the assembly implementation. */ #if defined(MBEDTLS_AESNI_HAVE_INTRINSICS) #define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics #elif defined(MBEDTLS_HAVE_ASM) && \ (defined(__GNUC__) || defined(__clang__)) && defined(MBEDTLS_ARCH_IS_X64) /* Can we do AESNI with inline assembly? * (Only implemented with gas syntax, only for 64-bit.) */ #define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly #else #error "MBEDTLS_AESNI_C defined, but neither intrinsics nor assembly available" #endif #if defined(MBEDTLS_AESNI_HAVE_CODE) #ifdef __cplusplus extern "C" { #endif /** * \brief Internal function to detect the AES-NI feature in CPUs. * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param what The feature to detect * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) * * \return 1 if CPU has support for the feature, 0 otherwise */ #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) int mbedtls_aesni_has_support(unsigned int what); #else #define mbedtls_aesni_has_support(what) 1 #endif /** * \brief Internal AES-NI AES-ECB block encryption and decryption * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT * \param input 16-byte input block * \param output 16-byte output block * * \return 0 on success (cannot fail) */ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); /** * \brief Internal GCM multiplication: c = a * b in GF(2^128) * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param c Result * \param a First operand * \param b Second operand * * \note Both operands and result are bit strings interpreted as * elements of GF(2^128) as per the GCM spec. */ void mbedtls_aesni_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Internal round key inversion. This function computes * decryption round keys from the encryption round keys. * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param invkey Round keys for the equivalent inverse cipher * \param fwdkey Original round keys (for encryption) * \param nr Number of rounds (that is, number of round keys minus one) */ void mbedtls_aesni_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief Internal key expansion for encryption * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param rk Destination buffer where the round keys are written * \param key Encryption key * \param bits Key size in bits (must be 128, 192 or 256) * * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH */ int mbedtls_aesni_setkey_enc(unsigned char *rk, const unsigned char *key, size_t bits); #ifdef __cplusplus } #endif #endif /* MBEDTLS_AESNI_HAVE_CODE */ #endif /* MBEDTLS_AESNI_C && (MBEDTLS_ARCH_IS_X64 || MBEDTLS_ARCH_IS_X86) */ #endif /* MBEDTLS_AESNI_H */ webfakes/src/mbedtls/library/bignum_mod_raw.h0000644000176200001440000004622114740737024021105 0ustar liggesusers/** * Low-level modular bignum functions * * This interface should only be used by the higher-level modular bignum * module (bignum_mod.c) and the ECP module (ecp.c, ecp_curves.c). All other * modules should use the high-level modular bignum interface (bignum_mod.h) * or the legacy bignum interface (bignum.h). * * This is a low-level interface to operations on integers modulo which * has no protection against passing invalid arguments such as arrays of * the wrong size. The functions in bignum_mod.h provide a higher-level * interface that includes protections against accidental misuse, at the * expense of code size and sometimes more cumbersome memory management. * * The functions in this module obey the following conventions unless * explicitly indicated otherwise: * - **Modulus parameters**: the modulus is passed as a pointer to a structure * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an * array of limbs storing the bignum value of the modulus. The modulus must * be odd and is assumed to have no leading zeroes. The modulus is usually * named \c N and is usually input-only. * - **Bignum parameters**: Bignums are passed as pointers to an array of * limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified: * - Bignum parameters called \c A, \c B, ... are inputs, and are not * modified by the function. * - Bignum parameters called \c X, \c Y are outputs or input-output. * The initial content of output-only parameters is ignored. * - \c T is a temporary storage area. The initial content of such a * parameter is ignored and the final content is unspecified. * - **Bignum sizes**: bignum sizes are usually expressed by the \c limbs * member of the modulus argument. All bignum parameters must have the same * number of limbs as the modulus. All bignum sizes must be at least 1 and * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is * undefined. * - **Bignum representation**: the representation of inputs and outputs is * specified by the \c int_rep field of the modulus for arithmetic * functions. Utility functions may allow for different representation. * - **Parameter ordering**: for bignum parameters, outputs come before inputs. * The modulus is passed after other bignum input parameters. Temporaries * come last. * - **Aliasing**: in general, output bignums may be aliased to one or more * inputs. Modulus values may not be aliased to any other parameter. Outputs * may not be aliased to one another. Temporaries may not be aliased to any * other parameter. * - **Overlap**: apart from aliasing of limb array pointers (where two * arguments are equal pointers), overlap is not supported and may result * in undefined behavior. * - **Error handling**: This is a low-level module. Functions generally do not * try to protect against invalid arguments such as nonsensical sizes or * null pointers. Note that passing bignums with a different size than the * modulus may lead to buffer overflows. Some functions which allocate * memory or handle reading/writing of bignums will return an error if * memory allocation fails or if buffer sizes are invalid. * - **Modular representatives**: all functions expect inputs to be in the * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. If * an input is out of range, outputs are fully unspecified, though bignum * values out of range should not cause buffer overflows (beware that this is * not extensively tested). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_MOD_RAW_H #define MBEDTLS_BIGNUM_MOD_RAW_H #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif #include "bignum_mod.h" /** * \brief Perform a safe conditional copy of an MPI which doesn't reveal * whether the assignment was done or not. * * The size to copy is determined by \p N. * * \param[out] X The address of the destination MPI. * This must be initialized. Must have enough limbs to * store the full value of \p A. * \param[in] A The address of the source MPI. This must be initialized. * \param[in] N The address of the modulus related to \p X and \p A. * \param assign The condition deciding whether to perform the * assignment or not. Must be either 0 or 1: * * \c 1: Perform the assignment `X = A`. * * \c 0: Keep the original value of \p X. * * \note This function avoids leaking any information about whether * the assignment was done or not. * * \warning If \p assign is neither 0 nor 1, the result of this function * is indeterminate, and the resulting value in \p X might be * neither its original value nor the value in \p A. */ void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N, unsigned char assign); /** * \brief Perform a safe conditional swap of two MPIs which doesn't reveal * whether the swap was done or not. * * The size to swap is determined by \p N. * * \param[in,out] X The address of the first MPI. This must be initialized. * \param[in,out] Y The address of the second MPI. This must be initialized. * \param[in] N The address of the modulus related to \p X and \p Y. * \param swap The condition deciding whether to perform * the swap or not. Must be either 0 or 1: * * \c 1: Swap the values of \p X and \p Y. * * \c 0: Keep the original values of \p X and \p Y. * * \note This function avoids leaking any information about whether * the swap was done or not. * * \warning If \p swap is neither 0 nor 1, the result of this function * is indeterminate, and both \p X and \p Y might end up with * values different to either of the original ones. */ void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X, mbedtls_mpi_uint *Y, const mbedtls_mpi_mod_modulus *N, unsigned char swap); /** Import X from unsigned binary data. * * The MPI needs to have enough limbs to store the full value (including any * most significant zero bytes in the input). * * \param[out] X The address of the MPI. The size is determined by \p N. * (In particular, it must have at least as many limbs as * the modulus \p N.) * \param[in] N The address of the modulus related to \p X. * \param[in] input The input buffer to import from. * \param input_length The length in bytes of \p input. * \param ext_rep The endianness of the number in the input buffer. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't * large enough to hold the value in \p input. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation * of \p N is invalid or \p X is not less than \p N. */ int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N, const unsigned char *input, size_t input_length, mbedtls_mpi_mod_ext_rep ext_rep); /** Export A into unsigned binary data. * * \param[in] A The address of the MPI. The size is determined by \p N. * (In particular, it must have at least as many limbs as * the modulus \p N.) * \param[in] N The address of the modulus related to \p A. * \param[out] output The output buffer to export to. * \param output_length The length in bytes of \p output. * \param ext_rep The endianness in which the number should be written into the output buffer. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't * large enough to hold the value of \p A. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation * of \p N is invalid. */ int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N, unsigned char *output, size_t output_length, mbedtls_mpi_mod_ext_rep ext_rep); /** \brief Subtract two MPIs, returning the residue modulo the specified * modulus. * * The size of the operation is determined by \p N. \p A and \p B must have * the same number of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \param[out] X The address of the result MPI. * This must be initialized. Must have enough limbs to * store the full value of the result. * \param[in] A The address of the first MPI. This must be initialized. * \param[in] B The address of the second MPI. This must be initialized. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the subtraction. */ void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N); /** \brief Multiply two MPIs, returning the residue modulo the specified * modulus. * * \note Currently handles the case when `N->int_rep` is * MBEDTLS_MPI_MOD_REP_MONTGOMERY. * * The size of the operation is determined by \p N. \p A, \p B and \p X must * all be associated with the modulus \p N and must all have the same number * of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. They may not alias \p N (since they must be in canonical * form, they cannot == \p N). * * \param[out] X The address of the result MPI. Must have the same * number of limbs as \p N. * On successful completion, \p X contains the result of * the multiplication `A * B * R^-1` mod N where * `R = 2^(biL * N->limbs)`. * \param[in] A The address of the first MPI. * \param[in] B The address of the second MPI. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the multiplication. * \param[in,out] T Temporary storage of size at least 2 * N->limbs + 1 * limbs. Its initial content is unused and * its final content is indeterminate. * It must not alias or otherwise overlap any of the * other parameters. */ void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *T); /** * \brief Returns the number of limbs of working memory required for * a call to `mbedtls_mpi_mod_raw_inv_prime()`. * * \note This will always be at least * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`, * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`. * * \param AN_limbs The number of limbs in the input `A` and the modulus `N` * (they must be the same size) that will be given to * `mbedtls_mpi_mod_raw_inv_prime()`. * * \return The number of limbs of working memory required by * `mbedtls_mpi_mod_raw_inv_prime()`. */ size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs); /** * \brief Perform fixed-width modular inversion of a Montgomery-form MPI with * respect to a modulus \p N that must be prime. * * \p X may be aliased to \p A, but not to \p N or \p RR. * * \param[out] X The modular inverse of \p A with respect to \p N. * Will be in Montgomery form. * \param[in] A The number to calculate the modular inverse of. * Must be in Montgomery form. Must not be 0. * \param[in] N The modulus, as a little-endian array of length \p AN_limbs. * Must be prime. * \param AN_limbs The number of limbs in \p A, \p N and \p RR. * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little- * endian array of length \p AN_limbs. * \param[in,out] T Temporary storage of at least the number of limbs returned * by `mbedtls_mpi_mod_raw_inv_prime_working_limbs()`. * Its initial content is unused and its final content is * indeterminate. * It must not alias or otherwise overlap any of the other * parameters. * It is up to the caller to zeroize \p T when it is no * longer needed, and before freeing it if it was dynamically * allocated. */ void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T); /** * \brief Perform a known-size modular addition. * * Calculate `A + B modulo N`. * * The number of limbs in each operand, and the result, is given by the * modulus \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \param[out] X The result of the modular addition. * \param[in] A Little-endian presentation of the left operand. This * must be smaller than \p N. * \param[in] B Little-endian presentation of the right operand. This * must be smaller than \p N. * \param[in] N The address of the modulus. */ void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N); /** Convert an MPI from canonical representation (little-endian limb array) * to the representation associated with the modulus. * * \param[in,out] X The limb array to convert. * It must have as many limbs as \p N. * It is converted in place. * If this function returns an error, the content of \p X * is unspecified. * \param[in] N The modulus structure. * * \return \c 0 if successful. * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code. */ int mbedtls_mpi_mod_raw_canonical_to_modulus_rep( mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); /** Convert an MPI from the representation associated with the modulus * to canonical representation (little-endian limb array). * * \param[in,out] X The limb array to convert. * It must have as many limbs as \p N. * It is converted in place. * If this function returns an error, the content of \p X * is unspecified. * \param[in] N The modulus structure. * * \return \c 0 if successful. * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code. */ int mbedtls_mpi_mod_raw_modulus_to_canonical_rep( mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); /** Generate a random number uniformly in a range. * * This function generates a random number between \p min inclusive and * \p N exclusive. * * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) * when the RNG is a suitably parametrized instance of HMAC_DRBG * and \p min is \c 1. * * \note There are `N - min` possible outputs. The lower bound * \p min can be reached, but the upper bound \p N cannot. * * \param X The destination MPI, in canonical representation modulo \p N. * It must not be aliased with \p N or otherwise overlap it. * \param min The minimum value to return. It must be strictly smaller * than \b N. * \param N The modulus. * This is the upper bound of the output range, exclusive. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was * unable to find a suitable value within a limited number * of attempts. This has a negligible probability if \p N * is significantly larger than \p min, which is the case * for all usual cryptographic applications. */ int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X, mbedtls_mpi_uint min, const mbedtls_mpi_mod_modulus *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Convert an MPI into Montgomery form. * * \param X The address of the MPI. * Must have the same number of limbs as \p N. * \param N The address of the modulus, which gives the size of * the base `R` = 2^(biL*N->limbs). * * \return \c 0 if successful. */ int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); /** Convert an MPI back from Montgomery representation. * * \param X The address of the MPI. * Must have the same number of limbs as \p N. * \param N The address of the modulus, which gives the size of * the base `R`= 2^(biL*N->limbs). * * \return \c 0 if successful. */ int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); /** \brief Perform fixed width modular negation. * * The size of the operation is determined by \p N. \p A must have * the same number of limbs as \p N. * * \p X may be aliased to \p A. * * \param[out] X The result of the modular negation. * This must be initialized. * \param[in] A Little-endian presentation of the input operand. This * must be less than or equal to \p N. * \param[in] N The modulus to use. */ void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N); #endif /* MBEDTLS_BIGNUM_MOD_RAW_H */ webfakes/src/mbedtls/library/ripemd160.c0000644000176200001440000003753114740737024017622 0ustar liggesusers/* * RIPE MD-160 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The RIPEMD-160 algorithm was designed by RIPE in 1996 * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 */ #include "common.h" #if defined(MBEDTLS_RIPEMD160_C) #include "mbedtls/ripemd160.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_RIPEMD160_ALT) void mbedtls_ripemd160_init(mbedtls_ripemd160_context *ctx) { memset(ctx, 0, sizeof(mbedtls_ripemd160_context)); } void mbedtls_ripemd160_free(mbedtls_ripemd160_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ripemd160_context)); } void mbedtls_ripemd160_clone(mbedtls_ripemd160_context *dst, const mbedtls_ripemd160_context *src) { *dst = *src; } /* * RIPEMD-160 context setup */ int mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; return 0; } #if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) /* * Process one block */ int mbedtls_internal_ripemd160_process(mbedtls_ripemd160_context *ctx, const unsigned char data[64]) { struct { uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; } local; local.X[0] = MBEDTLS_GET_UINT32_LE(data, 0); local.X[1] = MBEDTLS_GET_UINT32_LE(data, 4); local.X[2] = MBEDTLS_GET_UINT32_LE(data, 8); local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12); local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16); local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20); local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24); local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28); local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32); local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36); local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40); local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44); local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48); local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52); local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56); local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60); local.A = local.Ap = ctx->state[0]; local.B = local.Bp = ctx->state[1]; local.C = local.Cp = ctx->state[2]; local.D = local.Dp = ctx->state[3]; local.E = local.Ep = ctx->state[4]; #define F1(x, y, z) ((x) ^ (y) ^ (z)) #define F2(x, y, z) (((x) & (y)) | (~(x) & (z))) #define F3(x, y, z) (((x) | ~(y)) ^ (z)) #define F4(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define F5(x, y, z) ((x) ^ ((y) | ~(z))) #define S(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define P(a, b, c, d, e, r, s, f, k) \ do \ { \ (a) += f((b), (c), (d)) + local.X[r] + (k); \ (a) = S((a), (s)) + (e); \ (c) = S((c), 10); \ } while (0) #define P2(a, b, c, d, e, r, s, rp, sp) \ do \ { \ P((a), (b), (c), (d), (e), (r), (s), F, K); \ P(a ## p, b ## p, c ## p, d ## p, e ## p, \ (rp), (sp), Fp, Kp); \ } while (0) #define F F1 #define K 0x00000000 #define Fp F5 #define Kp 0x50A28BE6 P2(local.A, local.B, local.C, local.D, local.E, 0, 11, 5, 8); P2(local.E, local.A, local.B, local.C, local.D, 1, 14, 14, 9); P2(local.D, local.E, local.A, local.B, local.C, 2, 15, 7, 9); P2(local.C, local.D, local.E, local.A, local.B, 3, 12, 0, 11); P2(local.B, local.C, local.D, local.E, local.A, 4, 5, 9, 13); P2(local.A, local.B, local.C, local.D, local.E, 5, 8, 2, 15); P2(local.E, local.A, local.B, local.C, local.D, 6, 7, 11, 15); P2(local.D, local.E, local.A, local.B, local.C, 7, 9, 4, 5); P2(local.C, local.D, local.E, local.A, local.B, 8, 11, 13, 7); P2(local.B, local.C, local.D, local.E, local.A, 9, 13, 6, 7); P2(local.A, local.B, local.C, local.D, local.E, 10, 14, 15, 8); P2(local.E, local.A, local.B, local.C, local.D, 11, 15, 8, 11); P2(local.D, local.E, local.A, local.B, local.C, 12, 6, 1, 14); P2(local.C, local.D, local.E, local.A, local.B, 13, 7, 10, 14); P2(local.B, local.C, local.D, local.E, local.A, 14, 9, 3, 12); P2(local.A, local.B, local.C, local.D, local.E, 15, 8, 12, 6); #undef F #undef K #undef Fp #undef Kp #define F F2 #define K 0x5A827999 #define Fp F4 #define Kp 0x5C4DD124 P2(local.E, local.A, local.B, local.C, local.D, 7, 7, 6, 9); P2(local.D, local.E, local.A, local.B, local.C, 4, 6, 11, 13); P2(local.C, local.D, local.E, local.A, local.B, 13, 8, 3, 15); P2(local.B, local.C, local.D, local.E, local.A, 1, 13, 7, 7); P2(local.A, local.B, local.C, local.D, local.E, 10, 11, 0, 12); P2(local.E, local.A, local.B, local.C, local.D, 6, 9, 13, 8); P2(local.D, local.E, local.A, local.B, local.C, 15, 7, 5, 9); P2(local.C, local.D, local.E, local.A, local.B, 3, 15, 10, 11); P2(local.B, local.C, local.D, local.E, local.A, 12, 7, 14, 7); P2(local.A, local.B, local.C, local.D, local.E, 0, 12, 15, 7); P2(local.E, local.A, local.B, local.C, local.D, 9, 15, 8, 12); P2(local.D, local.E, local.A, local.B, local.C, 5, 9, 12, 7); P2(local.C, local.D, local.E, local.A, local.B, 2, 11, 4, 6); P2(local.B, local.C, local.D, local.E, local.A, 14, 7, 9, 15); P2(local.A, local.B, local.C, local.D, local.E, 11, 13, 1, 13); P2(local.E, local.A, local.B, local.C, local.D, 8, 12, 2, 11); #undef F #undef K #undef Fp #undef Kp #define F F3 #define K 0x6ED9EBA1 #define Fp F3 #define Kp 0x6D703EF3 P2(local.D, local.E, local.A, local.B, local.C, 3, 11, 15, 9); P2(local.C, local.D, local.E, local.A, local.B, 10, 13, 5, 7); P2(local.B, local.C, local.D, local.E, local.A, 14, 6, 1, 15); P2(local.A, local.B, local.C, local.D, local.E, 4, 7, 3, 11); P2(local.E, local.A, local.B, local.C, local.D, 9, 14, 7, 8); P2(local.D, local.E, local.A, local.B, local.C, 15, 9, 14, 6); P2(local.C, local.D, local.E, local.A, local.B, 8, 13, 6, 6); P2(local.B, local.C, local.D, local.E, local.A, 1, 15, 9, 14); P2(local.A, local.B, local.C, local.D, local.E, 2, 14, 11, 12); P2(local.E, local.A, local.B, local.C, local.D, 7, 8, 8, 13); P2(local.D, local.E, local.A, local.B, local.C, 0, 13, 12, 5); P2(local.C, local.D, local.E, local.A, local.B, 6, 6, 2, 14); P2(local.B, local.C, local.D, local.E, local.A, 13, 5, 10, 13); P2(local.A, local.B, local.C, local.D, local.E, 11, 12, 0, 13); P2(local.E, local.A, local.B, local.C, local.D, 5, 7, 4, 7); P2(local.D, local.E, local.A, local.B, local.C, 12, 5, 13, 5); #undef F #undef K #undef Fp #undef Kp #define F F4 #define K 0x8F1BBCDC #define Fp F2 #define Kp 0x7A6D76E9 P2(local.C, local.D, local.E, local.A, local.B, 1, 11, 8, 15); P2(local.B, local.C, local.D, local.E, local.A, 9, 12, 6, 5); P2(local.A, local.B, local.C, local.D, local.E, 11, 14, 4, 8); P2(local.E, local.A, local.B, local.C, local.D, 10, 15, 1, 11); P2(local.D, local.E, local.A, local.B, local.C, 0, 14, 3, 14); P2(local.C, local.D, local.E, local.A, local.B, 8, 15, 11, 14); P2(local.B, local.C, local.D, local.E, local.A, 12, 9, 15, 6); P2(local.A, local.B, local.C, local.D, local.E, 4, 8, 0, 14); P2(local.E, local.A, local.B, local.C, local.D, 13, 9, 5, 6); P2(local.D, local.E, local.A, local.B, local.C, 3, 14, 12, 9); P2(local.C, local.D, local.E, local.A, local.B, 7, 5, 2, 12); P2(local.B, local.C, local.D, local.E, local.A, 15, 6, 13, 9); P2(local.A, local.B, local.C, local.D, local.E, 14, 8, 9, 12); P2(local.E, local.A, local.B, local.C, local.D, 5, 6, 7, 5); P2(local.D, local.E, local.A, local.B, local.C, 6, 5, 10, 15); P2(local.C, local.D, local.E, local.A, local.B, 2, 12, 14, 8); #undef F #undef K #undef Fp #undef Kp #define F F5 #define K 0xA953FD4E #define Fp F1 #define Kp 0x00000000 P2(local.B, local.C, local.D, local.E, local.A, 4, 9, 12, 8); P2(local.A, local.B, local.C, local.D, local.E, 0, 15, 15, 5); P2(local.E, local.A, local.B, local.C, local.D, 5, 5, 10, 12); P2(local.D, local.E, local.A, local.B, local.C, 9, 11, 4, 9); P2(local.C, local.D, local.E, local.A, local.B, 7, 6, 1, 12); P2(local.B, local.C, local.D, local.E, local.A, 12, 8, 5, 5); P2(local.A, local.B, local.C, local.D, local.E, 2, 13, 8, 14); P2(local.E, local.A, local.B, local.C, local.D, 10, 12, 7, 6); P2(local.D, local.E, local.A, local.B, local.C, 14, 5, 6, 8); P2(local.C, local.D, local.E, local.A, local.B, 1, 12, 2, 13); P2(local.B, local.C, local.D, local.E, local.A, 3, 13, 13, 6); P2(local.A, local.B, local.C, local.D, local.E, 8, 14, 14, 5); P2(local.E, local.A, local.B, local.C, local.D, 11, 11, 0, 15); P2(local.D, local.E, local.A, local.B, local.C, 6, 8, 3, 13); P2(local.C, local.D, local.E, local.A, local.B, 15, 5, 9, 11); P2(local.B, local.C, local.D, local.E, local.A, 13, 6, 11, 11); #undef F #undef K #undef Fp #undef Kp local.C = ctx->state[1] + local.C + local.Dp; ctx->state[1] = ctx->state[2] + local.D + local.Ep; ctx->state[2] = ctx->state[3] + local.E + local.Ap; ctx->state[3] = ctx->state[4] + local.A + local.Bp; ctx->state[4] = ctx->state[0] + local.B + local.Cp; ctx->state[0] = local.C; /* Zeroise variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ /* * RIPEMD-160 process buffer */ int mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; if (ilen == 0) { return 0; } left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if (ctx->total[0] < (uint32_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_ripemd160_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= 64) { if ((ret = mbedtls_internal_ripemd160_process(ctx, input)) != 0) { return ret; } input += 64; ilen -= 64; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } static const unsigned char ripemd160_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * RIPEMD-160 final digest */ int mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx, unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); MBEDTLS_PUT_UINT32_LE(low, msglen, 0); MBEDTLS_PUT_UINT32_LE(high, msglen, 4); last = ctx->total[0] & 0x3F; padn = (last < 56) ? (56 - last) : (120 - last); ret = mbedtls_ripemd160_update(ctx, ripemd160_padding, padn); if (ret != 0) { goto exit; } ret = mbedtls_ripemd160_update(ctx, msglen, 8); if (ret != 0) { goto exit; } MBEDTLS_PUT_UINT32_LE(ctx->state[0], output, 0); MBEDTLS_PUT_UINT32_LE(ctx->state[1], output, 4); MBEDTLS_PUT_UINT32_LE(ctx->state[2], output, 8); MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12); MBEDTLS_PUT_UINT32_LE(ctx->state[4], output, 16); ret = 0; exit: mbedtls_ripemd160_free(ctx); return ret; } #endif /* ! MBEDTLS_RIPEMD160_ALT */ /* * output = RIPEMD-160( input buffer ) */ int mbedtls_ripemd160(const unsigned char *input, size_t ilen, unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ripemd160_context ctx; mbedtls_ripemd160_init(&ctx); if ((ret = mbedtls_ripemd160_starts(&ctx)) != 0) { goto exit; } if ((ret = mbedtls_ripemd160_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_ripemd160_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_ripemd160_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * Test vectors from the RIPEMD-160 paper and * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC */ #define TESTS 8 static const unsigned char ripemd160_test_str[TESTS][81] = { { "" }, { "a" }, { "abc" }, { "message digest" }, { "abcdefghijklmnopqrstuvwxyz" }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }, }; static const size_t ripemd160_test_strlen[TESTS] = { 0, 1, 3, 14, 26, 56, 62, 80 }; static const unsigned char ripemd160_test_md[TESTS][20] = { { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, }; /* * Checkup routine */ int mbedtls_ripemd160_self_test(int verbose) { int i, ret = 0; unsigned char output[20]; memset(output, 0, sizeof(output)); for (i = 0; i < TESTS; i++) { if (verbose != 0) { mbedtls_printf(" RIPEMD-160 test #%d: ", i + 1); } ret = mbedtls_ripemd160(ripemd160_test_str[i], ripemd160_test_strlen[i], output); if (ret != 0) { goto fail; } if (memcmp(output, ripemd160_test_md[i], 20) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_RIPEMD160_C */ webfakes/src/mbedtls/library/ctr.h0000644000176200001440000000166314740737024016705 0ustar liggesusers/** * \file ctr.h * * \brief This file contains common functionality for counter algorithms. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CTR_H #define MBEDTLS_CTR_H #include "common.h" /** * \brief Increment a big-endian 16-byte value. * This is quite performance-sensitive for AES-CTR and CTR-DRBG. * * \param n A 16-byte value to be incremented. */ static inline void mbedtls_ctr_increment_counter(uint8_t n[16]) { // The 32-bit version seems to perform about the same as a 64-bit version // on 64-bit architectures, so no need to define a 64-bit version. for (int i = 3;; i--) { uint32_t x = MBEDTLS_GET_UINT32_BE(n, i << 2); x += 1; MBEDTLS_PUT_UINT32_BE(x, n, i << 2); if (x != 0 || i == 0) { break; } } } #endif /* MBEDTLS_CTR_H */ webfakes/src/mbedtls/library/sha1.c0000644000176200001440000003355514740737024016751 0ustar liggesusers/* * FIPS-180-1 compliant SHA-1 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-1 standard was published by NIST in 1993. * * http://www.itl.nist.gov/fipspubs/fip180-1.htm */ #include "common.h" #if defined(MBEDTLS_SHA1_C) #include "mbedtls/sha1.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_SHA1_ALT) void mbedtls_sha1_init(mbedtls_sha1_context *ctx) { memset(ctx, 0, sizeof(mbedtls_sha1_context)); } void mbedtls_sha1_free(mbedtls_sha1_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha1_context)); } void mbedtls_sha1_clone(mbedtls_sha1_context *dst, const mbedtls_sha1_context *src) { *dst = *src; } /* * SHA-1 context setup */ int mbedtls_sha1_starts(mbedtls_sha1_context *ctx) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; return 0; } #if !defined(MBEDTLS_SHA1_PROCESS_ALT) int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64]) { struct { uint32_t temp, W[16], A, B, C, D, E; } local; local.W[0] = MBEDTLS_GET_UINT32_BE(data, 0); local.W[1] = MBEDTLS_GET_UINT32_BE(data, 4); local.W[2] = MBEDTLS_GET_UINT32_BE(data, 8); local.W[3] = MBEDTLS_GET_UINT32_BE(data, 12); local.W[4] = MBEDTLS_GET_UINT32_BE(data, 16); local.W[5] = MBEDTLS_GET_UINT32_BE(data, 20); local.W[6] = MBEDTLS_GET_UINT32_BE(data, 24); local.W[7] = MBEDTLS_GET_UINT32_BE(data, 28); local.W[8] = MBEDTLS_GET_UINT32_BE(data, 32); local.W[9] = MBEDTLS_GET_UINT32_BE(data, 36); local.W[10] = MBEDTLS_GET_UINT32_BE(data, 40); local.W[11] = MBEDTLS_GET_UINT32_BE(data, 44); local.W[12] = MBEDTLS_GET_UINT32_BE(data, 48); local.W[13] = MBEDTLS_GET_UINT32_BE(data, 52); local.W[14] = MBEDTLS_GET_UINT32_BE(data, 56); local.W[15] = MBEDTLS_GET_UINT32_BE(data, 60); #define S(x, n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) #define R(t) \ ( \ local.temp = local.W[((t) - 3) & 0x0F] ^ \ local.W[((t) - 8) & 0x0F] ^ \ local.W[((t) - 14) & 0x0F] ^ \ local.W[(t) & 0x0F], \ (local.W[(t) & 0x0F] = S(local.temp, 1)) \ ) #define P(a, b, c, d, e, x) \ do \ { \ (e) += S((a), 5) + F((b), (c), (d)) + K + (x); \ (b) = S((b), 30); \ } while (0) local.A = ctx->state[0]; local.B = ctx->state[1]; local.C = ctx->state[2]; local.D = ctx->state[3]; local.E = ctx->state[4]; #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define K 0x5A827999 P(local.A, local.B, local.C, local.D, local.E, local.W[0]); P(local.E, local.A, local.B, local.C, local.D, local.W[1]); P(local.D, local.E, local.A, local.B, local.C, local.W[2]); P(local.C, local.D, local.E, local.A, local.B, local.W[3]); P(local.B, local.C, local.D, local.E, local.A, local.W[4]); P(local.A, local.B, local.C, local.D, local.E, local.W[5]); P(local.E, local.A, local.B, local.C, local.D, local.W[6]); P(local.D, local.E, local.A, local.B, local.C, local.W[7]); P(local.C, local.D, local.E, local.A, local.B, local.W[8]); P(local.B, local.C, local.D, local.E, local.A, local.W[9]); P(local.A, local.B, local.C, local.D, local.E, local.W[10]); P(local.E, local.A, local.B, local.C, local.D, local.W[11]); P(local.D, local.E, local.A, local.B, local.C, local.W[12]); P(local.C, local.D, local.E, local.A, local.B, local.W[13]); P(local.B, local.C, local.D, local.E, local.A, local.W[14]); P(local.A, local.B, local.C, local.D, local.E, local.W[15]); P(local.E, local.A, local.B, local.C, local.D, R(16)); P(local.D, local.E, local.A, local.B, local.C, R(17)); P(local.C, local.D, local.E, local.A, local.B, R(18)); P(local.B, local.C, local.D, local.E, local.A, R(19)); #undef K #undef F #define F(x, y, z) ((x) ^ (y) ^ (z)) #define K 0x6ED9EBA1 P(local.A, local.B, local.C, local.D, local.E, R(20)); P(local.E, local.A, local.B, local.C, local.D, R(21)); P(local.D, local.E, local.A, local.B, local.C, R(22)); P(local.C, local.D, local.E, local.A, local.B, R(23)); P(local.B, local.C, local.D, local.E, local.A, R(24)); P(local.A, local.B, local.C, local.D, local.E, R(25)); P(local.E, local.A, local.B, local.C, local.D, R(26)); P(local.D, local.E, local.A, local.B, local.C, R(27)); P(local.C, local.D, local.E, local.A, local.B, R(28)); P(local.B, local.C, local.D, local.E, local.A, R(29)); P(local.A, local.B, local.C, local.D, local.E, R(30)); P(local.E, local.A, local.B, local.C, local.D, R(31)); P(local.D, local.E, local.A, local.B, local.C, R(32)); P(local.C, local.D, local.E, local.A, local.B, R(33)); P(local.B, local.C, local.D, local.E, local.A, R(34)); P(local.A, local.B, local.C, local.D, local.E, R(35)); P(local.E, local.A, local.B, local.C, local.D, R(36)); P(local.D, local.E, local.A, local.B, local.C, R(37)); P(local.C, local.D, local.E, local.A, local.B, R(38)); P(local.B, local.C, local.D, local.E, local.A, R(39)); #undef K #undef F #define F(x, y, z) (((x) & (y)) | ((z) & ((x) | (y)))) #define K 0x8F1BBCDC P(local.A, local.B, local.C, local.D, local.E, R(40)); P(local.E, local.A, local.B, local.C, local.D, R(41)); P(local.D, local.E, local.A, local.B, local.C, R(42)); P(local.C, local.D, local.E, local.A, local.B, R(43)); P(local.B, local.C, local.D, local.E, local.A, R(44)); P(local.A, local.B, local.C, local.D, local.E, R(45)); P(local.E, local.A, local.B, local.C, local.D, R(46)); P(local.D, local.E, local.A, local.B, local.C, R(47)); P(local.C, local.D, local.E, local.A, local.B, R(48)); P(local.B, local.C, local.D, local.E, local.A, R(49)); P(local.A, local.B, local.C, local.D, local.E, R(50)); P(local.E, local.A, local.B, local.C, local.D, R(51)); P(local.D, local.E, local.A, local.B, local.C, R(52)); P(local.C, local.D, local.E, local.A, local.B, R(53)); P(local.B, local.C, local.D, local.E, local.A, R(54)); P(local.A, local.B, local.C, local.D, local.E, R(55)); P(local.E, local.A, local.B, local.C, local.D, R(56)); P(local.D, local.E, local.A, local.B, local.C, R(57)); P(local.C, local.D, local.E, local.A, local.B, R(58)); P(local.B, local.C, local.D, local.E, local.A, R(59)); #undef K #undef F #define F(x, y, z) ((x) ^ (y) ^ (z)) #define K 0xCA62C1D6 P(local.A, local.B, local.C, local.D, local.E, R(60)); P(local.E, local.A, local.B, local.C, local.D, R(61)); P(local.D, local.E, local.A, local.B, local.C, R(62)); P(local.C, local.D, local.E, local.A, local.B, R(63)); P(local.B, local.C, local.D, local.E, local.A, R(64)); P(local.A, local.B, local.C, local.D, local.E, R(65)); P(local.E, local.A, local.B, local.C, local.D, R(66)); P(local.D, local.E, local.A, local.B, local.C, R(67)); P(local.C, local.D, local.E, local.A, local.B, R(68)); P(local.B, local.C, local.D, local.E, local.A, R(69)); P(local.A, local.B, local.C, local.D, local.E, R(70)); P(local.E, local.A, local.B, local.C, local.D, R(71)); P(local.D, local.E, local.A, local.B, local.C, R(72)); P(local.C, local.D, local.E, local.A, local.B, R(73)); P(local.B, local.C, local.D, local.E, local.A, R(74)); P(local.A, local.B, local.C, local.D, local.E, R(75)); P(local.E, local.A, local.B, local.C, local.D, R(76)); P(local.D, local.E, local.A, local.B, local.C, R(77)); P(local.C, local.D, local.E, local.A, local.B, R(78)); P(local.B, local.C, local.D, local.E, local.A, R(79)); #undef K #undef F ctx->state[0] += local.A; ctx->state[1] += local.B; ctx->state[2] += local.C; ctx->state[3] += local.D; ctx->state[4] += local.E; /* Zeroise buffers and variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_SHA1_PROCESS_ALT */ /* * SHA-1 process buffer */ int mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; if (ilen == 0) { return 0; } left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if (ctx->total[0] < (uint32_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= 64) { if ((ret = mbedtls_internal_sha1_process(ctx, input)) != 0) { return ret; } input += 64; ilen -= 64; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } /* * SHA-1 final digest */ int mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t used; uint32_t high, low; /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ used = ctx->total[0] & 0x3F; ctx->buffer[used++] = 0x80; if (used <= 56) { /* Enough room for padding + length in current block */ memset(ctx->buffer + used, 0, 56 - used); } else { /* We'll need an extra block */ memset(ctx->buffer + used, 0, 64 - used); if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { goto exit; } memset(ctx->buffer, 0, 56); } /* * Add message length */ high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56); MBEDTLS_PUT_UINT32_BE(low, ctx->buffer, 60); if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { goto exit; } /* * Output final state */ MBEDTLS_PUT_UINT32_BE(ctx->state[0], output, 0); MBEDTLS_PUT_UINT32_BE(ctx->state[1], output, 4); MBEDTLS_PUT_UINT32_BE(ctx->state[2], output, 8); MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12); MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16); ret = 0; exit: mbedtls_sha1_free(ctx); return ret; } #endif /* !MBEDTLS_SHA1_ALT */ /* * output = SHA-1( input buffer ) */ int mbedtls_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha1_context ctx; mbedtls_sha1_init(&ctx); if ((ret = mbedtls_sha1_starts(&ctx)) != 0) { goto exit; } if ((ret = mbedtls_sha1_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_sha1_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_sha1_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-1 test vectors */ static const unsigned char sha1_test_buf[3][57] = { { "abc" }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { "" } }; static const size_t sha1_test_buflen[3] = { 3, 56, 1000 }; static const unsigned char sha1_test_sum[3][20] = { { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } }; /* * Checkup routine */ int mbedtls_sha1_self_test(int verbose) { int i, j, buflen, ret = 0; unsigned char buf[1024]; unsigned char sha1sum[20]; mbedtls_sha1_context ctx; mbedtls_sha1_init(&ctx); /* * SHA-1 */ for (i = 0; i < 3; i++) { if (verbose != 0) { mbedtls_printf(" SHA-1 test #%d: ", i + 1); } if ((ret = mbedtls_sha1_starts(&ctx)) != 0) { goto fail; } if (i == 2) { memset(buf, 'a', buflen = 1000); for (j = 0; j < 1000; j++) { ret = mbedtls_sha1_update(&ctx, buf, buflen); if (ret != 0) { goto fail; } } } else { ret = mbedtls_sha1_update(&ctx, sha1_test_buf[i], sha1_test_buflen[i]); if (ret != 0) { goto fail; } } if ((ret = mbedtls_sha1_finish(&ctx, sha1sum)) != 0) { goto fail; } if (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } goto exit; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } exit: mbedtls_sha1_free(&ctx); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SHA1_C */ webfakes/src/mbedtls/library/bn_mul.h0000644000176200001440000012724214740737024017373 0ustar liggesusers/** * \file bn_mul.h * * \brief Multi-precision integer library */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Multiply source vector [s] with b, add result * to destination vector [d] and set carry c. * * Currently supports: * * . IA-32 (386+) . AMD64 / EM64T * . IA-32 (SSE2) . Motorola 68000 * . PowerPC, 32-bit . MicroBlaze * . PowerPC, 64-bit . TriCore * . SPARC v8 . ARM v3+ * . Alpha . MIPS32 * . C, longlong . C, generic */ #ifndef MBEDTLS_BN_MUL_H #define MBEDTLS_BN_MUL_H #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" /* * Conversion macros for embedded constants: * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 */ #if defined(MBEDTLS_HAVE_INT32) #define MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d) \ ((mbedtls_mpi_uint) (a) << 0) | \ ((mbedtls_mpi_uint) (b) << 8) | \ ((mbedtls_mpi_uint) (c) << 16) | \ ((mbedtls_mpi_uint) (d) << 24) #define MBEDTLS_BYTES_TO_T_UINT_2(a, b) \ MBEDTLS_BYTES_TO_T_UINT_4(a, b, 0, 0) #define MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, e, f, g, h) \ MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d), \ MBEDTLS_BYTES_TO_T_UINT_4(e, f, g, h) #else /* 64-bits */ #define MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, e, f, g, h) \ ((mbedtls_mpi_uint) (a) << 0) | \ ((mbedtls_mpi_uint) (b) << 8) | \ ((mbedtls_mpi_uint) (c) << 16) | \ ((mbedtls_mpi_uint) (d) << 24) | \ ((mbedtls_mpi_uint) (e) << 32) | \ ((mbedtls_mpi_uint) (f) << 40) | \ ((mbedtls_mpi_uint) (g) << 48) | \ ((mbedtls_mpi_uint) (h) << 56) #define MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d) \ MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, 0, 0, 0, 0) #define MBEDTLS_BYTES_TO_T_UINT_2(a, b) \ MBEDTLS_BYTES_TO_T_UINT_8(a, b, 0, 0, 0, 0, 0, 0) #endif /* bits in mbedtls_mpi_uint */ /* *INDENT-OFF* */ #if defined(MBEDTLS_HAVE_ASM) /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(__GNUC__) && \ ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) /* * GCC < 5.0 treated the x86 ebx (which is used for the GOT) as a * fixed reserved register when building as PIC, leading to errors * like: bn_mul.h:46:13: error: PIC register clobbered by 'ebx' in 'asm' * * This is fixed by an improved register allocator in GCC 5+. From the * release notes: * Register allocation improvements: Reuse of the PIC hard register, * instead of using a fixed register, was implemented on x86/x86-64 * targets. This improves generated PIC code performance as more hard * registers can be used. */ #if defined(__GNUC__) && __GNUC__ < 5 && defined(__PIC__) #define MULADDC_CANNOT_USE_EBX #endif /* * Disable use of the i386 assembly code below if option -O0, to disable all * compiler optimisations, is passed, detected with __OPTIMIZE__ * This is done as the number of registers used in the assembly code doesn't * work with the -O0 option. */ #if defined(__i386__) && defined(__OPTIMIZE__) && !defined(MULADDC_CANNOT_USE_EBX) #define MULADDC_X1_INIT \ { mbedtls_mpi_uint t; \ asm( \ "movl %%ebx, %0 \n\t" \ "movl %5, %%esi \n\t" \ "movl %6, %%edi \n\t" \ "movl %7, %%ecx \n\t" \ "movl %8, %%ebx \n\t" #define MULADDC_X1_CORE \ "lodsl \n\t" \ "mull %%ebx \n\t" \ "addl %%ecx, %%eax \n\t" \ "adcl $0, %%edx \n\t" \ "addl (%%edi), %%eax \n\t" \ "adcl $0, %%edx \n\t" \ "movl %%edx, %%ecx \n\t" \ "stosl \n\t" #define MULADDC_X1_STOP \ "movl %4, %%ebx \n\t" \ "movl %%ecx, %1 \n\t" \ "movl %%edi, %2 \n\t" \ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); } #if defined(MBEDTLS_HAVE_SSE2) #define MULADDC_X8_INIT MULADDC_X1_INIT #define MULADDC_X8_CORE \ "movd %%ecx, %%mm1 \n\t" \ "movd %%ebx, %%mm0 \n\t" \ "movd (%%edi), %%mm3 \n\t" \ "paddq %%mm3, %%mm1 \n\t" \ "movd (%%esi), %%mm2 \n\t" \ "pmuludq %%mm0, %%mm2 \n\t" \ "movd 4(%%esi), %%mm4 \n\t" \ "pmuludq %%mm0, %%mm4 \n\t" \ "movd 8(%%esi), %%mm6 \n\t" \ "pmuludq %%mm0, %%mm6 \n\t" \ "movd 12(%%esi), %%mm7 \n\t" \ "pmuludq %%mm0, %%mm7 \n\t" \ "paddq %%mm2, %%mm1 \n\t" \ "movd 4(%%edi), %%mm3 \n\t" \ "paddq %%mm4, %%mm3 \n\t" \ "movd 8(%%edi), %%mm5 \n\t" \ "paddq %%mm6, %%mm5 \n\t" \ "movd 12(%%edi), %%mm4 \n\t" \ "paddq %%mm4, %%mm7 \n\t" \ "movd %%mm1, (%%edi) \n\t" \ "movd 16(%%esi), %%mm2 \n\t" \ "pmuludq %%mm0, %%mm2 \n\t" \ "psrlq $32, %%mm1 \n\t" \ "movd 20(%%esi), %%mm4 \n\t" \ "pmuludq %%mm0, %%mm4 \n\t" \ "paddq %%mm3, %%mm1 \n\t" \ "movd 24(%%esi), %%mm6 \n\t" \ "pmuludq %%mm0, %%mm6 \n\t" \ "movd %%mm1, 4(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "movd 28(%%esi), %%mm3 \n\t" \ "pmuludq %%mm0, %%mm3 \n\t" \ "paddq %%mm5, %%mm1 \n\t" \ "movd 16(%%edi), %%mm5 \n\t" \ "paddq %%mm5, %%mm2 \n\t" \ "movd %%mm1, 8(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm7, %%mm1 \n\t" \ "movd 20(%%edi), %%mm5 \n\t" \ "paddq %%mm5, %%mm4 \n\t" \ "movd %%mm1, 12(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm2, %%mm1 \n\t" \ "movd 24(%%edi), %%mm5 \n\t" \ "paddq %%mm5, %%mm6 \n\t" \ "movd %%mm1, 16(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm4, %%mm1 \n\t" \ "movd 28(%%edi), %%mm5 \n\t" \ "paddq %%mm5, %%mm3 \n\t" \ "movd %%mm1, 20(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm6, %%mm1 \n\t" \ "movd %%mm1, 24(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm3, %%mm1 \n\t" \ "movd %%mm1, 28(%%edi) \n\t" \ "addl $32, %%edi \n\t" \ "addl $32, %%esi \n\t" \ "psrlq $32, %%mm1 \n\t" \ "movd %%mm1, %%ecx \n\t" #define MULADDC_X8_STOP \ "emms \n\t" \ "movl %4, %%ebx \n\t" \ "movl %%ecx, %1 \n\t" \ "movl %%edi, %2 \n\t" \ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); } \ #endif /* SSE2 */ #endif /* i386 */ #if defined(__amd64__) || defined (__x86_64__) #define MULADDC_X1_INIT \ asm( \ "xorq %%r8, %%r8\n" #define MULADDC_X1_CORE \ "movq (%%rsi), %%rax\n" \ "mulq %%rbx\n" \ "addq $8, %%rsi\n" \ "addq %%rcx, %%rax\n" \ "movq %%r8, %%rcx\n" \ "adcq $0, %%rdx\n" \ "nop \n" \ "addq %%rax, (%%rdi)\n" \ "adcq %%rdx, %%rcx\n" \ "addq $8, %%rdi\n" #define MULADDC_X1_STOP \ : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \ : "b" (b), "m" (*(const uint64_t (*)[16]) s) \ : "rax", "rdx", "r8" \ ); #endif /* AMD64 */ // The following assembly code assumes that a pointer will fit in a 64-bit register // (including ILP32 __aarch64__ ABIs such as on watchOS, hence the 2^32 - 1) #if defined(__aarch64__) && (UINTPTR_MAX == 0xfffffffful || UINTPTR_MAX == 0xfffffffffffffffful) /* * There are some issues around different compilers requiring different constraint * syntax for updating pointers from assembly code (see notes for * MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT in common.h), especially on aarch64_32 (aka ILP32). * * For this reason we cast the pointers to/from uintptr_t here. */ #define MULADDC_X1_INIT \ do { uintptr_t muladdc_d = (uintptr_t) d, muladdc_s = (uintptr_t) s; asm( #define MULADDC_X1_CORE \ "ldr x4, [%x2], #8 \n\t" \ "ldr x5, [%x1] \n\t" \ "mul x6, x4, %4 \n\t" \ "umulh x7, x4, %4 \n\t" \ "adds x5, x5, x6 \n\t" \ "adc x7, x7, xzr \n\t" \ "adds x5, x5, %0 \n\t" \ "adc %0, x7, xzr \n\t" \ "str x5, [%x1], #8 \n\t" #define MULADDC_X1_STOP \ : "+r" (c), \ "+r" (muladdc_d), \ "+r" (muladdc_s), \ "+m" (*(uint64_t (*)[16]) d) \ : "r" (b), "m" (*(const uint64_t (*)[16]) s) \ : "x4", "x5", "x6", "x7", "cc" \ ); d = (mbedtls_mpi_uint *)muladdc_d; s = (mbedtls_mpi_uint *)muladdc_s; } while (0); #endif /* Aarch64 */ #if defined(__mc68020__) || defined(__mcpu32__) #define MULADDC_X1_INIT \ asm( \ "movl %3, %%a2 \n\t" \ "movl %4, %%a3 \n\t" \ "movl %5, %%d3 \n\t" \ "movl %6, %%d2 \n\t" \ "moveq #0, %%d0 \n\t" #define MULADDC_X1_CORE \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "moveq #0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "addxl %%d4, %%d3 \n\t" #define MULADDC_X1_STOP \ "movl %%d3, %0 \n\t" \ "movl %%a3, %1 \n\t" \ "movl %%a2, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ ); #define MULADDC_X8_INIT MULADDC_X1_INIT #define MULADDC_X8_CORE \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addxl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d3:%%d1 \n\t" \ "addxl %%d4, %%d1 \n\t" \ "addxl %%d0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addxl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d3:%%d1 \n\t" \ "addxl %%d4, %%d1 \n\t" \ "addxl %%d0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addxl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d3:%%d1 \n\t" \ "addxl %%d4, %%d1 \n\t" \ "addxl %%d0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addxl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d3:%%d1 \n\t" \ "addxl %%d4, %%d1 \n\t" \ "addxl %%d0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "addxl %%d0, %%d3 \n\t" #define MULADDC_X8_STOP MULADDC_X1_STOP #endif /* MC68000 */ #if defined(__powerpc64__) || defined(__ppc64__) #if defined(__MACH__) && defined(__APPLE__) #define MULADDC_X1_INIT \ asm( \ "ld r3, %3 \n\t" \ "ld r4, %4 \n\t" \ "ld r5, %5 \n\t" \ "ld r6, %6 \n\t" \ "addi r3, r3, -8 \n\t" \ "addi r4, r4, -8 \n\t" \ "addic r5, r5, 0 \n\t" #define MULADDC_X1_CORE \ "ldu r7, 8(r3) \n\t" \ "mulld r8, r7, r6 \n\t" \ "mulhdu r9, r7, r6 \n\t" \ "adde r8, r8, r5 \n\t" \ "ld r7, 8(r4) \n\t" \ "addze r5, r9 \n\t" \ "addc r8, r8, r7 \n\t" \ "stdu r8, 8(r4) \n\t" #define MULADDC_X1_STOP \ "addze r5, r5 \n\t" \ "addi r4, r4, 8 \n\t" \ "addi r3, r3, 8 \n\t" \ "std r5, %0 \n\t" \ "std r4, %1 \n\t" \ "std r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ ); #else /* __MACH__ && __APPLE__ */ #define MULADDC_X1_INIT \ asm( \ "ld %%r3, %3 \n\t" \ "ld %%r4, %4 \n\t" \ "ld %%r5, %5 \n\t" \ "ld %%r6, %6 \n\t" \ "addi %%r3, %%r3, -8 \n\t" \ "addi %%r4, %%r4, -8 \n\t" \ "addic %%r5, %%r5, 0 \n\t" #define MULADDC_X1_CORE \ "ldu %%r7, 8(%%r3) \n\t" \ "mulld %%r8, %%r7, %%r6 \n\t" \ "mulhdu %%r9, %%r7, %%r6 \n\t" \ "adde %%r8, %%r8, %%r5 \n\t" \ "ld %%r7, 8(%%r4) \n\t" \ "addze %%r5, %%r9 \n\t" \ "addc %%r8, %%r8, %%r7 \n\t" \ "stdu %%r8, 8(%%r4) \n\t" #define MULADDC_X1_STOP \ "addze %%r5, %%r5 \n\t" \ "addi %%r4, %%r4, 8 \n\t" \ "addi %%r3, %%r3, 8 \n\t" \ "std %%r5, %0 \n\t" \ "std %%r4, %1 \n\t" \ "std %%r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ ); #endif /* __MACH__ && __APPLE__ */ #elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ #if defined(__MACH__) && defined(__APPLE__) #define MULADDC_X1_INIT \ asm( \ "lwz r3, %3 \n\t" \ "lwz r4, %4 \n\t" \ "lwz r5, %5 \n\t" \ "lwz r6, %6 \n\t" \ "addi r3, r3, -4 \n\t" \ "addi r4, r4, -4 \n\t" \ "addic r5, r5, 0 \n\t" #define MULADDC_X1_CORE \ "lwzu r7, 4(r3) \n\t" \ "mullw r8, r7, r6 \n\t" \ "mulhwu r9, r7, r6 \n\t" \ "adde r8, r8, r5 \n\t" \ "lwz r7, 4(r4) \n\t" \ "addze r5, r9 \n\t" \ "addc r8, r8, r7 \n\t" \ "stwu r8, 4(r4) \n\t" #define MULADDC_X1_STOP \ "addze r5, r5 \n\t" \ "addi r4, r4, 4 \n\t" \ "addi r3, r3, 4 \n\t" \ "stw r5, %0 \n\t" \ "stw r4, %1 \n\t" \ "stw r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ ); #else /* __MACH__ && __APPLE__ */ #define MULADDC_X1_INIT \ asm( \ "lwz %%r3, %3 \n\t" \ "lwz %%r4, %4 \n\t" \ "lwz %%r5, %5 \n\t" \ "lwz %%r6, %6 \n\t" \ "addi %%r3, %%r3, -4 \n\t" \ "addi %%r4, %%r4, -4 \n\t" \ "addic %%r5, %%r5, 0 \n\t" #define MULADDC_X1_CORE \ "lwzu %%r7, 4(%%r3) \n\t" \ "mullw %%r8, %%r7, %%r6 \n\t" \ "mulhwu %%r9, %%r7, %%r6 \n\t" \ "adde %%r8, %%r8, %%r5 \n\t" \ "lwz %%r7, 4(%%r4) \n\t" \ "addze %%r5, %%r9 \n\t" \ "addc %%r8, %%r8, %%r7 \n\t" \ "stwu %%r8, 4(%%r4) \n\t" #define MULADDC_X1_STOP \ "addze %%r5, %%r5 \n\t" \ "addi %%r4, %%r4, 4 \n\t" \ "addi %%r3, %%r3, 4 \n\t" \ "stw %%r5, %0 \n\t" \ "stw %%r4, %1 \n\t" \ "stw %%r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ ); #endif /* __MACH__ && __APPLE__ */ #endif /* PPC32 */ /* * The Sparc(64) assembly is reported to be broken. * Disable it for now, until we're able to fix it. */ #if 0 && defined(__sparc__) #if defined(__sparc64__) #define MULADDC_X1_INIT \ asm( \ "ldx %3, %%o0 \n\t" \ "ldx %4, %%o1 \n\t" \ "ld %5, %%o2 \n\t" \ "ld %6, %%o3 \n\t" #define MULADDC_X1_CORE \ "ld [%%o0], %%o4 \n\t" \ "inc 4, %%o0 \n\t" \ "ld [%%o1], %%o5 \n\t" \ "umul %%o3, %%o4, %%o4 \n\t" \ "addcc %%o4, %%o2, %%o4 \n\t" \ "rd %%y, %%g1 \n\t" \ "addx %%g1, 0, %%g1 \n\t" \ "addcc %%o4, %%o5, %%o4 \n\t" \ "st %%o4, [%%o1] \n\t" \ "addx %%g1, 0, %%o2 \n\t" \ "inc 4, %%o1 \n\t" #define MULADDC_X1_STOP \ "st %%o2, %0 \n\t" \ "stx %%o1, %1 \n\t" \ "stx %%o0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "g1", "o0", "o1", "o2", "o3", "o4", \ "o5" \ ); #else /* __sparc64__ */ #define MULADDC_X1_INIT \ asm( \ "ld %3, %%o0 \n\t" \ "ld %4, %%o1 \n\t" \ "ld %5, %%o2 \n\t" \ "ld %6, %%o3 \n\t" #define MULADDC_X1_CORE \ "ld [%%o0], %%o4 \n\t" \ "inc 4, %%o0 \n\t" \ "ld [%%o1], %%o5 \n\t" \ "umul %%o3, %%o4, %%o4 \n\t" \ "addcc %%o4, %%o2, %%o4 \n\t" \ "rd %%y, %%g1 \n\t" \ "addx %%g1, 0, %%g1 \n\t" \ "addcc %%o4, %%o5, %%o4 \n\t" \ "st %%o4, [%%o1] \n\t" \ "addx %%g1, 0, %%o2 \n\t" \ "inc 4, %%o1 \n\t" #define MULADDC_X1_STOP \ "st %%o2, %0 \n\t" \ "st %%o1, %1 \n\t" \ "st %%o0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "g1", "o0", "o1", "o2", "o3", "o4", \ "o5" \ ); #endif /* __sparc64__ */ #endif /* __sparc__ */ #if defined(__microblaze__) || defined(microblaze) #define MULADDC_X1_INIT \ asm( \ "lwi r3, %3 \n\t" \ "lwi r4, %4 \n\t" \ "lwi r5, %5 \n\t" \ "lwi r6, %6 \n\t" \ "andi r7, r6, 0xffff \n\t" \ "bsrli r6, r6, 16 \n\t" #if(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) #define MULADDC_LHUI \ "lhui r9, r3, 0 \n\t" \ "addi r3, r3, 2 \n\t" \ "lhui r8, r3, 0 \n\t" #else #define MULADDC_LHUI \ "lhui r8, r3, 0 \n\t" \ "addi r3, r3, 2 \n\t" \ "lhui r9, r3, 0 \n\t" #endif #define MULADDC_X1_CORE \ MULADDC_LHUI \ "addi r3, r3, 2 \n\t" \ "mul r10, r9, r6 \n\t" \ "mul r11, r8, r7 \n\t" \ "mul r12, r9, r7 \n\t" \ "mul r13, r8, r6 \n\t" \ "bsrli r8, r10, 16 \n\t" \ "bsrli r9, r11, 16 \n\t" \ "add r13, r13, r8 \n\t" \ "add r13, r13, r9 \n\t" \ "bslli r10, r10, 16 \n\t" \ "bslli r11, r11, 16 \n\t" \ "add r12, r12, r10 \n\t" \ "addc r13, r13, r0 \n\t" \ "add r12, r12, r11 \n\t" \ "addc r13, r13, r0 \n\t" \ "lwi r10, r4, 0 \n\t" \ "add r12, r12, r10 \n\t" \ "addc r13, r13, r0 \n\t" \ "add r12, r12, r5 \n\t" \ "addc r5, r13, r0 \n\t" \ "swi r12, r4, 0 \n\t" \ "addi r4, r4, 4 \n\t" #define MULADDC_X1_STOP \ "swi r5, %0 \n\t" \ "swi r4, %1 \n\t" \ "swi r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", \ "r9", "r10", "r11", "r12", "r13" \ ); #endif /* MicroBlaze */ #if defined(__tricore__) #define MULADDC_X1_INIT \ asm( \ "ld.a %%a2, %3 \n\t" \ "ld.a %%a3, %4 \n\t" \ "ld.w %%d4, %5 \n\t" \ "ld.w %%d1, %6 \n\t" \ "xor %%d5, %%d5 \n\t" #define MULADDC_X1_CORE \ "ld.w %%d0, [%%a2+] \n\t" \ "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ "ld.w %%d0, [%%a3] \n\t" \ "addx %%d2, %%d2, %%d0 \n\t" \ "addc %%d3, %%d3, 0 \n\t" \ "mov %%d4, %%d3 \n\t" \ "st.w [%%a3+], %%d2 \n\t" #define MULADDC_X1_STOP \ "st.w %0, %%d4 \n\t" \ "st.a %1, %%a3 \n\t" \ "st.a %2, %%a2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "d0", "d1", "e2", "d4", "a2", "a3" \ ); #endif /* TriCore */ #if defined(__arm__) #if defined(__thumb__) && !defined(__thumb2__) #if defined(MBEDTLS_COMPILER_IS_GCC) /* * Thumb 1 ISA. This code path has only been tested successfully on gcc; * it does not compile on clang or armclang. */ #if !defined(__OPTIMIZE__) && defined(__GNUC__) /* * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about * our use of r7 below, unless -fomit-frame-pointer is passed. * * On the other hand, -fomit-frame-pointer is implied by any -Ox options with * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by * clang and armcc5 under the same conditions). * * If gcc needs to use r7, we use r1 as a scratch register and have a few extra * instructions to preserve/restore it; otherwise, we can use r7 and avoid * the preserve/restore overhead. */ #define MULADDC_SCRATCH "RS .req r1 \n\t" #define MULADDC_PRESERVE_SCRATCH "mov r10, r1 \n\t" #define MULADDC_RESTORE_SCRATCH "mov r1, r10 \n\t" #define MULADDC_SCRATCH_CLOBBER "r10" #else /* !defined(__OPTIMIZE__) && defined(__GNUC__) */ #define MULADDC_SCRATCH "RS .req r7 \n\t" #define MULADDC_PRESERVE_SCRATCH "" #define MULADDC_RESTORE_SCRATCH "" #define MULADDC_SCRATCH_CLOBBER "r7" #endif /* !defined(__OPTIMIZE__) && defined(__GNUC__) */ #define MULADDC_X1_INIT \ asm( \ MULADDC_SCRATCH \ "ldr r0, %3 \n\t" \ "ldr r1, %4 \n\t" \ "ldr r2, %5 \n\t" \ "ldr r3, %6 \n\t" \ "lsr r4, r3, #16 \n\t" \ "mov r9, r4 \n\t" \ "lsl r4, r3, #16 \n\t" \ "lsr r4, r4, #16 \n\t" \ "mov r8, r4 \n\t" \ #define MULADDC_X1_CORE \ MULADDC_PRESERVE_SCRATCH \ "ldmia r0!, {r6} \n\t" \ "lsr RS, r6, #16 \n\t" \ "lsl r6, r6, #16 \n\t" \ "lsr r6, r6, #16 \n\t" \ "mov r4, r8 \n\t" \ "mul r4, r6 \n\t" \ "mov r3, r9 \n\t" \ "mul r6, r3 \n\t" \ "mov r5, r9 \n\t" \ "mul r5, RS \n\t" \ "mov r3, r8 \n\t" \ "mul RS, r3 \n\t" \ "lsr r3, r6, #16 \n\t" \ "add r5, r5, r3 \n\t" \ "lsr r3, RS, #16 \n\t" \ "add r5, r5, r3 \n\t" \ "add r4, r4, r2 \n\t" \ "mov r2, #0 \n\t" \ "adc r5, r2 \n\t" \ "lsl r3, r6, #16 \n\t" \ "add r4, r4, r3 \n\t" \ "adc r5, r2 \n\t" \ "lsl r3, RS, #16 \n\t" \ "add r4, r4, r3 \n\t" \ "adc r5, r2 \n\t" \ MULADDC_RESTORE_SCRATCH \ "ldr r3, [r1] \n\t" \ "add r4, r4, r3 \n\t" \ "adc r2, r5 \n\t" \ "stmia r1!, {r4} \n\t" #define MULADDC_X1_STOP \ "str r2, %0 \n\t" \ "str r1, %1 \n\t" \ "str r0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r0", "r1", "r2", "r3", "r4", "r5", \ "r6", MULADDC_SCRATCH_CLOBBER, "r8", "r9", "cc" \ ); #endif /* !defined(__ARMCC_VERSION) && !defined(__clang__) */ #elif (__ARM_ARCH >= 6) && \ defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) /* Armv6-M (or later) with DSP Instruction Set Extensions. * Requires support for either Thumb 2 or Arm ISA. */ #define MULADDC_X1_INIT \ { \ mbedtls_mpi_uint tmp_a, tmp_b; \ asm volatile ( #define MULADDC_X1_CORE \ ".p2align 2 \n\t" \ "ldr %[a], [%[in]], #4 \n\t" \ "ldr %[b], [%[acc]] \n\t" \ "umaal %[b], %[carry], %[scalar], %[a] \n\t" \ "str %[b], [%[acc]], #4 \n\t" #define MULADDC_X1_STOP \ : [a] "=&r" (tmp_a), \ [b] "=&r" (tmp_b), \ [in] "+r" (s), \ [acc] "+r" (d), \ [carry] "+l" (c) \ : [scalar] "r" (b) \ : "memory" \ ); \ } #define MULADDC_X2_INIT \ { \ mbedtls_mpi_uint tmp_a0, tmp_b0; \ mbedtls_mpi_uint tmp_a1, tmp_b1; \ asm volatile ( /* - Make sure loop is 4-byte aligned to avoid stalls * upon repeated non-word aligned instructions in * some microarchitectures. * - Don't use ldm with post-increment or back-to-back * loads with post-increment and same address register * to avoid stalls on some microarchitectures. * - Bunch loads and stores to reduce latency on some * microarchitectures. E.g., on Cortex-M4, the first * in a series of load/store operations has latency * 2 cycles, while subsequent loads/stores are single-cycle. */ #define MULADDC_X2_CORE \ ".p2align 2 \n\t" \ "ldr %[a0], [%[in]], #+8 \n\t" \ "ldr %[b0], [%[acc]], #+8 \n\t" \ "ldr %[a1], [%[in], #-4] \n\t" \ "ldr %[b1], [%[acc], #-4] \n\t" \ "umaal %[b0], %[carry], %[scalar], %[a0] \n\t" \ "umaal %[b1], %[carry], %[scalar], %[a1] \n\t" \ "str %[b0], [%[acc], #-8] \n\t" \ "str %[b1], [%[acc], #-4] \n\t" #define MULADDC_X2_STOP \ : [a0] "=&r" (tmp_a0), \ [b0] "=&r" (tmp_b0), \ [a1] "=&r" (tmp_a1), \ [b1] "=&r" (tmp_b1), \ [in] "+r" (s), \ [acc] "+r" (d), \ [carry] "+l" (c) \ : [scalar] "r" (b) \ : "memory" \ ); \ } #else /* Thumb 2 or Arm ISA, without DSP extensions */ #define MULADDC_X1_INIT \ asm( \ "ldr r0, %3 \n\t" \ "ldr r1, %4 \n\t" \ "ldr r2, %5 \n\t" \ "ldr r3, %6 \n\t" #define MULADDC_X1_CORE \ "ldr r4, [r0], #4 \n\t" \ "mov r5, #0 \n\t" \ "ldr r6, [r1] \n\t" \ "umlal r2, r5, r3, r4 \n\t" \ "adds r4, r6, r2 \n\t" \ "adc r2, r5, #0 \n\t" \ "str r4, [r1], #4 \n\t" #define MULADDC_X1_STOP \ "str r2, %0 \n\t" \ "str r1, %1 \n\t" \ "str r0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r0", "r1", "r2", "r3", "r4", "r5", \ "r6", "cc" \ ); #endif /* ISA codepath selection */ #endif /* defined(__arm__) */ #if defined(__alpha__) #define MULADDC_X1_INIT \ asm( \ "ldq $1, %3 \n\t" \ "ldq $2, %4 \n\t" \ "ldq $3, %5 \n\t" \ "ldq $4, %6 \n\t" #define MULADDC_X1_CORE \ "ldq $6, 0($1) \n\t" \ "addq $1, 8, $1 \n\t" \ "mulq $6, $4, $7 \n\t" \ "umulh $6, $4, $6 \n\t" \ "addq $7, $3, $7 \n\t" \ "cmpult $7, $3, $3 \n\t" \ "ldq $5, 0($2) \n\t" \ "addq $7, $5, $7 \n\t" \ "cmpult $7, $5, $5 \n\t" \ "stq $7, 0($2) \n\t" \ "addq $2, 8, $2 \n\t" \ "addq $6, $3, $3 \n\t" \ "addq $5, $3, $3 \n\t" #define MULADDC_X1_STOP \ "stq $3, %0 \n\t" \ "stq $2, %1 \n\t" \ "stq $1, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ ); #endif /* Alpha */ #if defined(__mips__) && !defined(__mips64) #define MULADDC_X1_INIT \ asm( \ "lw $10, %3 \n\t" \ "lw $11, %4 \n\t" \ "lw $12, %5 \n\t" \ "lw $13, %6 \n\t" #define MULADDC_X1_CORE \ "lw $14, 0($10) \n\t" \ "multu $13, $14 \n\t" \ "addi $10, $10, 4 \n\t" \ "mflo $14 \n\t" \ "mfhi $9 \n\t" \ "addu $14, $12, $14 \n\t" \ "lw $15, 0($11) \n\t" \ "sltu $12, $14, $12 \n\t" \ "addu $15, $14, $15 \n\t" \ "sltu $14, $15, $14 \n\t" \ "addu $12, $12, $9 \n\t" \ "sw $15, 0($11) \n\t" \ "addu $12, $12, $14 \n\t" \ "addi $11, $11, 4 \n\t" #define MULADDC_X1_STOP \ "sw $12, %0 \n\t" \ "sw $11, %1 \n\t" \ "sw $10, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ ); #endif /* MIPS */ #endif /* GNUC */ #if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) #define MULADDC_X1_INIT \ __asm mov esi, s \ __asm mov edi, d \ __asm mov ecx, c \ __asm mov ebx, b #define MULADDC_X1_CORE \ __asm lodsd \ __asm mul ebx \ __asm add eax, ecx \ __asm adc edx, 0 \ __asm add eax, [edi] \ __asm adc edx, 0 \ __asm mov ecx, edx \ __asm stosd #define MULADDC_X1_STOP \ __asm mov c, ecx \ __asm mov d, edi \ __asm mov s, esi #if defined(MBEDTLS_HAVE_SSE2) #define EMIT __asm _emit #define MULADDC_X8_INIT MULADDC_X1_INIT #define MULADDC_X8_CORE \ EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ EMIT 0x0F EMIT 0x6E EMIT 0x1F \ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ EMIT 0x0F EMIT 0x6E EMIT 0x16 \ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ EMIT 0x0F EMIT 0x7E EMIT 0x0F \ EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0x7E EMIT 0xC9 #define MULADDC_X8_STOP \ EMIT 0x0F EMIT 0x77 \ __asm mov c, ecx \ __asm mov d, edi \ __asm mov s, esi #endif /* SSE2 */ #endif /* MSVC */ #endif /* MBEDTLS_HAVE_ASM */ #if !defined(MULADDC_X1_CORE) #if defined(MBEDTLS_HAVE_UDBL) #define MULADDC_X1_INIT \ { \ mbedtls_t_udbl r; \ mbedtls_mpi_uint r0, r1; #define MULADDC_X1_CORE \ r = *(s++) * (mbedtls_t_udbl) b; \ r0 = (mbedtls_mpi_uint) r; \ r1 = (mbedtls_mpi_uint)( r >> biL ); \ r0 += c; r1 += (r0 < c); \ r0 += *d; r1 += (r0 < *d); \ c = r1; *(d++) = r0; #define MULADDC_X1_STOP \ } #else /* MBEDTLS_HAVE_UDBL */ #define MULADDC_X1_INIT \ { \ mbedtls_mpi_uint s0, s1, b0, b1; \ mbedtls_mpi_uint r0, r1, rx, ry; \ b0 = ( b << biH ) >> biH; \ b1 = ( b >> biH ); #define MULADDC_X1_CORE \ s0 = ( *s << biH ) >> biH; \ s1 = ( *s >> biH ); s++; \ rx = s0 * b1; r0 = s0 * b0; \ ry = s1 * b0; r1 = s1 * b1; \ r1 += ( rx >> biH ); \ r1 += ( ry >> biH ); \ rx <<= biH; ry <<= biH; \ r0 += rx; r1 += (r0 < rx); \ r0 += ry; r1 += (r0 < ry); \ r0 += c; r1 += (r0 < c); \ r0 += *d; r1 += (r0 < *d); \ c = r1; *(d++) = r0; #define MULADDC_X1_STOP \ } #endif /* C (longlong) */ #endif /* C (generic) */ #if !defined(MULADDC_X2_CORE) #define MULADDC_X2_INIT MULADDC_X1_INIT #define MULADDC_X2_STOP MULADDC_X1_STOP #define MULADDC_X2_CORE MULADDC_X1_CORE MULADDC_X1_CORE #endif /* MULADDC_X2_CORE */ #if !defined(MULADDC_X4_CORE) #define MULADDC_X4_INIT MULADDC_X2_INIT #define MULADDC_X4_STOP MULADDC_X2_STOP #define MULADDC_X4_CORE MULADDC_X2_CORE MULADDC_X2_CORE #endif /* MULADDC_X4_CORE */ #if !defined(MULADDC_X8_CORE) #define MULADDC_X8_INIT MULADDC_X4_INIT #define MULADDC_X8_STOP MULADDC_X4_STOP #define MULADDC_X8_CORE MULADDC_X4_CORE MULADDC_X4_CORE #endif /* MULADDC_X8_CORE */ /* *INDENT-ON* */ #endif /* bn_mul.h */ webfakes/src/mbedtls/library/lmots.h0000644000176200001440000003062314740737024017251 0ustar liggesusers/** * \file lmots.h * * \brief This file provides an API for the LM-OTS post-quantum-safe one-time * public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. * This implementation currently only supports a single parameter set * MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_LMOTS_H #define MBEDTLS_LMOTS_H #include "mbedtls/build_info.h" #include "psa/crypto.h" #include "mbedtls/lms.h" #include #include #define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ MBEDTLS_LMOTS_I_KEY_ID_LEN + \ MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ MBEDTLS_LMOTS_N_HASH_LEN(type)) #define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0) #define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \ MBEDTLS_LMOTS_TYPE_LEN) #define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \ MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type)) #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_TEST_HOOKS) extern int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *); #endif /* defined(MBEDTLS_TEST_HOOKS) */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief This function converts a \ref psa_status_t to a * low-level LMS error code. * * \param status The psa_status_t to convert * * \return The corresponding LMS error code. */ int MBEDTLS_DEPRECATED mbedtls_lms_error_from_psa(psa_status_t status); #endif /** * \brief This function initializes a public LMOTS context * * \param ctx The uninitialized LMOTS context that will then be * initialized. */ void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx); /** * \brief This function uninitializes a public LMOTS context * * \param ctx The initialized LMOTS context that will then be * uninitialized. */ void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx); /** * \brief This function imports an LMOTS public key into a * LMOTS context. * * \note Before this function is called, the context must * have been initialized. * * \note See IETF RFC8554 for details of the encoding of * this public key. * * \param ctx The initialized LMOTS context store the key in. * \param key The buffer from which the key will be read. * #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read * from this. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, const unsigned char *key, size_t key_size); /** * \brief This function exports an LMOTS public key from a * LMOTS context that already contains a public key. * * \note Before this function is called, the context must * have been initialized and the context must contain * a public key. * * \note See IETF RFC8554 for details of the encoding of * this public key. * * \param ctx The initialized LMOTS context that contains the * public key. * \param key The buffer into which the key will be output. Must * be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len); /** * \brief This function creates a candidate public key from * an LMOTS signature. This can then be compared to * the real public key to determine the validity of * the signature. * * \note This function is exposed publicly to be used in LMS * signature verification, it is expected that * mbedtls_lmots_verify will be used for LMOTS * signature verification. * * \param params The LMOTS parameter set, q and I values as an * mbedtls_lmots_parameters_t struct. * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buffer from which the signature will be read. * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from * this. * \param out The buffer where the candidate public key will be * stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN * bytes in size. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size, unsigned char *out, size_t out_size, size_t *out_len); /** * \brief This function verifies a LMOTS signature, using a * LMOTS context that contains a public key. * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with * handling stateful keys. The API for this function * may change considerably in future versions. * * \note Before this function is called, the context must * have been initialized and must contain a public key * (either by import or calculation from a private * key). * * \param ctx The initialized LMOTS context from which the public * key will be read. * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buf from which the signature will be read. * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from * this. * * \return \c 0 on successful verification. * \return A non-zero error code on failure. */ int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size); #if defined(MBEDTLS_LMS_PRIVATE) /** * \brief This function initializes a private LMOTS context * * \param ctx The uninitialized LMOTS context that will then be * initialized. */ void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx); /** * \brief This function uninitializes a private LMOTS context * * \param ctx The initialized LMOTS context that will then be * uninitialized. */ void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx); /** * \brief This function calculates an LMOTS private key, and * stores in into an LMOTS context. * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with * handling stateful keys. The API for this function * may change considerably in future versions. * * \note The seed must have at least 256 bits of entropy. * * \param ctx The initialized LMOTS context to generate the key * into. * \param I_key_identifier The key identifier of the key, as a 16-byte string. * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is * not being used as part of an LMS key, this should * be set to 0. * \param seed The seed used to deterministically generate the * key. * \param seed_size The length of the seed. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, mbedtls_lmots_algorithm_type_t type, const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], uint32_t q_leaf_identifier, const unsigned char *seed, size_t seed_size); /** * \brief This function generates an LMOTS public key from a * LMOTS context that already contains a private key. * * \note Before this function is called, the context must * have been initialized and the context must contain * a private key. * * \param ctx The initialized LMOTS context to generate the key * from and store it into. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, const mbedtls_lmots_private_t *priv_ctx); /** * \brief This function creates a LMOTS signature, using a * LMOTS context that contains a private key. * * \note Before this function is called, the context must * have been initialized and must contain a private * key. * * \note LMOTS private keys can only be used once, otherwise * attackers may be able to create forged signatures. * If the signing operation is successful, the private * key in the context will be erased, and no further * signing will be possible until another private key * is loaded * * \param ctx The initialized LMOTS context from which the * private key will be read. * \param f_rng The RNG function to be used for signature * generation. * \param p_rng The RNG context to be passed to f_rng * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buf into which the signature will be stored. * Must be at least #MBEDTLS_LMOTS_SIG_LEN in size. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *msg, size_t msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len); #endif /* defined(MBEDTLS_LMS_PRIVATE) */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_LMOTS_H */ webfakes/src/mbedtls/library/constant_time_impl.h0000644000176200001440000005253114740737201022002 0ustar liggesusers/** * Constant-time functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONSTANT_TIME_IMPL_H #define MBEDTLS_CONSTANT_TIME_IMPL_H #include #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif /* * To improve readability of constant_time_internal.h, the static inline * definitions are here, and constant_time_internal.h has only the declarations. * * This results in duplicate declarations of the form: * static inline void f(); // from constant_time_internal.h * static inline void f() { ... } // from constant_time_impl.h * when constant_time_internal.h is included. * * This appears to behave as if the declaration-without-definition was not present * (except for warnings if gcc -Wredundant-decls or similar is used). * * Disable -Wredundant-decls so that gcc does not warn about this. This is re-enabled * at the bottom of this file. */ #if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wredundant-decls" #endif /* Disable asm under Memsan because it confuses Memsan and generates false errors. * * We also disable under Valgrind by default, because it's more useful * for Valgrind to test the plain C implementation. MBEDTLS_TEST_CONSTANT_FLOW_ASM //no-check-names * may be set to permit building asm under Valgrind. */ #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) || \ (defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) && !defined(MBEDTLS_TEST_CONSTANT_FLOW_ASM)) //no-check-names #define MBEDTLS_CT_NO_ASM #elif defined(__has_feature) #if __has_feature(memory_sanitizer) #define MBEDTLS_CT_NO_ASM #endif #endif /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && (!defined(__ARMCC_VERSION) || \ __ARMCC_VERSION >= 6000000) && !defined(MBEDTLS_CT_NO_ASM) #define MBEDTLS_CT_ASM #if (defined(__arm__) || defined(__thumb__) || defined(__thumb2__)) #define MBEDTLS_CT_ARM_ASM #elif defined(__aarch64__) #define MBEDTLS_CT_AARCH64_ASM #elif defined(__amd64__) || defined(__x86_64__) #define MBEDTLS_CT_X86_64_ASM #elif defined(__i386__) #define MBEDTLS_CT_X86_ASM #endif #endif #define MBEDTLS_CT_SIZE (sizeof(mbedtls_ct_uint_t) * 8) /* ============================================================================ * Core const-time primitives */ /* Ensure that the compiler cannot know the value of x (i.e., cannot optimise * based on its value) after this function is called. * * If we are not using assembly, this will be fairly inefficient, so its use * should be minimised. */ #if !defined(MBEDTLS_CT_ASM) extern volatile mbedtls_ct_uint_t mbedtls_ct_zero; #endif /** * \brief Ensure that a value cannot be known at compile time. * * \param x The value to hide from the compiler. * \return The same value that was passed in, such that the compiler * cannot prove its value (even for calls of the form * x = mbedtls_ct_compiler_opaque(1), x will be unknown). * * \note This is mainly used in constructing mbedtls_ct_condition_t * values and performing operations over them, to ensure that * there is no way for the compiler to ever know anything about * the value of an mbedtls_ct_condition_t. */ static inline mbedtls_ct_uint_t mbedtls_ct_compiler_opaque(mbedtls_ct_uint_t x) { #if defined(MBEDTLS_CT_ASM) asm volatile ("" : [x] "+r" (x) :); return x; #else return x ^ mbedtls_ct_zero; #endif } /* * Selecting unified syntax is needed for gcc, and harmless on clang. * * This is needed because on Thumb 1, condition flags are always set, so * e.g. "negs" is supported but "neg" is not (on Thumb 2, both exist). * * Under Thumb 1 unified syntax, only the "negs" form is accepted, and * under divided syntax, only the "neg" form is accepted. clang only * supports unified syntax. * * On Thumb 2 and Arm, both compilers are happy with the "s" suffix, * although we don't actually care about setting the flags. * * For old versions of gcc (see #8516 for details), restore divided * syntax afterwards - otherwise old versions of gcc seem to apply * unified syntax globally, which breaks other asm code. */ #if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__thumb__) && !defined(__thumb2__) && \ (__GNUC__ < 11) && !defined(__ARM_ARCH_2__) #define RESTORE_ASM_SYNTAX ".syntax divided \n\t" #else #define RESTORE_ASM_SYNTAX #endif /* Convert a number into a condition in constant time. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x) { /* * Define mask-generation code that, as far as possible, will not use branches or conditional instructions. * * For some platforms / type sizes, we define assembly to assure this. * * Otherwise, we define a plain C fallback which (in May 2023) does not get optimised into * conditional instructions or branches by trunk clang, gcc, or MSVC v19. */ #if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) mbedtls_ct_uint_t s; asm volatile ("neg %x[s], %x[x] \n\t" "orr %x[x], %x[s], %x[x] \n\t" "asr %x[x], %x[x], 63 \n\t" : [s] "=&r" (s), [x] "+&r" (x) : : ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32) uint32_t s; asm volatile (".syntax unified \n\t" "negs %[s], %[x] \n\t" "orrs %[x], %[x], %[s] \n\t" "asrs %[x], %[x], #31 \n\t" RESTORE_ASM_SYNTAX : [s] "=&l" (s), [x] "+&l" (x) : : "cc" /* clobbers flag bits */ ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) uint64_t s; asm volatile ("mov %[x], %[s] \n\t" "neg %[s] \n\t" "or %[x], %[s] \n\t" "sar $63, %[s] \n\t" : [s] "=&a" (s) : [x] "D" (x) : ); return (mbedtls_ct_condition_t) s; #elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32) uint32_t s; asm volatile ("mov %[x], %[s] \n\t" "neg %[s] \n\t" "or %[s], %[x] \n\t" "sar $31, %[x] \n\t" : [s] "=&c" (s), [x] "+&a" (x) : : ); return (mbedtls_ct_condition_t) x; #else const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x); #if defined(_MSC_VER) /* MSVC has a warning about unary minus on unsigned, but this is * well-defined and precisely what we want to do here */ # pragma warning( push ) # pragma warning( disable : 4146 ) #endif // y is negative (i.e., top bit set) iff x is non-zero mbedtls_ct_int_t y = (-xo) | -(xo >> 1); // extract only the sign bit of y so that y == 1 (if x is non-zero) or 0 (if x is zero) y = (((mbedtls_ct_uint_t) y) >> (MBEDTLS_CT_SIZE - 1)); // -y has all bits set (if x is non-zero), or all bits clear (if x is zero) return (mbedtls_ct_condition_t) (-y); #if defined(_MSC_VER) # pragma warning( pop ) #endif #endif } static inline mbedtls_ct_uint_t mbedtls_ct_if(mbedtls_ct_condition_t condition, mbedtls_ct_uint_t if1, mbedtls_ct_uint_t if0) { #if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) asm volatile ("and %x[if1], %x[if1], %x[condition] \n\t" "mvn %x[condition], %x[condition] \n\t" "and %x[condition], %x[condition], %x[if0] \n\t" "orr %x[condition], %x[if1], %x[condition]" : [condition] "+&r" (condition), [if1] "+&r" (if1) : [if0] "r" (if0) : ); return (mbedtls_ct_uint_t) condition; #elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32) asm volatile (".syntax unified \n\t" "ands %[if1], %[if1], %[condition] \n\t" "mvns %[condition], %[condition] \n\t" "ands %[condition], %[condition], %[if0] \n\t" "orrs %[condition], %[if1], %[condition] \n\t" RESTORE_ASM_SYNTAX : [condition] "+&l" (condition), [if1] "+&l" (if1) : [if0] "l" (if0) : "cc" ); return (mbedtls_ct_uint_t) condition; #elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) asm volatile ("and %[condition], %[if1] \n\t" "not %[condition] \n\t" "and %[condition], %[if0] \n\t" "or %[if1], %[if0] \n\t" : [condition] "+&D" (condition), [if1] "+&S" (if1), [if0] "+&a" (if0) : : ); return if0; #elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32) asm volatile ("and %[condition], %[if1] \n\t" "not %[condition] \n\t" "and %[if0], %[condition] \n\t" "or %[condition], %[if1] \n\t" : [condition] "+&c" (condition), [if1] "+&a" (if1) : [if0] "b" (if0) : ); return if1; #else mbedtls_ct_condition_t not_cond = (mbedtls_ct_condition_t) (~mbedtls_ct_compiler_opaque(condition)); return (mbedtls_ct_uint_t) ((condition & if1) | (not_cond & if0)); #endif } static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { #if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) uint64_t s1; asm volatile ("eor %x[s1], %x[y], %x[x] \n\t" "sub %x[x], %x[x], %x[y] \n\t" "bic %x[x], %x[x], %x[s1] \n\t" "and %x[s1], %x[s1], %x[y] \n\t" "orr %x[s1], %x[x], %x[s1] \n\t" "asr %x[x], %x[s1], 63" : [s1] "=&r" (s1), [x] "+&r" (x) : [y] "r" (y) : ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32) uint32_t s1; asm volatile ( ".syntax unified \n\t" #if defined(__thumb__) && !defined(__thumb2__) "movs %[s1], %[x] \n\t" "eors %[s1], %[s1], %[y] \n\t" #else "eors %[s1], %[x], %[y] \n\t" #endif "subs %[x], %[x], %[y] \n\t" "bics %[x], %[x], %[s1] \n\t" "ands %[y], %[s1], %[y] \n\t" "orrs %[x], %[x], %[y] \n\t" "asrs %[x], %[x], #31 \n\t" RESTORE_ASM_SYNTAX : [s1] "=&l" (s1), [x] "+&l" (x), [y] "+&l" (y) : : "cc" ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) uint64_t s; asm volatile ("mov %[x], %[s] \n\t" "xor %[y], %[s] \n\t" "sub %[y], %[x] \n\t" "and %[s], %[y] \n\t" "not %[s] \n\t" "and %[s], %[x] \n\t" "or %[y], %[x] \n\t" "sar $63, %[x] \n\t" : [s] "=&a" (s), [x] "+&D" (x), [y] "+&S" (y) : : ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32) uint32_t s; asm volatile ("mov %[x], %[s] \n\t" "xor %[y], %[s] \n\t" "sub %[y], %[x] \n\t" "and %[s], %[y] \n\t" "not %[s] \n\t" "and %[s], %[x] \n\t" "or %[y], %[x] \n\t" "sar $31, %[x] \n\t" : [s] "=&b" (s), [x] "+&a" (x), [y] "+&c" (y) : : ); return (mbedtls_ct_condition_t) x; #else /* Ensure that the compiler cannot optimise the following operations over x and y, * even if it knows the value of x and y. */ const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x); const mbedtls_ct_uint_t yo = mbedtls_ct_compiler_opaque(y); /* * Check if the most significant bits (MSB) of the operands are different. * cond is true iff the MSBs differ. */ mbedtls_ct_condition_t cond = mbedtls_ct_bool((xo ^ yo) >> (MBEDTLS_CT_SIZE - 1)); /* * If the MSB are the same then the difference x-y will be negative (and * have its MSB set to 1 during conversion to unsigned) if and only if x> (MBEDTLS_CT_SIZE - 1); // Convert to a condition (i.e., all bits set iff non-zero) return mbedtls_ct_bool(ret); #endif } static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { /* diff = 0 if x == y, non-zero otherwise */ const mbedtls_ct_uint_t diff = mbedtls_ct_compiler_opaque(x) ^ mbedtls_ct_compiler_opaque(y); /* all ones if x != y, 0 otherwise */ return mbedtls_ct_bool(diff); } static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, unsigned char high, unsigned char c, unsigned char t) { const unsigned char co = (unsigned char) mbedtls_ct_compiler_opaque(c); const unsigned char to = (unsigned char) mbedtls_ct_compiler_opaque(t); /* low_mask is: 0 if low <= c, 0x...ff if low > c */ unsigned low_mask = ((unsigned) co - low) >> 8; /* high_mask is: 0 if c <= high, 0x...ff if c > high */ unsigned high_mask = ((unsigned) high - co) >> 8; return (unsigned char) (~(low_mask | high_mask)) & to; } /* ============================================================================ * Everything below here is trivial wrapper functions */ static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition, size_t if1, size_t if0) { return (size_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); } static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition, unsigned if1, unsigned if0) { return (unsigned) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition, mbedtls_ct_condition_t if1, mbedtls_ct_condition_t if0) { return (mbedtls_ct_condition_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); } #if defined(MBEDTLS_BIGNUM_C) static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, mbedtls_mpi_uint if1, mbedtls_mpi_uint if0) { return (mbedtls_mpi_uint) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); } #endif static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1) { return (size_t) (condition & if1); } static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1) { return (unsigned) (condition & if1); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition, mbedtls_ct_condition_t if1) { return (mbedtls_ct_condition_t) (condition & if1); } #if defined(MBEDTLS_BIGNUM_C) static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition, mbedtls_mpi_uint if1) { return (mbedtls_mpi_uint) (condition & if1); } #endif /* MBEDTLS_BIGNUM_C */ static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0) { /* Coverting int -> uint -> int here is safe, because we require if1 and if0 to be * in the range -32767..0, and we require 32-bit int and uint types. * * This means that (0 <= -if0 < INT_MAX), so negating if0 is safe, and similarly for * converting back to int. */ return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1), (mbedtls_ct_uint_t) (-if0))); } static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1) { return -((int) (condition & (-if1))); } static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { return ~mbedtls_ct_uint_ne(x, y); } static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { return mbedtls_ct_uint_lt(y, x); } static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { return ~mbedtls_ct_uint_lt(x, y); } static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { return ~mbedtls_ct_uint_gt(x, y); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y) { return (mbedtls_ct_condition_t) (x ^ y); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y) { return (mbedtls_ct_condition_t) (x & y); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y) { return (mbedtls_ct_condition_t) (x | y); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x) { return (mbedtls_ct_condition_t) (~x); } #if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4) /* Restore warnings for -Wredundant-decls on gcc */ # pragma GCC diagnostic pop #endif #endif /* MBEDTLS_CONSTANT_TIME_IMPL_H */ webfakes/src/mbedtls/library/psa_crypto_slot_management.h0000644000176200001440000003177014740737024023537 0ustar liggesusers/* * PSA crypto layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H #define PSA_CRYPTO_SLOT_MANAGEMENT_H #include "psa/crypto.h" #include "psa_crypto_core.h" #include "psa_crypto_se.h" /** Range of volatile key identifiers. * * The first #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation * range of key identifiers are reserved for volatile key identifiers. * * If \c id is a a volatile key identifier, #PSA_KEY_ID_VOLATILE_MIN - \c id * indicates the key slot containing the volatile key definition. See * psa_crypto_slot_management.c for details. */ /** The minimum value for a volatile key identifier. */ #define PSA_KEY_ID_VOLATILE_MIN PSA_KEY_ID_VENDOR_MIN /** The maximum value for a volatile key identifier. */ #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) #define PSA_KEY_ID_VOLATILE_MAX (MBEDTLS_PSA_KEY_ID_BUILTIN_MIN - 1) #else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ #define PSA_KEY_ID_VOLATILE_MAX \ (PSA_KEY_ID_VOLATILE_MIN + MBEDTLS_PSA_KEY_SLOT_COUNT - 1) #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ /** Test whether a key identifier is a volatile key identifier. * * \param key_id Key identifier to test. * * \retval 1 * The key identifier is a volatile key identifier. * \retval 0 * The key identifier is not a volatile key identifier. */ static inline int psa_key_id_is_volatile(psa_key_id_t key_id) { return (key_id >= PSA_KEY_ID_VOLATILE_MIN) && (key_id <= PSA_KEY_ID_VOLATILE_MAX); } /** Get the description of a key given its identifier and lock it. * * The descriptions of volatile keys and loaded persistent keys are stored in * key slots. This function returns a pointer to the key slot containing the * description of a key given its identifier. * * In case of a persistent key, the function loads the description of the key * into a key slot if not already done. * * On success, the returned key slot has been registered for reading. * It is the responsibility of the caller to call psa_unregister_read(slot) * when they have finished reading the contents of the slot. * * On failure, `*p_slot` is set to NULL. This ensures that it is always valid * to call psa_unregister_read on the returned slot. * * \param key Key identifier to query. * \param[out] p_slot On success, `*p_slot` contains a pointer to the * key slot containing the description of the key * identified by \p key. * * \retval #PSA_SUCCESS * \p *p_slot contains a pointer to the key slot containing the * description of the key identified by \p key. * The key slot counter has been incremented. * \retval #PSA_ERROR_BAD_STATE * The library has not been initialized. * \retval #PSA_ERROR_INVALID_HANDLE * \p key is not a valid key identifier. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \p key is a persistent key identifier. The implementation does not * have sufficient resources to load the persistent key. This can be * due to a lack of empty key slot, or available memory. * \retval #PSA_ERROR_DOES_NOT_EXIST * There is no key with key identifier \p key. * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot); /** Initialize the key slot structures. * * \retval #PSA_SUCCESS * Currently this function always succeeds. */ psa_status_t psa_initialize_key_slots(void); #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) /* Allow test code to customize the key slice length. We use this in tests * that exhaust the key store to reach a full key store in reasonable time * and memory. * * The length of each slice must be between 1 and * (1 << KEY_ID_SLOT_INDEX_WIDTH) inclusive. * * The length for a given slice index must not change while * the key store is initialized. */ extern size_t (*mbedtls_test_hook_psa_volatile_key_slice_length)( size_t slice_idx); /* The number of volatile key slices. */ size_t psa_key_slot_volatile_slice_count(void); #endif /** Delete all data from key slots in memory. * This function is not thread safe, it wipes every key slot regardless of * state and reader count. It should only be called when no slot is in use. * * This does not affect persistent storage. */ void psa_wipe_all_key_slots(void); /** Find a free key slot and reserve it to be filled with a key. * * This function finds a key slot that is free, * sets its state to PSA_SLOT_FILLING and then returns the slot. * * On success, the key slot's state is PSA_SLOT_FILLING. * It is the responsibility of the caller to change the slot's state to * PSA_SLOT_EMPTY/FULL once key creation has finished. * * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[out] volatile_key_id - If null, reserve a cache slot for * a persistent or built-in key. * - If non-null, allocate a slot for * a volatile key. On success, * \p *volatile_key_id is the * identifier corresponding to the * returned slot. It is the caller's * responsibility to set this key identifier * in the attributes. * \param[out] p_slot On success, a pointer to the slot. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * There were no free key slots. * When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, there was not * enough memory to allocate more slots. * \retval #PSA_ERROR_BAD_STATE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED * This function attempted to operate on a key slot which was in an * unexpected state. */ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, psa_key_slot_t **p_slot); #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) /** Return a key slot to the free list. * * Call this function when a slot obtained from psa_reserve_free_key_slot() * is no longer in use. * * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param slice_idx The slice containing the slot. * This is `slot->slice_index` when the slot * is obtained from psa_reserve_free_key_slot(). * \param slot The key slot. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED * This function attempted to operate on a key slot which was in an * unexpected state. */ psa_status_t psa_free_key_slot(size_t slice_idx, psa_key_slot_t *slot); #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ /** Change the state of a key slot. * * This function changes the state of the key slot from expected_state to * new state. If the state of the slot was not expected_state, the state is * unchanged. * * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[in] slot The key slot. * \param[in] expected_state The current state of the slot. * \param[in] new_state The new state of the slot. * * \retval #PSA_SUCCESS The key slot's state variable is new_state. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was not expected_state. */ static inline psa_status_t psa_key_slot_state_transition( psa_key_slot_t *slot, psa_key_slot_state_t expected_state, psa_key_slot_state_t new_state) { if (slot->state != expected_state) { return PSA_ERROR_CORRUPTION_DETECTED; } slot->state = new_state; return PSA_SUCCESS; } /** Register as a reader of a key slot. * * This function increments the key slot registered reader counter by one. * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[in] slot The key slot. * * \retval #PSA_SUCCESS The key slot registered reader counter was incremented. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The reader counter already reached its maximum value and was not * increased, or the slot's state was not PSA_SLOT_FULL. */ static inline psa_status_t psa_register_read(psa_key_slot_t *slot) { if ((slot->state != PSA_SLOT_FULL) || (slot->var.occupied.registered_readers >= SIZE_MAX)) { return PSA_ERROR_CORRUPTION_DETECTED; } slot->var.occupied.registered_readers++; return PSA_SUCCESS; } /** Unregister from reading a key slot. * * This function decrements the key slot registered reader counter by one. * If the state of the slot is PSA_SLOT_PENDING_DELETION, * and there is only one registered reader (the caller), * this function will call psa_wipe_key_slot(). * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \note To ease the handling of errors in retrieving a key slot * a NULL input pointer is valid, and the function returns * successfully without doing anything in that case. * * \param[in] slot The key slot. * \retval #PSA_SUCCESS * \p slot is NULL or the key slot reader counter has been * decremented (and potentially wiped) successfully. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was neither PSA_SLOT_FULL nor * PSA_SLOT_PENDING_DELETION. * Or a wipe was attempted and the slot's state was not * PSA_SLOT_PENDING_DELETION. * Or registered_readers was equal to 0. */ psa_status_t psa_unregister_read(psa_key_slot_t *slot); /** Wrap a call to psa_unregister_read in the global key slot mutex. * * If threading is disabled, this simply calls psa_unregister_read. * * \note To ease the handling of errors in retrieving a key slot * a NULL input pointer is valid, and the function returns * successfully without doing anything in that case. * * \param[in] slot The key slot. * \retval #PSA_SUCCESS * \p slot is NULL or the key slot reader counter has been * decremented (and potentially wiped) successfully. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was neither PSA_SLOT_FULL nor * PSA_SLOT_PENDING_DELETION. * Or a wipe was attempted and the slot's state was not * PSA_SLOT_PENDING_DELETION. * Or registered_readers was equal to 0. */ psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot); /** Test whether a lifetime designates a key in an external cryptoprocessor. * * \param lifetime The lifetime to test. * * \retval 1 * The lifetime designates an external key. There should be a * registered driver for this lifetime, otherwise the key cannot * be created or manipulated. * \retval 0 * The lifetime designates a key that is volatile or in internal * storage. */ static inline int psa_key_lifetime_is_external(psa_key_lifetime_t lifetime) { return PSA_KEY_LIFETIME_GET_LOCATION(lifetime) != PSA_KEY_LOCATION_LOCAL_STORAGE; } /** Validate a key's location. * * This function checks whether the key's attributes point to a location that * is known to the PSA Core, and returns the driver function table if the key * is to be found in an external location. * * \param[in] lifetime The key lifetime attribute. * \param[out] p_drv On success, when a key is located in external * storage, returns a pointer to the driver table * associated with the key's storage location. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription */ psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime, psa_se_drv_table_entry_t **p_drv); /** Validate the persistence of a key. * * \param[in] lifetime The key lifetime attribute. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED The key is persistent but persistent keys * are not supported. */ psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime); /** Validate a key identifier. * * \param[in] key The key identifier. * \param[in] vendor_ok Non-zero to indicate that key identifiers in the * vendor range are allowed, volatile key identifiers * excepted \c 0 otherwise. * * \retval <> 0 if the key identifier is valid, 0 otherwise. */ int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok); #endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ webfakes/src/mbedtls/library/x509write.c0000644000176200001440000001555214740737024017672 0ustar liggesusers/* * X.509 internal, common functions for writing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_X509_CSR_WRITE_C) || defined(MBEDTLS_X509_CRT_WRITE_C) #include "mbedtls/x509_crt.h" #include "x509_internal.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include #include #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif /* MBEDTLS_PEM_WRITE_C */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "mbedtls/psa_util.h" #include "md_psa.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ #define CHECK_OVERFLOW_ADD(a, b) \ do \ { \ if (a > SIZE_MAX - (b)) \ { \ return MBEDTLS_ERR_X509_BAD_INPUT_DATA; \ } \ a += b; \ } while (0) int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions, const mbedtls_x509_san_list *san_list) { int ret = 0; const mbedtls_x509_san_list *cur; unsigned char *buf; unsigned char *p; size_t len; size_t buflen = 0; /* Determine the maximum size of the SubjectAltName list */ for (cur = san_list; cur != NULL; cur = cur->next) { /* Calculate size of the required buffer */ switch (cur->node.type) { case MBEDTLS_X509_SAN_DNS_NAME: case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: case MBEDTLS_X509_SAN_IP_ADDRESS: case MBEDTLS_X509_SAN_RFC822_NAME: /* length of value for each name entry, * maximum 4 bytes for the length field, * 1 byte for the tag/type. */ CHECK_OVERFLOW_ADD(buflen, cur->node.san.unstructured_name.len); CHECK_OVERFLOW_ADD(buflen, 4 + 1); break; case MBEDTLS_X509_SAN_DIRECTORY_NAME: { const mbedtls_asn1_named_data *chunk = &cur->node.san.directory_name; while (chunk != NULL) { // Max 4 bytes for length, +1 for tag, // additional 4 max for length, +1 for tag. // See x509_write_name for more information. CHECK_OVERFLOW_ADD(buflen, 4 + 1 + 4 + 1); CHECK_OVERFLOW_ADD(buflen, chunk->oid.len); CHECK_OVERFLOW_ADD(buflen, chunk->val.len); chunk = chunk->next; } CHECK_OVERFLOW_ADD(buflen, 4 + 1); break; } default: /* Not supported - return. */ return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } } /* Add the extra length field and tag */ CHECK_OVERFLOW_ADD(buflen, 4 + 1); /* Allocate buffer */ buf = mbedtls_calloc(1, buflen); if (buf == NULL) { return MBEDTLS_ERR_ASN1_ALLOC_FAILED; } p = buf + buflen; /* Write ASN.1-based structure */ cur = san_list; len = 0; while (cur != NULL) { size_t single_san_len = 0; switch (cur->node.type) { case MBEDTLS_X509_SAN_DNS_NAME: case MBEDTLS_X509_SAN_RFC822_NAME: case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: case MBEDTLS_X509_SAN_IP_ADDRESS: { const unsigned char *unstructured_name = (const unsigned char *) cur->node.san.unstructured_name.p; size_t unstructured_name_len = cur->node.san.unstructured_name.len; MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_raw_buffer( &p, buf, unstructured_name, unstructured_name_len)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_len( &p, buf, unstructured_name_len)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_tag( &p, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type)); } break; case MBEDTLS_X509_SAN_DIRECTORY_NAME: MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_x509_write_names(&p, buf, (mbedtls_asn1_named_data *) & cur->node .san.directory_name)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_len(&p, buf, single_san_len)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_X509_SAN_DIRECTORY_NAME)); break; default: /* Error out on an unsupported SAN */ ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; goto cleanup; } cur = cur->next; /* check for overflow */ if (len > SIZE_MAX - single_san_len) { ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; goto cleanup; } len += single_san_len; } MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); ret = mbedtls_x509_set_extension(extensions, MBEDTLS_OID_SUBJECT_ALT_NAME, MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME), 0, buf + buflen - len, len); /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list * was incorrectly calculated and memory is corrupted. */ if (p < buf) { ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } cleanup: mbedtls_free(buf); return ret; } #endif /* MBEDTLS_X509_CSR_WRITE_C || MBEDTLS_X509_CRT_WRITE_C */ webfakes/src/mbedtls/library/x509_create.c0000644000176200001440000004653314740737024020145 0ustar liggesusers/* * X.509 base functions for creating certificates / CSRs * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_X509_CREATE_C) #include "x509_internal.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include #include "mbedtls/platform.h" #include "mbedtls/asn1.h" /* Structure linking OIDs for X.509 DN AttributeTypes to their * string representations and default string encodings used by Mbed TLS. */ typedef struct { const char *name; /* String representation of AttributeType, e.g. * "CN" or "emailAddress". */ size_t name_len; /* Length of 'name', without trailing 0 byte. */ const char *oid; /* String representation of OID of AttributeType, * as per RFC 5280, Appendix A.1. encoded as per * X.690 */ int default_tag; /* The default character encoding used for the * given attribute type, e.g. * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ } x509_attr_descriptor_t; #define ADD_STRLEN(s) s, sizeof(s) - 1 /* X.509 DN attributes from RFC 5280, Appendix A.1. */ static const x509_attr_descriptor_t x509_attrs[] = { { ADD_STRLEN("CN"), MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("commonName"), MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("C"), MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("countryName"), MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("O"), MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("organizationName"), MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("L"), MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("locality"), MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("R"), MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, { ADD_STRLEN("OU"), MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("organizationalUnitName"), MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("ST"), MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("stateOrProvinceName"), MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("emailAddress"), MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, { ADD_STRLEN("serialNumber"), MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("postalAddress"), MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("postalCode"), MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("dnQualifier"), MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("title"), MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("surName"), MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("SN"), MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("givenName"), MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("GN"), MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("initials"), MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("pseudonym"), MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("generationQualifier"), MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("domainComponent"), MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, { ADD_STRLEN("DC"), MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, { NULL, 0, NULL, MBEDTLS_ASN1_NULL } }; static const x509_attr_descriptor_t *x509_attr_descr_from_name(const char *name, size_t name_len) { const x509_attr_descriptor_t *cur; for (cur = x509_attrs; cur->name != NULL; cur++) { if (cur->name_len == name_len && strncmp(cur->name, name, name_len) == 0) { break; } } if (cur->name == NULL) { return NULL; } return cur; } static int hex_to_int(char c) { return ('0' <= c && c <= '9') ? (c - '0') : ('a' <= c && c <= 'f') ? (c - 'a' + 10) : ('A' <= c && c <= 'F') ? (c - 'A' + 10) : -1; } static int hexpair_to_int(const char *hexpair) { int n1 = hex_to_int(*hexpair); int n2 = hex_to_int(*(hexpair + 1)); if (n1 != -1 && n2 != -1) { return (n1 << 4) | n2; } else { return -1; } } static int parse_attribute_value_string(const char *s, int len, unsigned char *data, size_t *data_len) { const char *c; const char *end = s + len; unsigned char *d = data; int n; for (c = s; c < end; c++) { if (*c == '\\') { c++; /* Check for valid escaped characters as per RFC 4514 Section 3 */ if (c + 1 < end && (n = hexpair_to_int(c)) != -1) { if (n == 0) { return MBEDTLS_ERR_X509_INVALID_NAME; } *(d++) = n; c++; } else if (c < end && strchr(" ,=+<>#;\"\\", *c)) { *(d++) = *c; } else { return MBEDTLS_ERR_X509_INVALID_NAME; } } else { *(d++) = *c; } if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) { return MBEDTLS_ERR_X509_INVALID_NAME; } } *data_len = (size_t) (d - data); return 0; } /** Parse a hexstring containing a DER-encoded string. * * \param s A string of \p len bytes hexadecimal digits. * \param len Number of bytes to read from \p s. * \param data Output buffer of size \p data_size. * On success, it contains the payload that's DER-encoded * in the input (content without the tag and length). * If the DER tag is a string tag, the payload is guaranteed * not to contain null bytes. * \param data_size Length of the \p data buffer. * \param data_len On success, the length of the parsed string. * It is guaranteed to be less than * #MBEDTLS_X509_MAX_DN_NAME_SIZE. * \param tag The ASN.1 tag that the payload in \p data is encoded in. * * \retval 0 on success. * \retval #MBEDTLS_ERR_X509_INVALID_NAME if \p s does not contain * a valid hexstring, * or if the decoded hexstring is not valid DER, * or if the payload does not fit in \p data, * or if the payload is more than * #MBEDTLS_X509_MAX_DN_NAME_SIZE bytes, * of if \p *tag is an ASN.1 string tag and the payload * contains a null byte. * \retval #MBEDTLS_ERR_X509_ALLOC_FAILED on low memory. */ static int parse_attribute_value_hex_der_encoded(const char *s, size_t len, unsigned char *data, size_t data_size, size_t *data_len, int *tag) { /* Step 1: preliminary length checks. */ /* Each byte is encoded by exactly two hexadecimal digits. */ if (len % 2 != 0) { /* Odd number of hex digits */ return MBEDTLS_ERR_X509_INVALID_NAME; } size_t const der_length = len / 2; if (der_length > MBEDTLS_X509_MAX_DN_NAME_SIZE + 4) { /* The payload would be more than MBEDTLS_X509_MAX_DN_NAME_SIZE * (after subtracting the ASN.1 tag and length). Reject this early * to avoid allocating a large intermediate buffer. */ return MBEDTLS_ERR_X509_INVALID_NAME; } if (der_length < 1) { /* Avoid empty-buffer shenanigans. A valid DER encoding is never * empty. */ return MBEDTLS_ERR_X509_INVALID_NAME; } /* Step 2: Decode the hex string into an intermediate buffer. */ unsigned char *der = mbedtls_calloc(1, der_length); if (der == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } /* Beyond this point, der needs to be freed on exit. */ for (size_t i = 0; i < der_length; i++) { int c = hexpair_to_int(s + 2 * i); if (c < 0) { goto error; } der[i] = c; } /* Step 3: decode the DER. */ /* We've checked that der_length >= 1 above. */ *tag = der[0]; { unsigned char *p = der + 1; if (mbedtls_asn1_get_len(&p, der + der_length, data_len) != 0) { goto error; } /* Now p points to the first byte of the payload inside der, * and *data_len is the length of the payload. */ /* Step 4: payload validation */ if (*data_len > MBEDTLS_X509_MAX_DN_NAME_SIZE) { goto error; } /* Strings must not contain null bytes. */ if (MBEDTLS_ASN1_IS_STRING_TAG(*tag)) { for (size_t i = 0; i < *data_len; i++) { if (p[i] == 0) { goto error; } } } /* Step 5: output the payload. */ if (*data_len > data_size) { goto error; } memcpy(data, p, *data_len); } mbedtls_free(der); return 0; error: mbedtls_free(der); return MBEDTLS_ERR_X509_INVALID_NAME; } int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name) { int ret = MBEDTLS_ERR_X509_INVALID_NAME; int parse_ret = 0; const char *s = name, *c = s; const char *end = s + strlen(s); mbedtls_asn1_buf oid = { .p = NULL, .len = 0, .tag = MBEDTLS_ASN1_NULL }; const x509_attr_descriptor_t *attr_descr = NULL; int in_attr_type = 1; int tag; int numericoid = 0; unsigned char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; size_t data_len = 0; /* Clear existing chain if present */ mbedtls_asn1_free_named_data_list(head); while (c <= end) { if (in_attr_type && *c == '=') { if ((attr_descr = x509_attr_descr_from_name(s, (size_t) (c - s))) == NULL) { if ((mbedtls_oid_from_numeric_string(&oid, s, (size_t) (c - s))) != 0) { return MBEDTLS_ERR_X509_INVALID_NAME; } else { numericoid = 1; } } else { oid.len = strlen(attr_descr->oid); oid.p = mbedtls_calloc(1, oid.len); memcpy(oid.p, attr_descr->oid, oid.len); numericoid = 0; } s = c + 1; in_attr_type = 0; } if (!in_attr_type && ((*c == ',' && *(c-1) != '\\') || c == end)) { if (s == c) { mbedtls_free(oid.p); return MBEDTLS_ERR_X509_INVALID_NAME; } else if (*s == '#') { /* We know that c >= s (loop invariant) and c != s (in this * else branch), hence c - s - 1 >= 0. */ parse_ret = parse_attribute_value_hex_der_encoded( s + 1, (size_t) (c - s) - 1, data, sizeof(data), &data_len, &tag); if (parse_ret != 0) { mbedtls_free(oid.p); return parse_ret; } } else { if (numericoid) { mbedtls_free(oid.p); return MBEDTLS_ERR_X509_INVALID_NAME; } else { if ((parse_ret = parse_attribute_value_string(s, (int) (c - s), data, &data_len)) != 0) { mbedtls_free(oid.p); return parse_ret; } tag = attr_descr->default_tag; } } mbedtls_asn1_named_data *cur = mbedtls_asn1_store_named_data(head, (char *) oid.p, oid.len, (unsigned char *) data, data_len); mbedtls_free(oid.p); oid.p = NULL; if (cur == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } // set tagType cur->val.tag = tag; while (c < end && *(c + 1) == ' ') { c++; } s = c + 1; in_attr_type = 1; /* Successfully parsed one name, update ret to success */ ret = 0; } c++; } if (oid.p != NULL) { mbedtls_free(oid.p); } return ret; } /* The first byte of the value in the mbedtls_asn1_named_data structure is reserved * to store the critical boolean for us */ int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len) { mbedtls_asn1_named_data *cur; if (val_len > (SIZE_MAX - 1)) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } if ((cur = mbedtls_asn1_store_named_data(head, oid, oid_len, NULL, val_len + 1)) == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } cur->val.p[0] = critical; memcpy(cur->val.p + 1, val, val_len); return 0; } /* * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ static int x509_write_name(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *cur_name) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; const char *oid = (const char *) cur_name->oid.p; size_t oid_len = cur_name->oid.len; const unsigned char *name = cur_name->val.p; size_t name_len = cur_name->val.len; // Write correct string tag and value MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tagged_string(p, start, cur_name->val.tag, (const char *) name, name_len)); // Write OID // MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); return (int) len; } int mbedtls_x509_write_names(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *first) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; mbedtls_asn1_named_data *cur = first; while (cur != NULL) { MBEDTLS_ASN1_CHK_ADD(len, x509_write_name(p, start, cur)); cur = cur->next; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start, const char *oid, size_t oid_len, unsigned char *sig, size_t size, mbedtls_pk_type_t pk_alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int write_null_par; size_t len = 0; if (*p < start || (size_t) (*p - start) < size) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } len = size; (*p) -= len; memcpy(*p, sig, len); if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = 0; len += 1; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING)); // Write OID // if (pk_alg == MBEDTLS_PK_ECDSA) { /* * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and * https://www.rfc-editor.org/rfc/rfc5758#section-3. */ write_null_par = 0; } else { write_null_par = 1; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, 0, write_null_par)); return (int) len; } static int x509_write_extension(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *ext) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->val.p + 1, ext->val.len - 1)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->val.len - 1)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING)); if (ext->val.p[0] != 0) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(p, start, 1)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->oid.p, ext->oid.len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->oid.len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } /* * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING * -- contains the DER encoding of an ASN.1 value * -- corresponding to the extension type identified * -- by extnID * } */ int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *first) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; mbedtls_asn1_named_data *cur_ext = first; while (cur_ext != NULL) { MBEDTLS_ASN1_CHK_ADD(len, x509_write_extension(p, start, cur_ext)); cur_ext = cur_ext->next; } return (int) len; } #endif /* MBEDTLS_X509_CREATE_C */ webfakes/src/mbedtls/library/mps_trace.h0000644000176200001440000001266014740737024020071 0ustar liggesusers/* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** * \file mps_trace.h * * \brief Tracing module for MPS */ #ifndef MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H #define MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H #include "common.h" #include "mps_common.h" #include "mps_trace.h" #include "mbedtls/platform.h" #if defined(MBEDTLS_MPS_ENABLE_TRACE) /* * Adapt this to enable/disable tracing output * from the various layers of the MPS. */ #define MBEDTLS_MPS_TRACE_ENABLE_LAYER_1 #define MBEDTLS_MPS_TRACE_ENABLE_LAYER_2 #define MBEDTLS_MPS_TRACE_ENABLE_LAYER_3 #define MBEDTLS_MPS_TRACE_ENABLE_LAYER_4 #define MBEDTLS_MPS_TRACE_ENABLE_READER #define MBEDTLS_MPS_TRACE_ENABLE_WRITER /* * To use the existing trace module, only change * MBEDTLS_MPS_TRACE_ENABLE_XXX above, but don't modify the * rest of this file. */ typedef enum { MBEDTLS_MPS_TRACE_TYPE_COMMENT, MBEDTLS_MPS_TRACE_TYPE_CALL, MBEDTLS_MPS_TRACE_TYPE_ERROR, MBEDTLS_MPS_TRACE_TYPE_RETURN } mbedtls_mps_trace_type; #define MBEDTLS_MPS_TRACE_BIT_LAYER_1 1 #define MBEDTLS_MPS_TRACE_BIT_LAYER_2 2 #define MBEDTLS_MPS_TRACE_BIT_LAYER_3 3 #define MBEDTLS_MPS_TRACE_BIT_LAYER_4 4 #define MBEDTLS_MPS_TRACE_BIT_WRITER 5 #define MBEDTLS_MPS_TRACE_BIT_READER 6 #if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_1) #define MBEDTLS_MPS_TRACE_MASK_LAYER_1 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_1) #else #define MBEDTLS_MPS_TRACE_MASK_LAYER_1 0 #endif #if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_2) #define MBEDTLS_MPS_TRACE_MASK_LAYER_2 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_2) #else #define MBEDTLS_MPS_TRACE_MASK_LAYER_2 0 #endif #if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_3) #define MBEDTLS_MPS_TRACE_MASK_LAYER_3 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_3) #else #define MBEDTLS_MPS_TRACE_MASK_LAYER_3 0 #endif #if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_4) #define MBEDTLS_MPS_TRACE_MASK_LAYER_4 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_4) #else #define MBEDTLS_MPS_TRACE_MASK_LAYER_4 0 #endif #if defined(MBEDTLS_MPS_TRACE_ENABLE_READER) #define MBEDTLS_MPS_TRACE_MASK_READER (1u << MBEDTLS_MPS_TRACE_BIT_READER) #else #define MBEDTLS_MPS_TRACE_MASK_READER 0 #endif #if defined(MBEDTLS_MPS_TRACE_ENABLE_WRITER) #define MBEDTLS_MPS_TRACE_MASK_WRITER (1u << MBEDTLS_MPS_TRACE_BIT_WRITER) #else #define MBEDTLS_MPS_TRACE_MASK_WRITER 0 #endif #define MBEDTLS_MPS_TRACE_MASK (MBEDTLS_MPS_TRACE_MASK_LAYER_1 | \ MBEDTLS_MPS_TRACE_MASK_LAYER_2 | \ MBEDTLS_MPS_TRACE_MASK_LAYER_3 | \ MBEDTLS_MPS_TRACE_MASK_LAYER_4 | \ MBEDTLS_MPS_TRACE_MASK_READER | \ MBEDTLS_MPS_TRACE_MASK_WRITER) /* We have to avoid globals because E-ACSL chokes on them... * Wrap everything in stub functions. */ int mbedtls_mps_trace_get_depth(void); void mbedtls_mps_trace_inc_depth(void); void mbedtls_mps_trace_dec_depth(void); void mbedtls_mps_trace_color(int id); void mbedtls_mps_trace_indent(int level, mbedtls_mps_trace_type ty); void mbedtls_mps_trace_print_msg(int id, int line, const char *format, ...); #define MBEDTLS_MPS_TRACE(type, ...) \ do { \ if (!(MBEDTLS_MPS_TRACE_MASK & (1u << mbedtls_mps_trace_id))) \ break; \ mbedtls_mps_trace_indent(mbedtls_mps_trace_get_depth(), type); \ mbedtls_mps_trace_color(mbedtls_mps_trace_id); \ mbedtls_mps_trace_print_msg(mbedtls_mps_trace_id, __LINE__, __VA_ARGS__); \ mbedtls_mps_trace_color(0); \ } while (0) #define MBEDTLS_MPS_TRACE_INIT(...) \ do { \ if (!(MBEDTLS_MPS_TRACE_MASK & (1u << mbedtls_mps_trace_id))) \ break; \ MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_CALL, __VA_ARGS__); \ mbedtls_mps_trace_inc_depth(); \ } while (0) #define MBEDTLS_MPS_TRACE_END(val) \ do { \ if (!(MBEDTLS_MPS_TRACE_MASK & (1u << mbedtls_mps_trace_id))) \ break; \ MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_RETURN, "%d (-%#04x)", \ (int) (val), -((unsigned) (val))); \ mbedtls_mps_trace_dec_depth(); \ } while (0) #define MBEDTLS_MPS_TRACE_RETURN(val) \ do { \ /* Breaks tail recursion. */ \ int ret__ = val; \ MBEDTLS_MPS_TRACE_END(ret__); \ return ret__; \ } while (0) #else /* MBEDTLS_MPS_TRACE */ #define MBEDTLS_MPS_TRACE(type, ...) do { } while (0) #define MBEDTLS_MPS_TRACE_INIT(...) do { } while (0) #define MBEDTLS_MPS_TRACE_END do { } while (0) #define MBEDTLS_MPS_TRACE_RETURN(val) return val; #endif /* MBEDTLS_MPS_TRACE */ #endif /* MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H */ webfakes/src/mbedtls/library/threading.c0000644000176200001440000001435314740737024020055 0ustar liggesusers/* * Threading abstraction layer * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Ensure gmtime_r is available even with -std=c99; must be defined before * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms. */ #if !defined(_POSIX_C_SOURCE) #define _POSIX_C_SOURCE 200112L #endif #include "common.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) #if !defined(_WIN32) && (defined(unix) || \ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ defined(__MACH__))) #include #endif /* !_WIN32 && (unix || __unix || __unix__ || * (__APPLE__ && __MACH__)) */ #if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \ (defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \ _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L)) /* * This is a convenience shorthand macro to avoid checking the long * preprocessor conditions above. Ideally, we could expose this macro in * platform_util.h and simply use it in platform_util.c, threading.c and * threading.h. However, this macro is not part of the Mbed TLS public API, so * we keep it private by only defining it in this file */ #if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) #define THREADING_USE_GMTIME #endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ #endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ #endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ #if defined(MBEDTLS_THREADING_PTHREAD) static void threading_mutex_init_pthread(mbedtls_threading_mutex_t *mutex) { if (mutex == NULL) { return; } /* One problem here is that calling lock on a pthread mutex without first * having initialised it is undefined behaviour. Obviously we cannot check * this here in a thread safe manner without a significant performance * hit, so state transitions are checked in tests only via the state * variable. Please make sure any new mutex that gets added is exercised in * tests; see tests/src/threading_helpers.c for more details. */ (void) pthread_mutex_init(&mutex->mutex, NULL); } static void threading_mutex_free_pthread(mbedtls_threading_mutex_t *mutex) { if (mutex == NULL) { return; } (void) pthread_mutex_destroy(&mutex->mutex); } static int threading_mutex_lock_pthread(mbedtls_threading_mutex_t *mutex) { if (mutex == NULL) { return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; } if (pthread_mutex_lock(&mutex->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } return 0; } static int threading_mutex_unlock_pthread(mbedtls_threading_mutex_t *mutex) { if (mutex == NULL) { return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; } if (pthread_mutex_unlock(&mutex->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } return 0; } void (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *) = threading_mutex_init_pthread; void (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *) = threading_mutex_free_pthread; int (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *) = threading_mutex_lock_pthread; int (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *) = threading_mutex_unlock_pthread; /* * With pthreads we can statically initialize mutexes */ #define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } #endif /* MBEDTLS_THREADING_PTHREAD */ #if defined(MBEDTLS_THREADING_ALT) static int threading_mutex_fail(mbedtls_threading_mutex_t *mutex) { ((void) mutex); return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; } static void threading_mutex_dummy(mbedtls_threading_mutex_t *mutex) { ((void) mutex); return; } void (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *) = threading_mutex_dummy; void (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *) = threading_mutex_dummy; int (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *) = threading_mutex_fail; int (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *) = threading_mutex_fail; /* * Set functions pointers and initialize global mutexes */ void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *), void (*mutex_free)(mbedtls_threading_mutex_t *), int (*mutex_lock)(mbedtls_threading_mutex_t *), int (*mutex_unlock)(mbedtls_threading_mutex_t *)) { mbedtls_mutex_init = mutex_init; mbedtls_mutex_free = mutex_free; mbedtls_mutex_lock = mutex_lock; mbedtls_mutex_unlock = mutex_unlock; #if defined(MBEDTLS_FS_IO) mbedtls_mutex_init(&mbedtls_threading_readdir_mutex); #endif #if defined(THREADING_USE_GMTIME) mbedtls_mutex_init(&mbedtls_threading_gmtime_mutex); #endif #if defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_mutex_init(&mbedtls_threading_key_slot_mutex); mbedtls_mutex_init(&mbedtls_threading_psa_globaldata_mutex); mbedtls_mutex_init(&mbedtls_threading_psa_rngdata_mutex); #endif } /* * Free global mutexes */ void mbedtls_threading_free_alt(void) { #if defined(MBEDTLS_FS_IO) mbedtls_mutex_free(&mbedtls_threading_readdir_mutex); #endif #if defined(THREADING_USE_GMTIME) mbedtls_mutex_free(&mbedtls_threading_gmtime_mutex); #endif #if defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_mutex_free(&mbedtls_threading_key_slot_mutex); mbedtls_mutex_free(&mbedtls_threading_psa_globaldata_mutex); mbedtls_mutex_free(&mbedtls_threading_psa_rngdata_mutex); #endif } #endif /* MBEDTLS_THREADING_ALT */ /* * Define global mutexes */ #ifndef MUTEX_INIT #define MUTEX_INIT #endif #if defined(MBEDTLS_FS_IO) mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; #endif #if defined(THREADING_USE_GMTIME) mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; #endif #if defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex MUTEX_INIT; mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex MUTEX_INIT; mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex MUTEX_INIT; #endif #endif /* MBEDTLS_THREADING_C */ webfakes/src/mbedtls/library/x509_internal.h0000644000176200001440000001035214740737024020511 0ustar liggesusers/** * \file x509.h * * \brief Internal part of the public "x509.h". */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_INTERNAL_H #define MBEDTLS_X509_INTERNAL_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/x509.h" #include "mbedtls/asn1.h" #include "pk_internal.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur); int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg); int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg, mbedtls_x509_buf *params); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, int *salt_len); #endif int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig); int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, void **sig_opts); int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, mbedtls_x509_time *t); int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *serial); int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext, int tag); #if !defined(MBEDTLS_X509_REMOVE_INFO) int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, const void *sig_opts); #endif int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name); int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len); int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *first); int mbedtls_x509_write_names(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *first); int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start, const char *oid, size_t oid_len, unsigned char *sig, size_t size, mbedtls_pk_type_t pk_alg); int mbedtls_x509_get_ns_cert_type(unsigned char **p, const unsigned char *end, unsigned char *ns_cert_type); int mbedtls_x509_get_key_usage(unsigned char **p, const unsigned char *end, unsigned int *key_usage); int mbedtls_x509_get_subject_alt_name(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name); int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name); int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, const mbedtls_x509_sequence *subject_alt_name, const char *prefix); int mbedtls_x509_info_cert_type(char **buf, size_t *size, unsigned char ns_cert_type); int mbedtls_x509_info_key_usage(char **buf, size_t *size, unsigned int key_usage); int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions, const mbedtls_x509_san_list *san_list); #endif /* MBEDTLS_X509_INTERNAL_H */ webfakes/src/mbedtls/library/psa_crypto_mac.c0000644000176200001440000003526014740737024021113 0ustar liggesusers/* * PSA MAC layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa_crypto_core.h" #include "psa_crypto_cipher.h" #include "psa_crypto_mac.h" #include #include #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) static psa_status_t psa_hmac_abort_internal( mbedtls_psa_hmac_operation_t *hmac) { mbedtls_platform_zeroize(hmac->opad, sizeof(hmac->opad)); return psa_hash_abort(&hmac->hash_ctx); } static psa_status_t psa_hmac_setup_internal( mbedtls_psa_hmac_operation_t *hmac, const uint8_t *key, size_t key_length, psa_algorithm_t hash_alg) { uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; size_t i; size_t hash_size = PSA_HASH_LENGTH(hash_alg); size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); psa_status_t status; hmac->alg = hash_alg; /* Sanity checks on block_size, to guarantee that there won't be a buffer * overflow below. This should never trigger if the hash algorithm * is implemented correctly. */ /* The size checks against the ipad and opad buffers cannot be written * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )` * because that triggers -Wlogical-op on GCC 7.3. */ if (block_size > sizeof(ipad)) { return PSA_ERROR_NOT_SUPPORTED; } if (block_size > sizeof(hmac->opad)) { return PSA_ERROR_NOT_SUPPORTED; } if (block_size < hash_size) { return PSA_ERROR_NOT_SUPPORTED; } if (key_length > block_size) { status = psa_hash_compute(hash_alg, key, key_length, ipad, sizeof(ipad), &key_length); if (status != PSA_SUCCESS) { goto cleanup; } } /* A 0-length key is not commonly used in HMAC when used as a MAC, * but it is permitted. It is common when HMAC is used in HKDF, for * example. Don't call `memcpy` in the 0-length because `key` could be * an invalid pointer which would make the behavior undefined. */ else if (key_length != 0) { memcpy(ipad, key, key_length); } /* ipad contains the key followed by garbage. Xor and fill with 0x36 * to create the ipad value. */ for (i = 0; i < key_length; i++) { ipad[i] ^= 0x36; } memset(ipad + key_length, 0x36, block_size - key_length); /* Copy the key material from ipad to opad, flipping the requisite bits, * and filling the rest of opad with the requisite constant. */ for (i = 0; i < key_length; i++) { hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C; } memset(hmac->opad + key_length, 0x5C, block_size - key_length); status = psa_hash_setup(&hmac->hash_ctx, hash_alg); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_hash_update(&hmac->hash_ctx, ipad, block_size); cleanup: mbedtls_platform_zeroize(ipad, sizeof(ipad)); return status; } static psa_status_t psa_hmac_update_internal( mbedtls_psa_hmac_operation_t *hmac, const uint8_t *data, size_t data_length) { return psa_hash_update(&hmac->hash_ctx, data, data_length); } static psa_status_t psa_hmac_finish_internal( mbedtls_psa_hmac_operation_t *hmac, uint8_t *mac, size_t mac_size) { uint8_t tmp[PSA_HASH_MAX_SIZE]; psa_algorithm_t hash_alg = hmac->alg; size_t hash_size = 0; size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); psa_status_t status; status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size); if (status != PSA_SUCCESS) { return status; } /* From here on, tmp needs to be wiped. */ status = psa_hash_setup(&hmac->hash_ctx, hash_alg); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&hmac->hash_ctx, hmac->opad, block_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&hmac->hash_ctx, tmp, hash_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size); if (status != PSA_SUCCESS) { goto exit; } memcpy(mac, tmp, mac_size); exit: mbedtls_platform_zeroize(tmp, hash_size); return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) static psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(PSA_WANT_KEY_TYPE_DES) /* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept * to do CMAC with pure DES, so return NOT_SUPPORTED here. */ if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES && (psa_get_key_bits(attributes) == 64 || psa_get_key_bits(attributes) == 128)) { return PSA_ERROR_NOT_SUPPORTED; } #endif const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_psa( PSA_ALG_CMAC, psa_get_key_type(attributes), psa_get_key_bits(attributes), NULL); if (cipher_info == NULL) { return PSA_ERROR_NOT_SUPPORTED; } ret = mbedtls_cipher_setup(&operation->ctx.cmac, cipher_info); if (ret != 0) { goto exit; } ret = mbedtls_cipher_cmac_starts(&operation->ctx.cmac, key_buffer, psa_get_key_bits(attributes)); exit: return mbedtls_to_psa_error(ret); } #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) /* Initialize this driver's MAC operation structure. Once this function has been * called, mbedtls_psa_mac_abort can run and will do the right thing. */ static psa_status_t mac_init( mbedtls_psa_mac_operation_t *operation, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; operation->alg = alg; #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { mbedtls_cipher_init(&operation->ctx.cmac); status = PSA_SUCCESS; } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(operation->alg)) { /* We'll set up the hash operation later in psa_hmac_setup_internal. */ operation->ctx.hmac.alg = 0; status = PSA_SUCCESS; } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { (void) operation; status = PSA_ERROR_NOT_SUPPORTED; } if (status != PSA_SUCCESS) { memset(operation, 0, sizeof(*operation)); } return status; } psa_status_t mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t *operation) { if (operation->alg == 0) { /* The object has (apparently) been initialized but it is not * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } else #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { mbedtls_cipher_free(&operation->ctx.cmac); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(operation->alg)) { psa_hmac_abort_internal(&operation->ctx.hmac); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { /* Sanity check (shouldn't happen: operation->alg should * always have been initialized to a valid value). */ goto bad_state; } operation->alg = 0; return PSA_SUCCESS; bad_state: /* If abort is called on an uninitialized object, we can't trust * anything. Wipe the object in case it contains confidential data. * This may result in a memory leak if a pointer gets overwritten, * but it's too late to do anything about this. */ memset(operation, 0, sizeof(*operation)); return PSA_ERROR_BAD_STATE; } static psa_status_t psa_mac_setup(mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* A context must be freshly initialized before it can be set up. */ if (operation->alg != 0) { return PSA_ERROR_BAD_STATE; } status = mac_init(operation, alg); if (status != PSA_SUCCESS) { return status; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) { /* Key buffer size for CMAC is dictated by the key bits set on the * attributes, and previously validated by the core on key import. */ (void) key_buffer_size; status = cmac_setup(operation, attributes, key_buffer); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(alg)) { status = psa_hmac_setup_internal(&operation->ctx.hmac, key_buffer, key_buffer_size, PSA_ALG_HMAC_GET_HASH(alg)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { (void) attributes; (void) key_buffer; (void) key_buffer_size; status = PSA_ERROR_NOT_SUPPORTED; } if (status != PSA_SUCCESS) { mbedtls_psa_mac_abort(operation); } return status; } psa_status_t mbedtls_psa_mac_sign_setup( mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { return psa_mac_setup(operation, attributes, key_buffer, key_buffer_size, alg); } psa_status_t mbedtls_psa_mac_verify_setup( mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { return psa_mac_setup(operation, attributes, key_buffer, key_buffer_size, alg); } psa_status_t mbedtls_psa_mac_update( mbedtls_psa_mac_operation_t *operation, const uint8_t *input, size_t input_length) { if (operation->alg == 0) { return PSA_ERROR_BAD_STATE; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { return mbedtls_to_psa_error( mbedtls_cipher_cmac_update(&operation->ctx.cmac, input, input_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(operation->alg)) { return psa_hmac_update_internal(&operation->ctx.hmac, input, input_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { /* This shouldn't happen if `operation` was initialized by * a setup function. */ (void) input; (void) input_length; return PSA_ERROR_BAD_STATE; } } static psa_status_t psa_mac_finish_internal( mbedtls_psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE]; int ret = mbedtls_cipher_cmac_finish(&operation->ctx.cmac, tmp); if (ret == 0) { memcpy(mac, tmp, mac_size); } mbedtls_platform_zeroize(tmp, sizeof(tmp)); return mbedtls_to_psa_error(ret); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(operation->alg)) { return psa_hmac_finish_internal(&operation->ctx.hmac, mac, mac_size); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { /* This shouldn't happen if `operation` was initialized by * a setup function. */ (void) operation; (void) mac; (void) mac_size; return PSA_ERROR_BAD_STATE; } } psa_status_t mbedtls_psa_mac_sign_finish( mbedtls_psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->alg == 0) { return PSA_ERROR_BAD_STATE; } status = psa_mac_finish_internal(operation, mac, mac_size); if (status == PSA_SUCCESS) { *mac_length = mac_size; } return status; } psa_status_t mbedtls_psa_mac_verify_finish( mbedtls_psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length) { uint8_t actual_mac[PSA_MAC_MAX_SIZE]; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->alg == 0) { return PSA_ERROR_BAD_STATE; } /* Consistency check: requested MAC length fits our local buffer */ if (mac_length > sizeof(actual_mac)) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_mac_finish_internal(operation, actual_mac, mac_length); if (status != PSA_SUCCESS) { goto cleanup; } if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } cleanup: mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac)); return status; } psa_status_t mbedtls_psa_mac_compute( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT; status = psa_mac_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } if (input_length > 0) { status = mbedtls_psa_mac_update(&operation, input, input_length); if (status != PSA_SUCCESS) { goto exit; } } status = psa_mac_finish_internal(&operation, mac, mac_size); if (status == PSA_SUCCESS) { *mac_length = mac_size; } exit: mbedtls_psa_mac_abort(&operation); return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/block_cipher_internal.h0000644000176200001440000000651014740737024022431 0ustar liggesusers/** * \file block_cipher_internal.h * * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks, * for use by the GCM and CCM modules. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BLOCK_CIPHER_INTERNAL_H #define MBEDTLS_BLOCK_CIPHER_INTERNAL_H #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #include "mbedtls/block_cipher.h" #ifdef __cplusplus extern "C" { #endif /** * \brief Initialize the context. * This must be the first API call before using the context. * * \param ctx The context to initialize. */ static inline void mbedtls_block_cipher_init(mbedtls_block_cipher_context_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } /** * \brief Set the block cipher to use with this context. * This must be called after mbedtls_block_cipher_init(). * * \param ctx The context to set up. * \param cipher_id The identifier of the cipher to use. * This must be either AES, ARIA or Camellia. * Warning: this is a ::mbedtls_cipher_id_t, * not a ::mbedtls_block_cipher_id_t! * * \retval \c 0 on success. * \retval #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if \p cipher_id was * invalid. */ int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx, mbedtls_cipher_id_t cipher_id); /** * \brief Set the key into the context. * * \param ctx The context to configure. * \param key The buffer holding the key material. * \param key_bitlen The size of the key in bits. * * \retval \c 0 on success. * \retval #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not * properly set up before calling this function. * \retval One of #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH, * #MBEDTLS_ERR_ARIA_BAD_INPUT_DATA, * #MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA if \p key_bitlen is * invalid. */ int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx, const unsigned char *key, unsigned key_bitlen); /** * \brief Encrypt one block (16 bytes) with the configured key. * * \param ctx The context holding the key. * \param input The buffer holding the input block. Must be 16 bytes. * \param output The buffer to which the output block will be written. * Must be writable and 16 bytes long. * This must either not overlap with \p input, or be equal. * * \retval \c 0 on success. * \retval #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not * properly set up before calling this function. * \retval Another negative value if encryption failed. */ int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx, const unsigned char input[16], unsigned char output[16]); /** * \brief Clear the context. * * \param ctx The context to clear. */ void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx); #ifdef __cplusplus } #endif #endif /* MBEDTLS_BLOCK_CIPHER_INTERNAL_H */ webfakes/src/mbedtls/library/ssl_tls13_generic.c0000644000176200001440000016661314740737024021442 0ustar liggesusers/* * TLS 1.3 functionality shared between client and server * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) #include #include "mbedtls/error.h" #include "debug_internal.h" #include "mbedtls/oid.h" #include "mbedtls/platform.h" #include "mbedtls/constant_time.h" #include "psa/crypto.h" #include "mbedtls/psa_util.h" #include "ssl_misc.h" #include "ssl_tls13_invasive.h" #include "ssl_tls13_keys.h" #include "ssl_debug_helpers.h" #include "psa/crypto.h" #include "psa_util_internal.h" /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) int mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl) { psa_status_t status = psa_crypto_init(); if (status != PSA_SUCCESS) { (void) ssl; // unused when debugging is disabled MBEDTLS_SSL_DEBUG_RET(1, "psa_crypto_init", status); } return PSA_TO_MBEDTLS_ERR(status); } const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ MBEDTLS_SERVER_HELLO_RANDOM_LEN] = { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C }; int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, unsigned char **buf, size_t *buf_len) { int ret; if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); goto cleanup; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || ssl->in_msg[0] != hs_type) { MBEDTLS_SSL_DEBUG_MSG(1, ("Receive unexpected handshake message.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; goto cleanup; } /* * Jump handshake header (4 bytes, see Section 4 of RFC 8446). * ... * HandshakeType msg_type; * uint24 length; * ... */ *buf = ssl->in_msg + 4; *buf_len = ssl->in_hslen - 4; cleanup: return ret; } int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end, const unsigned char **supported_versions_data, const unsigned char **supported_versions_data_end) { const unsigned char *p = buf; size_t extensions_len; const unsigned char *extensions_end; *supported_versions_data = NULL; *supported_versions_data_end = NULL; /* Case of no extension */ if (p == end) { return 0; } /* ... * Extension extensions; * ... * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Check extensions do not go beyond the buffer of data. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) { *supported_versions_data = p; *supported_versions_data_end = p + extension_data_len; return 1; } p += extension_data_len; } return 0; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * STATE HANDLING: Read CertificateVerify */ /* Macro to express the maximum length of the verify structure. * * The structure is computed per TLS 1.3 specification as: * - 64 bytes of octet 32, * - 33 bytes for the context string * (which is either "TLS 1.3, client CertificateVerify" * or "TLS 1.3, server CertificateVerify"), * - 1 byte for the octet 0x0, which serves as a separator, * - 32 or 48 bytes for the Transcript-Hash(Handshake Context, Certificate) * (depending on the size of the transcript_hash) * * This results in a total size of * - 130 bytes for a SHA256-based transcript hash, or * (64 + 33 + 1 + 32 bytes) * - 146 bytes for a SHA384-based transcript hash. * (64 + 33 + 1 + 48 bytes) * */ #define SSL_VERIFY_STRUCT_MAX_SIZE (64 + \ 33 + \ 1 + \ MBEDTLS_TLS1_3_MD_MAX_SIZE \ ) /* * The ssl_tls13_create_verify_structure() creates the verify structure. * As input, it requires the transcript hash. * * The caller has to ensure that the buffer has size at least * SSL_VERIFY_STRUCT_MAX_SIZE bytes. */ static void ssl_tls13_create_verify_structure(const unsigned char *transcript_hash, size_t transcript_hash_len, unsigned char *verify_buffer, size_t *verify_buffer_len, int from) { size_t idx; /* RFC 8446, Section 4.4.3: * * The digital signature [in the CertificateVerify message] is then * computed over the concatenation of: * - A string that consists of octet 32 (0x20) repeated 64 times * - The context string * - A single 0 byte which serves as the separator * - The content to be signed */ memset(verify_buffer, 0x20, 64); idx = 64; if (from == MBEDTLS_SSL_IS_CLIENT) { memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.client_cv, MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv)); idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv); } else { /* from == MBEDTLS_SSL_IS_SERVER */ memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.server_cv, MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv)); idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv); } verify_buffer[idx++] = 0x0; memcpy(verify_buffer + idx, transcript_hash, transcript_hash_len); idx += transcript_hash_len; *verify_buffer_len = idx; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_certificate_verify(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end, const unsigned char *verify_buffer, size_t verify_buffer_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; uint16_t algorithm; size_t signature_len; mbedtls_pk_type_t sig_alg; mbedtls_md_type_t md_alg; psa_algorithm_t hash_alg = PSA_ALG_NONE; unsigned char verify_hash[PSA_HASH_MAX_SIZE]; size_t verify_hash_len; void const *options = NULL; #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_pk_rsassa_pss_options rsassa_pss_options; #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ /* * struct { * SignatureScheme algorithm; * opaque signature<0..2^16-1>; * } CertificateVerify; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); algorithm = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* RFC 8446 section 4.4.3 * * If the CertificateVerify message is sent by a server, the signature * algorithm MUST be one offered in the client's "signature_algorithms" * extension unless no valid certificate chain can be produced without * unsupported algorithms * * RFC 8446 section 4.4.2.2 * * If the client cannot construct an acceptable chain using the provided * certificates and decides to abort the handshake, then it MUST abort the * handshake with an appropriate certificate-related alert * (by default, "unsupported_certificate"). * * Check if algorithm is an offered signature algorithm. */ if (!mbedtls_ssl_sig_alg_is_offered(ssl, algorithm)) { /* algorithm not in offered signature algorithms list */ MBEDTLS_SSL_DEBUG_MSG(1, ("Received signature algorithm(%04x) is not " "offered.", (unsigned int) algorithm)); goto error; } if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( algorithm, &sig_alg, &md_alg) != 0) { goto error; } hash_alg = mbedtls_md_psa_alg_from_type(md_alg); if (hash_alg == 0) { goto error; } MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate Verify: Signature algorithm ( %04x )", (unsigned int) algorithm)); /* * Check the certificate's key type matches the signature alg */ if (!mbedtls_pk_can_do(&ssl->session_negotiate->peer_cert->pk, sig_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("signature algorithm doesn't match cert key")); goto error; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); signature_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, signature_len); status = psa_hash_compute(hash_alg, verify_buffer, verify_buffer_len, verify_hash, sizeof(verify_hash), &verify_hash_len); if (status != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "hash computation PSA error", status); goto error; } MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) if (sig_alg == MBEDTLS_PK_RSASSA_PSS) { rsassa_pss_options.mgf1_hash_id = md_alg; rsassa_pss_options.expected_salt_len = PSA_HASH_LENGTH(hash_alg); options = (const void *) &rsassa_pss_options; } #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ if ((ret = mbedtls_pk_verify_ext(sig_alg, options, &ssl->session_negotiate->peer_cert->pk, md_alg, verify_hash, verify_hash_len, p, signature_len)) == 0) { return 0; } MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify_ext", ret); error: /* RFC 8446 section 4.4.3 * * If the verification fails, the receiver MUST terminate the handshake * with a "decrypt_error" alert. */ MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE]; size_t verify_buffer_len; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; unsigned char *buf; size_t buf_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify")); MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len)); /* Need to calculate the hash of the transcript first * before reading the message since otherwise it gets * included in the transcript */ ret = mbedtls_ssl_get_handshake_transcript( ssl, (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, MBEDTLS_ERR_SSL_INTERNAL_ERROR); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash", transcript, transcript_len); /* Create verify structure */ ssl_tls13_create_verify_structure(transcript, transcript_len, verify_buffer, &verify_buffer_len, (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT); /* Process the message contents */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_verify( ssl, buf, buf + buf_len, verify_buffer, verify_buffer_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, buf, buf_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify")); MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_process_certificate_verify", ret); return ret; #else ((void) ssl); MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ } /* * * STATE HANDLING: Incoming Certificate. * */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* * Structure of Certificate message: * * enum { * X509(0), * RawPublicKey(2), * (255) * } CertificateType; * * struct { * select (certificate_type) { * case RawPublicKey: * * From RFC 7250 ASN.1_subjectPublicKeyInfo * * opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; * case X509: * opaque cert_data<1..2^24-1>; * }; * Extension extensions<0..2^16-1>; * } CertificateEntry; * * struct { * opaque certificate_request_context<0..2^8-1>; * CertificateEntry certificate_list<0..2^24-1>; * } Certificate; * */ /* Parse certificate chain send by the server. */ MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_STATIC_TESTABLE int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t certificate_request_context_len = 0; size_t certificate_list_len = 0; const unsigned char *p = buf; const unsigned char *certificate_list_end; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); certificate_request_context_len = p[0]; certificate_list_len = MBEDTLS_GET_UINT24_BE(p, 1); p += 4; /* In theory, the certificate list can be up to 2^24 Bytes, but we don't * support anything beyond 2^16 = 64K. */ if ((certificate_request_context_len != 0) || (certificate_list_len >= 0x10000)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* In case we tried to reuse a session but it failed */ if (ssl->session_negotiate->peer_cert != NULL) { mbedtls_x509_crt_free(ssl->session_negotiate->peer_cert); mbedtls_free(ssl->session_negotiate->peer_cert); } /* This is used by ssl_tls13_validate_certificate() */ if (certificate_list_len == 0) { ssl->session_negotiate->peer_cert = NULL; ret = 0; goto exit; } if ((ssl->session_negotiate->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt))) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc( %" MBEDTLS_PRINTF_SIZET " bytes ) failed", sizeof(mbedtls_x509_crt))); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, MBEDTLS_ERR_SSL_ALLOC_FAILED); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } mbedtls_x509_crt_init(ssl->session_negotiate->peer_cert); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_list_len); certificate_list_end = p + certificate_list_len; while (p < certificate_list_end) { size_t cert_data_len, extensions_len; const unsigned char *extensions_end; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 3); cert_data_len = MBEDTLS_GET_UINT24_BE(p, 0); p += 3; /* In theory, the CRT can be up to 2^24 Bytes, but we don't support * anything beyond 2^16 = 64K. Otherwise as in the TLS 1.2 code, * check that we have a minimum of 128 bytes of data, this is not * clear why we need that though. */ if ((cert_data_len < 128) || (cert_data_len >= 0x10000)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, cert_data_len); ret = mbedtls_x509_crt_parse_der(ssl->session_negotiate->peer_cert, p, cert_data_len); switch (ret) { case 0: /*ok*/ break; case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: /* Ignore certificate with an unknown algorithm: maybe a prior certificate was already trusted. */ break; case MBEDTLS_ERR_X509_ALLOC_FAILED: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, MBEDTLS_ERR_X509_ALLOC_FAILED); MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); return ret; case MBEDTLS_ERR_X509_UNKNOWN_VERSION: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, MBEDTLS_ERR_X509_UNKNOWN_VERSION); MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); return ret; default: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret); MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); return ret; } p += cert_data_len; /* Certificate extensions length */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, extensions_len); extensions_end = p + extensions_len; handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; /* * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_CERTIFICATE, extension_type, MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT); if (ret != 0) { return ret; } switch (extension_type) { default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_CERTIFICATE, extension_type, "( ignored )"); break; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE, handshake->received_extensions); } exit: /* Check that all the message is consumed. */ if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", ssl->session_negotiate->peer_cert); return ret; } #else MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_STATIC_TESTABLE int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { ((void) ssl); ((void) buf); ((void) end); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* Validate certificate chain sent by the server. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl) { /* Authmode: precedence order is SNI if used else configuration */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ? ssl->handshake->sni_authmode : ssl->conf->authmode; #else const int authmode = ssl->conf->authmode; #endif /* * If the peer hasn't sent a certificate ( i.e. it sent * an empty certificate chain ), this is reflected in the peer CRT * structure being unset. * Check for that and handle it depending on the * authentication mode. */ if (ssl->session_negotiate->peer_cert == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate")); #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { /* The client was asked for a certificate but didn't send * one. The client should know what's going on, so we * don't send an alert. */ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) { return 0; } else { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_NO_CERT, MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE); return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; } } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) /* Regardless of authmode, the server is not allowed to send an empty * certificate chain. (Last paragraph before 4.4.2.1 in RFC 8446: "The * server's certificate_list MUST always be non-empty.") With authmode * optional/none, we continue the handshake if we can't validate the * server's cert, but we still break it if no certificate was sent. */ if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT, MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE); return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE; } #endif /* MBEDTLS_SSL_CLI_C */ } return mbedtls_ssl_verify_certificate(ssl, authmode, ssl->session_negotiate->peer_cert, NULL, NULL); } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl) { ((void) ssl); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) unsigned char *buf; size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE, &buf, &buf_len)); /* Parse the certificate chain sent by the peer. */ MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_parse_certificate(ssl, buf, buf + buf_len)); /* Validate the certificate chain and set the verification results. */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_validate_certificate(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, buf_len)); cleanup: #else /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ (void) ssl; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate")); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * enum { * X509(0), * RawPublicKey(2), * (255) * } CertificateType; * * struct { * select (certificate_type) { * case RawPublicKey: * // From RFC 7250 ASN.1_subjectPublicKeyInfo * opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; * * case X509: * opaque cert_data<1..2^24-1>; * }; * Extension extensions<0..2^16-1>; * } CertificateEntry; * * struct { * opaque certificate_request_context<0..2^8-1>; * CertificateEntry certificate_list<0..2^24-1>; * } Certificate; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { const mbedtls_x509_crt *crt = mbedtls_ssl_own_cert(ssl); unsigned char *p = buf; unsigned char *certificate_request_context = ssl->handshake->certificate_request_context; unsigned char certificate_request_context_len = ssl->handshake->certificate_request_context_len; unsigned char *p_certificate_list_len; /* ... * opaque certificate_request_context<0..2^8-1>; * ... */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, certificate_request_context_len + 1); *p++ = certificate_request_context_len; if (certificate_request_context_len > 0) { memcpy(p, certificate_request_context, certificate_request_context_len); p += certificate_request_context_len; } /* ... * CertificateEntry certificate_list<0..2^24-1>; * ... */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3); p_certificate_list_len = p; p += 3; MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", crt); while (crt != NULL) { size_t cert_data_len = crt->raw.len; MBEDTLS_SSL_CHK_BUF_PTR(p, end, cert_data_len + 3 + 2); MBEDTLS_PUT_UINT24_BE(cert_data_len, p, 0); p += 3; memcpy(p, crt->raw.p, cert_data_len); p += cert_data_len; crt = crt->next; /* Currently, we don't have any certificate extensions defined. * Hence, we are sending an empty extension with length zero. */ MBEDTLS_PUT_UINT16_BE(0, p, 0); p += 2; } MBEDTLS_PUT_UINT24_BE(p - p_certificate_list_len - 3, p_certificate_list_len, 0); *out_len = p - buf; MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_CERTIFICATE, ssl->handshake->sent_extensions); return 0; } int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl) { int ret; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_body(ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate")); return ret; } /* * STATE HANDLING: Output Certificate Verify */ int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg, mbedtls_pk_context *key) { mbedtls_pk_type_t pk_type = (mbedtls_pk_type_t) mbedtls_ssl_sig_from_pk(key); size_t key_size = mbedtls_pk_get_bitlen(key); switch (pk_type) { case MBEDTLS_SSL_SIG_ECDSA: switch (key_size) { case 256: return sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256; case 384: return sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384; case 521: return sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512; default: break; } break; case MBEDTLS_SSL_SIG_RSA: switch (sig_alg) { case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: /* Intentional fallthrough */ case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: /* Intentional fallthrough */ case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: return 1; default: break; } break; default: break; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_verify_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; mbedtls_pk_context *own_key; unsigned char handshake_hash[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t handshake_hash_len; unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE]; size_t verify_buffer_len; uint16_t *sig_alg = ssl->handshake->received_sig_algs; size_t signature_len = 0; *out_len = 0; own_key = mbedtls_ssl_own_key(ssl); if (own_key == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ret = mbedtls_ssl_get_handshake_transcript( ssl, (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac, handshake_hash, sizeof(handshake_hash), &handshake_hash_len); if (ret != 0) { return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash", handshake_hash, handshake_hash_len); ssl_tls13_create_verify_structure(handshake_hash, handshake_hash_len, verify_buffer, &verify_buffer_len, ssl->conf->endpoint); /* * struct { * SignatureScheme algorithm; * opaque signature<0..2^16-1>; * } CertificateVerify; */ /* Check there is space for the algorithm identifier (2 bytes) and the * signature length (2 bytes). */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_pk_type_t pk_type = MBEDTLS_PK_NONE; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; psa_algorithm_t psa_algorithm = PSA_ALG_NONE; unsigned char verify_hash[PSA_HASH_MAX_SIZE]; size_t verify_hash_len; if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) { continue; } if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) { continue; } if (!mbedtls_ssl_tls13_check_sig_alg_cert_key_match(*sig_alg, own_key)) { continue; } if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( *sig_alg, &pk_type, &md_alg) != 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Hash verify buffer with indicated hash function */ psa_algorithm = mbedtls_md_psa_alg_from_type(md_alg); status = psa_hash_compute(psa_algorithm, verify_buffer, verify_buffer_len, verify_hash, sizeof(verify_hash), &verify_hash_len); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len); if ((ret = mbedtls_pk_sign_ext(pk_type, own_key, md_alg, verify_hash, verify_hash_len, p + 4, (size_t) (end - (p + 4)), &signature_len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature failed with %s", mbedtls_ssl_sig_alg_to_str(*sig_alg))); MBEDTLS_SSL_DEBUG_RET(2, "mbedtls_pk_sign_ext", ret); /* The signature failed. This is possible if the private key * was not suitable for the signature operation as purposely we * did not check its suitability completely. Let's try with * another signature algorithm. */ continue; } MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature with %s", mbedtls_ssl_sig_alg_to_str(*sig_alg))); break; } if (*sig_alg == MBEDTLS_TLS1_3_SIG_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("no suitable signature algorithm")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0); MBEDTLS_PUT_UINT16_BE(signature_len, p, 2); *out_len = 4 + signature_len; return 0; } int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl) { int ret = 0; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_verify_body( ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate verify")); return ret; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * * STATE HANDLING: Incoming Finished message. */ /* * Implementation */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_preprocess_finished_message(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_calculate_verify_data( ssl, ssl->handshake->state_local.finished_in.digest, sizeof(ssl->handshake->state_local.finished_in.digest), &ssl->handshake->state_local.finished_in.digest_len, ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_calculate_verify_data", ret); return ret; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_finished_message(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { /* * struct { * opaque verify_data[Hash.length]; * } Finished; */ const unsigned char *expected_verify_data = ssl->handshake->state_local.finished_in.digest; size_t expected_verify_data_len = ssl->handshake->state_local.finished_in.digest_len; /* Structural validation */ if ((size_t) (end - buf) != expected_verify_data_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (self-computed):", expected_verify_data, expected_verify_data_len); MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (received message):", buf, expected_verify_data_len); /* Semantic validation */ if (mbedtls_ct_memcmp(buf, expected_verify_data, expected_verify_data_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } return 0; } int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished message")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len)); /* Preprocessing step: Compute handshake digest */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_preprocess_finished_message(ssl)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_finished_message( ssl, buf, buf + buf_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_FINISHED, buf, buf_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished message")); return ret; } /* * * STATE HANDLING: Write and send Finished message. * */ /* * Implement */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_finished_message(mbedtls_ssl_context *ssl) { int ret; /* Compute transcript of handshake up to now. */ ret = mbedtls_ssl_tls13_calculate_verify_data(ssl, ssl->handshake->state_local.finished_out.digest, sizeof(ssl->handshake->state_local.finished_out. digest), &ssl->handshake->state_local.finished_out.digest_len, ssl->conf->endpoint); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calculate_verify_data failed", ret); return ret; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_finished_message_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { size_t verify_data_len = ssl->handshake->state_local.finished_out.digest_len; /* * struct { * opaque verify_data[Hash.length]; * } Finished; */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, verify_data_len); memcpy(buf, ssl->handshake->state_local.finished_out.digest, verify_data_len); *out_len = verify_data_len; return 0; } /* Main entry point: orchestrates the other functions */ int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished message")); MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_finished_message(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_finished_message_body( ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_FINISHED, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished message")); return ret; } void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup")); MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for inbound traffic")); mbedtls_ssl_set_inbound_transform(ssl, ssl->transform_application); MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for outbound traffic")); mbedtls_ssl_set_outbound_transform(ssl, ssl->transform_application); /* * Free the previous session and switch to the current one. */ if (ssl->session) { mbedtls_ssl_session_free(ssl->session); mbedtls_free(ssl->session); } ssl->session = ssl->session_negotiate; ssl->session_negotiate = NULL; MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup")); } /* * * STATE HANDLING: Write ChangeCipherSpec * */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_change_cipher_spec_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *olen) { ((void) ssl); MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1); buf[0] = 1; *olen = 1; return 0; } int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec")); /* Only one CCS to send. */ if (ssl->handshake->ccs_sent) { ret = 0; goto cleanup; } /* Write CCS message */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body( ssl, ssl->out_msg, ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, &ssl->out_msglen)); ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; /* Dispatch message */ MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0)); ssl->handshake->ccs_sent = 1; cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec")); return ret; } #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ /* Early Data Indication Extension * * struct { * select ( Handshake.msg_type ) { * case new_session_ticket: uint32 max_early_data_size; * case client_hello: Empty; * case encrypted_extensions: Empty; * }; * } EarlyDataIndication; */ #if defined(MBEDTLS_SSL_EARLY_DATA) int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, int in_new_session_ticket, unsigned char *buf, const unsigned char *end, size_t *out_len) { unsigned char *p = buf; #if defined(MBEDTLS_SSL_SRV_C) const size_t needed = in_new_session_ticket ? 8 : 4; #else const size_t needed = 4; ((void) in_new_session_ticket); #endif *out_len = 0; MBEDTLS_SSL_CHK_BUF_PTR(p, end, needed); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EARLY_DATA, p, 0); MBEDTLS_PUT_UINT16_BE(needed - 4, p, 2); #if defined(MBEDTLS_SSL_SRV_C) if (in_new_session_ticket) { MBEDTLS_PUT_UINT32_BE(ssl->conf->max_early_data_size, p, 4); MBEDTLS_SSL_DEBUG_MSG( 4, ("Sent max_early_data_size=%u", (unsigned int) ssl->conf->max_early_data_size)); } #endif *out_len = needed; mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_EARLY_DATA); return 0; } #if defined(MBEDTLS_SSL_SRV_C) int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl, size_t early_data_len) { /* * This function should be called only while an handshake is in progress * and thus a session under negotiation. Add a sanity check to detect a * misuse. */ if (ssl->session_negotiate == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* RFC 8446 section 4.6.1 * * A server receiving more than max_early_data_size bytes of 0-RTT data * SHOULD terminate the connection with an "unexpected_message" alert. * Note that if it is still possible to send early_data_len bytes of early * data, it means that early_data_len is smaller than max_early_data_size * (type uint32_t) and can fit in an uint32_t. We use this further * down. */ if (early_data_len > (ssl->session_negotiate->max_early_data_size - ssl->total_early_data_size)) { MBEDTLS_SSL_DEBUG_MSG( 2, ("EarlyData: Too much early data received, " "%lu + %" MBEDTLS_PRINTF_SIZET " > %lu", (unsigned long) ssl->total_early_data_size, early_data_len, (unsigned long) ssl->session_negotiate->max_early_data_size)); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* * early_data_len has been checked to be less than max_early_data_size * that is uint32_t. Its cast to an uint32_t below is thus safe. We need * the cast to appease some compilers. */ ssl->total_early_data_size += (uint32_t) early_data_len; return 0; } #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ /* Reset SSL context and update hash for handling HRR. * * Replace Transcript-Hash(X) by * Transcript-Hash( message_hash || * 00 00 Hash.length || * X ) * A few states of the handshake are preserved, including: * - session ID * - session ticket * - negotiated ciphersuite */ int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char hash_transcript[PSA_HASH_MAX_SIZE + 4]; size_t hash_len; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(3, ("Reset SSL session for HRR")); ret = mbedtls_ssl_get_handshake_transcript(ssl, (mbedtls_md_type_t) ciphersuite_info->mac, hash_transcript + 4, PSA_HASH_MAX_SIZE, &hash_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); return ret; } hash_transcript[0] = MBEDTLS_SSL_HS_MESSAGE_HASH; hash_transcript[1] = 0; hash_transcript[2] = 0; hash_transcript[3] = (unsigned char) hash_len; hash_len += 4; MBEDTLS_SSL_DEBUG_BUF(4, "Truncated handshake transcript", hash_transcript, hash_len); /* Reset running hash and replace it with a hash of the transcript */ ret = mbedtls_ssl_reset_checksum(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret); return ret; } ret = ssl->handshake->update_checksum(ssl, hash_transcript, hash_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) int mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t buf_len) { uint8_t *p = (uint8_t *) buf; const uint8_t *end = buf + buf_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Get size of the TLS opaque key_exchange field of the KeyShareEntry struct. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); uint16_t peerkey_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Check if key size is consistent with given buffer length. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, peerkey_len); /* Store peer's ECDH/FFDH public key. */ if (peerkey_len > sizeof(handshake->xxdh_psa_peerkey)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %u > %" MBEDTLS_PRINTF_SIZET, (unsigned) peerkey_len, sizeof(handshake->xxdh_psa_peerkey))); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } memcpy(handshake->xxdh_psa_peerkey, p, peerkey_len); handshake->xxdh_psa_peerkey_len = peerkey_len; return 0; } #if defined(PSA_WANT_ALG_FFDH) static psa_status_t mbedtls_ssl_get_psa_ffdh_info_from_tls_id( uint16_t tls_id, size_t *bits, psa_key_type_t *key_type) { switch (tls_id) { #if defined(PSA_WANT_DH_RFC7919_2048) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048: *bits = 2048; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_2048 */ #if defined(PSA_WANT_DH_RFC7919_3072) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072: *bits = 3072; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_3072 */ #if defined(PSA_WANT_DH_RFC7919_4096) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096: *bits = 4096; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_4096 */ #if defined(PSA_WANT_DH_RFC7919_6144) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144: *bits = 6144; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_6144 */ #if defined(PSA_WANT_DH_RFC7919_8192) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192: *bits = 8192; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_8192 */ default: return PSA_ERROR_NOT_SUPPORTED; } } #endif /* PSA_WANT_ALG_FFDH */ int mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( mbedtls_ssl_context *ssl, uint16_t named_group, unsigned char *buf, unsigned char *end, size_t *out_len) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; psa_key_attributes_t key_attributes; size_t own_pubkey_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; size_t bits = 0; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; psa_algorithm_t alg = PSA_ALG_NONE; size_t buf_size = (size_t) (end - buf); MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH/FFDH computation.")); /* Convert EC's TLS ID to PSA key type. */ #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_get_psa_curve_info_from_tls_id( named_group, &key_type, &bits) == PSA_SUCCESS) { alg = PSA_ALG_ECDH; } #endif #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_get_psa_ffdh_info_from_tls_id(named_group, &bits, &key_type) == PSA_SUCCESS) { alg = PSA_ALG_FFDH; } #endif if (key_type == PSA_KEY_TYPE_NONE) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } if (buf_size < PSA_BITS_TO_BYTES(bits)) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } handshake->xxdh_psa_type = key_type; ssl->handshake->xxdh_psa_bits = bits; key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, alg); psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); /* Generate ECDH/FFDH private key. */ status = psa_generate_key(&key_attributes, &handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret); return ret; } /* Export the public part of the ECDH/FFDH private key from PSA. */ status = psa_export_public_key(handshake->xxdh_psa_privkey, buf, buf_size, &own_pubkey_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret); return ret; } *out_len = own_pubkey_len; return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ /* RFC 8446 section 4.2 * * If an implementation receives an extension which it recognizes and which is * not specified for the message in which it appears, it MUST abort the handshake * with an "illegal_parameter" alert. * */ int mbedtls_ssl_tls13_check_received_extension( mbedtls_ssl_context *ssl, int hs_msg_type, unsigned int received_extension_type, uint32_t hs_msg_allowed_extensions_mask) { uint32_t extension_mask = mbedtls_ssl_get_extension_mask( received_extension_type); MBEDTLS_SSL_PRINT_EXT( 3, hs_msg_type, received_extension_type, "received"); if ((extension_mask & hs_msg_allowed_extensions_mask) == 0) { MBEDTLS_SSL_PRINT_EXT( 3, hs_msg_type, received_extension_type, "is illegal"); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->handshake->received_extensions |= extension_mask; /* * If it is a message containing extension responses, check that we * previously sent the extension. */ switch (hs_msg_type) { case MBEDTLS_SSL_HS_SERVER_HELLO: case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST: case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS: case MBEDTLS_SSL_HS_CERTIFICATE: /* Check if the received extension is sent by peer message.*/ if ((ssl->handshake->sent_extensions & extension_mask) != 0) { return 0; } break; default: return 0; } MBEDTLS_SSL_PRINT_EXT( 3, hs_msg_type, received_extension_type, "is unsupported"); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) /* RFC 8449, section 4: * * The ExtensionData of the "record_size_limit" extension is * RecordSizeLimit: * uint16 RecordSizeLimit; */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; uint16_t record_size_limit; const size_t extension_data_len = end - buf; if (extension_data_len != MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH) { MBEDTLS_SSL_DEBUG_MSG(2, ("record_size_limit extension has invalid length: %" MBEDTLS_PRINTF_SIZET " Bytes", extension_data_len)); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0); MBEDTLS_SSL_DEBUG_MSG(2, ("RecordSizeLimit: %u Bytes", record_size_limit)); /* RFC 8449, section 4: * * Endpoints MUST NOT send a "record_size_limit" extension with a value * smaller than 64. An endpoint MUST treat receipt of a smaller value * as a fatal error and generate an "illegal_parameter" alert. */ if (record_size_limit < MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid record size limit : %u Bytes", record_size_limit)); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->session_negotiate->record_size_limit = record_size_limit; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len) { unsigned char *p = buf; *out_len = 0; MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_IN_CONTENT_LEN >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN, "MBEDTLS_SSL_IN_CONTENT_LEN is less than the " "minimum record size limit"); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT, p, 0); MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH, p, 2); MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_IN_CONTENT_LEN, p, 4); *out_len = 6; MBEDTLS_SSL_DEBUG_MSG(2, ("Sent RecordSizeLimit: %d Bytes", MBEDTLS_SSL_IN_CONTENT_LEN)); mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT); return 0; } #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #endif /* MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_PROTO_TLS1_3 */ webfakes/src/mbedtls/library/error.c0000644000176200001440000011045614740737024017242 0ustar liggesusers/* * Error message information * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "mbedtls/error.h" #if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) #if defined(MBEDTLS_ERROR_C) #include "mbedtls/platform.h" #include #include #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #endif #if defined(MBEDTLS_ARIA_C) #include "mbedtls/aria.h" #endif #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #endif #if defined(MBEDTLS_BASE64_C) #include "mbedtls/base64.h" #endif #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #endif #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" #endif #if defined(MBEDTLS_CHACHA20_C) #include "mbedtls/chacha20.h" #endif #if defined(MBEDTLS_CHACHAPOLY_C) #include "mbedtls/chachapoly.h" #endif #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" #endif #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #endif #if defined(MBEDTLS_DHM_C) #include "mbedtls/dhm.h" #endif #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" #endif #if defined(MBEDTLS_ERROR_C) #include "mbedtls/error.h" #endif #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #endif #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif #if defined(MBEDTLS_HKDF_C) #include "mbedtls/hkdf.h" #endif #if defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #endif #if defined(MBEDTLS_LMS_C) #include "mbedtls/lms.h" #endif #if defined(MBEDTLS_MD_C) #include "mbedtls/md.h" #endif #if defined(MBEDTLS_NET_C) #include "mbedtls/net_sockets.h" #endif #if defined(MBEDTLS_OID_C) #include "mbedtls/oid.h" #endif #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_PK_C) #include "mbedtls/pk.h" #endif #if defined(MBEDTLS_PKCS12_C) #include "mbedtls/pkcs12.h" #endif #if defined(MBEDTLS_PKCS5_C) #include "mbedtls/pkcs5.h" #endif #if defined(MBEDTLS_PKCS7_C) #include "mbedtls/pkcs7.h" #endif #if defined(MBEDTLS_POLY1305_C) #include "mbedtls/poly1305.h" #endif #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif #if defined(MBEDTLS_SHA1_C) #include "mbedtls/sha1.h" #endif #if defined(MBEDTLS_SHA256_C) #include "mbedtls/sha256.h" #endif #if defined(MBEDTLS_SHA3_C) #include "mbedtls/sha3.h" #endif #if defined(MBEDTLS_SHA512_C) #include "mbedtls/sha512.h" #endif #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/ssl.h" #endif #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) #include "mbedtls/x509.h" #endif const char *mbedtls_high_level_strerr(int error_code) { int high_level_error_code; if (error_code < 0) { error_code = -error_code; } /* Extract the high-level part from the error code. */ high_level_error_code = error_code & 0xFF80; switch (high_level_error_code) { /* Begin Auto-Generated Code. */ #if defined(MBEDTLS_CIPHER_C) case -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE): return( "CIPHER - The selected feature is not available" ); case -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA): return( "CIPHER - Bad input parameters" ); case -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED): return( "CIPHER - Failed to allocate memory" ); case -(MBEDTLS_ERR_CIPHER_INVALID_PADDING): return( "CIPHER - Input data contains invalid padding and is rejected" ); case -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED): return( "CIPHER - Decryption of block requires a full block" ); case -(MBEDTLS_ERR_CIPHER_AUTH_FAILED): return( "CIPHER - Authentication failed (for AEAD modes)" ); case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT): return( "CIPHER - The context is invalid. For example, because it was freed" ); #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_DHM_C) case -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA): return( "DHM - Bad input parameters" ); case -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED): return( "DHM - Reading of the DHM parameters failed" ); case -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED): return( "DHM - Making of the DHM parameters failed" ); case -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED): return( "DHM - Reading of the public values failed" ); case -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED): return( "DHM - Making of the public value failed" ); case -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED): return( "DHM - Calculation of the DHM secret failed" ); case -(MBEDTLS_ERR_DHM_INVALID_FORMAT): return( "DHM - The ASN.1 data is not formatted correctly" ); case -(MBEDTLS_ERR_DHM_ALLOC_FAILED): return( "DHM - Allocation of memory failed" ); case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR): return( "DHM - Read or write of file failed" ); case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED): return( "DHM - Setting the modulus and generator failed" ); #endif /* MBEDTLS_DHM_C */ #if defined(MBEDTLS_ECP_C) case -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA): return( "ECP - Bad input parameters to function" ); case -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL): return( "ECP - The buffer is too small to write to" ); case -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE): return( "ECP - The requested feature is not available, for example, the requested curve is not supported" ); case -(MBEDTLS_ERR_ECP_VERIFY_FAILED): return( "ECP - The signature is not valid" ); case -(MBEDTLS_ERR_ECP_ALLOC_FAILED): return( "ECP - Memory allocation failed" ); case -(MBEDTLS_ERR_ECP_RANDOM_FAILED): return( "ECP - Generation of random value, such as ephemeral key, failed" ); case -(MBEDTLS_ERR_ECP_INVALID_KEY): return( "ECP - Invalid private or public key" ); case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH): return( "ECP - The buffer contains a valid signature followed by more data" ); case -(MBEDTLS_ERR_ECP_IN_PROGRESS): return( "ECP - Operation in progress, call again with the same parameters to continue" ); #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_MD_C) case -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE): return( "MD - The selected feature is not available" ); case -(MBEDTLS_ERR_MD_BAD_INPUT_DATA): return( "MD - Bad input parameters to function" ); case -(MBEDTLS_ERR_MD_ALLOC_FAILED): return( "MD - Failed to allocate memory" ); case -(MBEDTLS_ERR_MD_FILE_IO_ERROR): return( "MD - Opening or reading of file failed" ); #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) case -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT): return( "PEM - No PEM header or footer found" ); case -(MBEDTLS_ERR_PEM_INVALID_DATA): return( "PEM - PEM string is not as expected" ); case -(MBEDTLS_ERR_PEM_ALLOC_FAILED): return( "PEM - Failed to allocate memory" ); case -(MBEDTLS_ERR_PEM_INVALID_ENC_IV): return( "PEM - RSA IV is not in hex-format" ); case -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG): return( "PEM - Unsupported key encryption algorithm" ); case -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED): return( "PEM - Private key password can't be empty" ); case -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH): return( "PEM - Given private key password does not allow for correct decryption" ); case -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE): return( "PEM - Unavailable feature, e.g. hashing/encryption combination" ); case -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA): return( "PEM - Bad input parameters to function" ); #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ #if defined(MBEDTLS_PK_C) case -(MBEDTLS_ERR_PK_ALLOC_FAILED): return( "PK - Memory allocation failed" ); case -(MBEDTLS_ERR_PK_TYPE_MISMATCH): return( "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); case -(MBEDTLS_ERR_PK_BAD_INPUT_DATA): return( "PK - Bad input parameters to function" ); case -(MBEDTLS_ERR_PK_FILE_IO_ERROR): return( "PK - Read/write of file failed" ); case -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION): return( "PK - Unsupported key version" ); case -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT): return( "PK - Invalid key tag or value" ); case -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG): return( "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); case -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED): return( "PK - Private key password can't be empty" ); case -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH): return( "PK - Given private key password does not allow for correct decryption" ); case -(MBEDTLS_ERR_PK_INVALID_PUBKEY): return( "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); case -(MBEDTLS_ERR_PK_INVALID_ALG): return( "PK - The algorithm tag or value is invalid" ); case -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE): return( "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); case -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE): return( "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH): return( "PK - The buffer contains a valid signature followed by more data" ); case -(MBEDTLS_ERR_PK_BUFFER_TOO_SMALL): return( "PK - The output buffer is too small" ); #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_PKCS12_C) case -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA): return( "PKCS12 - Bad input parameters to function" ); case -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE): return( "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); case -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT): return( "PKCS12 - PBE ASN.1 data not as expected" ); case -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH): return( "PKCS12 - Given private key password does not allow for correct decryption" ); #endif /* MBEDTLS_PKCS12_C */ #if defined(MBEDTLS_PKCS5_C) case -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA): return( "PKCS5 - Bad input parameters to function" ); case -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT): return( "PKCS5 - Unexpected ASN.1 data" ); case -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE): return( "PKCS5 - Requested encryption or digest alg not available" ); case -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH): return( "PKCS5 - Given private key password does not allow for correct decryption" ); #endif /* MBEDTLS_PKCS5_C */ #if defined(MBEDTLS_PKCS7_C) case -(MBEDTLS_ERR_PKCS7_INVALID_FORMAT): return( "PKCS7 - The format is invalid, e.g. different type expected" ); case -(MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE): return( "PKCS7 - Unavailable feature, e.g. anything other than signed data" ); case -(MBEDTLS_ERR_PKCS7_INVALID_VERSION): return( "PKCS7 - The PKCS #7 version element is invalid or cannot be parsed" ); case -(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO): return( "PKCS7 - The PKCS #7 content info is invalid or cannot be parsed" ); case -(MBEDTLS_ERR_PKCS7_INVALID_ALG): return( "PKCS7 - The algorithm tag or value is invalid or cannot be parsed" ); case -(MBEDTLS_ERR_PKCS7_INVALID_CERT): return( "PKCS7 - The certificate tag or value is invalid or cannot be parsed" ); case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE): return( "PKCS7 - Error parsing the signature" ); case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO): return( "PKCS7 - Error parsing the signer's info" ); case -(MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA): return( "PKCS7 - Input invalid" ); case -(MBEDTLS_ERR_PKCS7_ALLOC_FAILED): return( "PKCS7 - Allocation of memory failed" ); case -(MBEDTLS_ERR_PKCS7_VERIFY_FAIL): return( "PKCS7 - Verification Failed" ); case -(MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID): return( "PKCS7 - The PKCS #7 date issued/expired dates are invalid" ); #endif /* MBEDTLS_PKCS7_C */ #if defined(MBEDTLS_RSA_C) case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA): return( "RSA - Bad input parameters to function" ); case -(MBEDTLS_ERR_RSA_INVALID_PADDING): return( "RSA - Input data contains invalid padding and is rejected" ); case -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED): return( "RSA - Something failed during generation of a key" ); case -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED): return( "RSA - Key failed to pass the validity check of the library" ); case -(MBEDTLS_ERR_RSA_PUBLIC_FAILED): return( "RSA - The public key operation failed" ); case -(MBEDTLS_ERR_RSA_PRIVATE_FAILED): return( "RSA - The private key operation failed" ); case -(MBEDTLS_ERR_RSA_VERIFY_FAILED): return( "RSA - The PKCS#1 verification failed" ); case -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE): return( "RSA - The output buffer for decryption is not large enough" ); case -(MBEDTLS_ERR_RSA_RNG_FAILED): return( "RSA - The random generator failed to generate non-zeros" ); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_SSL_TLS_C) case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS): return( "SSL - A cryptographic operation is in progress. Try again later" ); case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE): return( "SSL - The requested feature is not available" ); case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA): return( "SSL - Bad input parameters to function" ); case -(MBEDTLS_ERR_SSL_INVALID_MAC): return( "SSL - Verification of the message MAC failed" ); case -(MBEDTLS_ERR_SSL_INVALID_RECORD): return( "SSL - An invalid SSL record was received" ); case -(MBEDTLS_ERR_SSL_CONN_EOF): return( "SSL - The connection indicated an EOF" ); case -(MBEDTLS_ERR_SSL_DECODE_ERROR): return( "SSL - A message could not be parsed due to a syntactic error" ); case -(MBEDTLS_ERR_SSL_NO_RNG): return( "SSL - No RNG was provided to the SSL module" ); case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE): return( "SSL - No client certification received from the client, but required by the authentication mode" ); case -(MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION): return( "SSL - Client received an extended server hello containing an unsupported extension" ); case -(MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL): return( "SSL - No ALPN protocols supported that the client advertises" ); case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED): return( "SSL - The own private key or pre-shared key is not set, but needed" ); case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED): return( "SSL - No CA Chain is set, but required to operate" ); case -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE): return( "SSL - An unexpected message was received from our peer" ); case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE): return( "SSL - A fatal alert message was received from our peer" ); case -(MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME): return( "SSL - No server could be identified matching the client's SNI" ); case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY): return( "SSL - The peer notified us that the connection is going to be closed" ); case -(MBEDTLS_ERR_SSL_BAD_CERTIFICATE): return( "SSL - Processing of the Certificate handshake message failed" ); case -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET): return( "SSL - A TLS 1.3 NewSessionTicket message has been received" ); case -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA): return( "SSL - Not possible to read early data" ); case -(MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA): return( "SSL - * Early data has been received as part of an on-going handshake. This error code can be returned only on server side if and only if early data has been enabled by means of the mbedtls_ssl_conf_early_data() API. This error code can then be returned by mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if early data has been received as part of the handshake sequence they triggered. To read the early data, call mbedtls_ssl_read_early_data()" ); case -(MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA): return( "SSL - Not possible to write early data" ); case -(MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND): return( "SSL - Cache entry not found" ); case -(MBEDTLS_ERR_SSL_ALLOC_FAILED): return( "SSL - Memory allocation failed" ); case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED): return( "SSL - Hardware acceleration function returned with error" ); case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH): return( "SSL - Hardware acceleration function skipped / left alone data" ); case -(MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION): return( "SSL - Handshake protocol not within min/max boundaries" ); case -(MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE): return( "SSL - The handshake negotiation failed" ); case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED): return( "SSL - Session ticket has expired" ); case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH): return( "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); case -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY): return( "SSL - Unknown identity received (eg, PSK identity)" ); case -(MBEDTLS_ERR_SSL_INTERNAL_ERROR): return( "SSL - Internal error (eg, unexpected failure in lower-level module)" ); case -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING): return( "SSL - A counter would wrap (eg, too many messages exchanged)" ); case -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO): return( "SSL - Unexpected message at ServerHello in renegotiation" ); case -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED): return( "SSL - DTLS client must retry for hello verification" ); case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL): return( "SSL - A buffer is too small to receive or write a message" ); case -(MBEDTLS_ERR_SSL_WANT_READ): return( "SSL - No data of requested type currently available on underlying transport" ); case -(MBEDTLS_ERR_SSL_WANT_WRITE): return( "SSL - Connection requires a write call" ); case -(MBEDTLS_ERR_SSL_TIMEOUT): return( "SSL - The operation timed out" ); case -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT): return( "SSL - The client initiated a reconnect from the same port" ); case -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD): return( "SSL - Record header looks valid but is not expected" ); case -(MBEDTLS_ERR_SSL_NON_FATAL): return( "SSL - The alert message received indicates a non-fatal error" ); case -(MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER): return( "SSL - A field in a message was incorrect or inconsistent with other fields" ); case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING): return( "SSL - Internal-only message signaling that further message-processing should be done" ); case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS): return( "SSL - The asynchronous operation is not completed yet" ); case -(MBEDTLS_ERR_SSL_EARLY_MESSAGE): return( "SSL - Internal-only message signaling that a message arrived early" ); case -(MBEDTLS_ERR_SSL_UNEXPECTED_CID): return( "SSL - An encrypted DTLS-frame with an unexpected CID was received" ); case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH): return( "SSL - An operation failed due to an unexpected version or configuration" ); case -(MBEDTLS_ERR_SSL_BAD_CONFIG): return( "SSL - Invalid value in SSL config" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) case -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE): return( "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); case -(MBEDTLS_ERR_X509_UNKNOWN_OID): return( "X509 - Requested OID is unknown" ); case -(MBEDTLS_ERR_X509_INVALID_FORMAT): return( "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); case -(MBEDTLS_ERR_X509_INVALID_VERSION): return( "X509 - The CRT/CRL/CSR version element is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_SERIAL): return( "X509 - The serial tag or value is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_ALG): return( "X509 - The algorithm tag or value is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_NAME): return( "X509 - The name tag or value is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_DATE): return( "X509 - The date tag or value is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_SIGNATURE): return( "X509 - The signature tag or value invalid" ); case -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS): return( "X509 - The extension tag or value is invalid" ); case -(MBEDTLS_ERR_X509_UNKNOWN_VERSION): return( "X509 - CRT/CRL/CSR has an unsupported version number" ); case -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG): return( "X509 - Signature algorithm (oid) is unsupported" ); case -(MBEDTLS_ERR_X509_SIG_MISMATCH): return( "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); case -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED): return( "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); case -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT): return( "X509 - Format not recognized as DER or PEM" ); case -(MBEDTLS_ERR_X509_BAD_INPUT_DATA): return( "X509 - Input invalid" ); case -(MBEDTLS_ERR_X509_ALLOC_FAILED): return( "X509 - Allocation of memory failed" ); case -(MBEDTLS_ERR_X509_FILE_IO_ERROR): return( "X509 - Read/write of file failed" ); case -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL): return( "X509 - Destination buffer is too small" ); case -(MBEDTLS_ERR_X509_FATAL_ERROR): return( "X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed" ); #endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ /* End Auto-Generated Code. */ default: break; } return NULL; } const char *mbedtls_low_level_strerr(int error_code) { int low_level_error_code; if (error_code < 0) { error_code = -error_code; } /* Extract the low-level part from the error code. */ low_level_error_code = error_code & ~0xFF80; switch (low_level_error_code) { /* Begin Auto-Generated Code. */ #if defined(MBEDTLS_AES_C) case -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH): return( "AES - Invalid key length" ); case -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH): return( "AES - Invalid data input length" ); case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA): return( "AES - Invalid input data" ); #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_ARIA_C) case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA): return( "ARIA - Bad input data" ); case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH): return( "ARIA - Invalid data input length" ); #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_ASN1_PARSE_C) case -(MBEDTLS_ERR_ASN1_OUT_OF_DATA): return( "ASN1 - Out of data when parsing an ASN1 data structure" ); case -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG): return( "ASN1 - ASN1 tag was of an unexpected value" ); case -(MBEDTLS_ERR_ASN1_INVALID_LENGTH): return( "ASN1 - Error when trying to determine the length or invalid length" ); case -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH): return( "ASN1 - Actual length differs from expected length" ); case -(MBEDTLS_ERR_ASN1_INVALID_DATA): return( "ASN1 - Data is invalid" ); case -(MBEDTLS_ERR_ASN1_ALLOC_FAILED): return( "ASN1 - Memory allocation failed" ); case -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL): return( "ASN1 - Buffer too small when writing ASN.1 data structure" ); #endif /* MBEDTLS_ASN1_PARSE_C */ #if defined(MBEDTLS_BASE64_C) case -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL): return( "BASE64 - Output buffer too small" ); case -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER): return( "BASE64 - Invalid character in input" ); #endif /* MBEDTLS_BASE64_C */ #if defined(MBEDTLS_BIGNUM_C) case -(MBEDTLS_ERR_MPI_FILE_IO_ERROR): return( "BIGNUM - An error occurred while reading from or writing to a file" ); case -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA): return( "BIGNUM - Bad input parameters to function" ); case -(MBEDTLS_ERR_MPI_INVALID_CHARACTER): return( "BIGNUM - There is an invalid character in the digit string" ); case -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL): return( "BIGNUM - The buffer is too small to write to" ); case -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE): return( "BIGNUM - The input arguments are negative or result in illegal output" ); case -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO): return( "BIGNUM - The input argument for division is zero, which is not allowed" ); case -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE): return( "BIGNUM - The input arguments are not acceptable" ); case -(MBEDTLS_ERR_MPI_ALLOC_FAILED): return( "BIGNUM - Memory allocation failed" ); #endif /* MBEDTLS_BIGNUM_C */ #if defined(MBEDTLS_CAMELLIA_C) case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA): return( "CAMELLIA - Bad input data" ); case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH): return( "CAMELLIA - Invalid data input length" ); #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_CCM_C) case -(MBEDTLS_ERR_CCM_BAD_INPUT): return( "CCM - Bad input parameters to the function" ); case -(MBEDTLS_ERR_CCM_AUTH_FAILED): return( "CCM - Authenticated decryption failed" ); #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHA20_C) case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA): return( "CHACHA20 - Invalid input parameter(s)" ); #endif /* MBEDTLS_CHACHA20_C */ #if defined(MBEDTLS_CHACHAPOLY_C) case -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE): return( "CHACHAPOLY - The requested operation is not permitted in the current state" ); case -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED): return( "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); #endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CTR_DRBG_C) case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED): return( "CTR_DRBG - The entropy source failed" ); case -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG): return( "CTR_DRBG - The requested random buffer length is too big" ); case -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG): return( "CTR_DRBG - The input (entropy + additional data) is too large" ); case -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR): return( "CTR_DRBG - Read or write error in file" ); #endif /* MBEDTLS_CTR_DRBG_C */ #if defined(MBEDTLS_DES_C) case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH): return( "DES - The data input has an invalid length" ); #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_ENTROPY_C) case -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED): return( "ENTROPY - Critical entropy source failure" ); case -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES): return( "ENTROPY - No more sources can be added" ); case -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED): return( "ENTROPY - No sources have been added to poll" ); case -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE): return( "ENTROPY - No strong sources have been added to poll" ); case -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR): return( "ENTROPY - Read/write error in file" ); #endif /* MBEDTLS_ENTROPY_C */ #if defined(MBEDTLS_ERROR_C) case -(MBEDTLS_ERR_ERROR_GENERIC_ERROR): return( "ERROR - Generic error" ); case -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED): return( "ERROR - This is a bug in the library" ); #endif /* MBEDTLS_ERROR_C */ #if defined(MBEDTLS_PLATFORM_C) case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED): return( "PLATFORM - Hardware accelerator failed" ); case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED): return( "PLATFORM - The requested feature is not supported by the platform" ); #endif /* MBEDTLS_PLATFORM_C */ #if defined(MBEDTLS_GCM_C) case -(MBEDTLS_ERR_GCM_AUTH_FAILED): return( "GCM - Authenticated decryption failed" ); case -(MBEDTLS_ERR_GCM_BAD_INPUT): return( "GCM - Bad input parameters to function" ); case -(MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL): return( "GCM - An output buffer is too small" ); #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_HKDF_C) case -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA): return( "HKDF - Bad input parameters to function" ); #endif /* MBEDTLS_HKDF_C */ #if defined(MBEDTLS_HMAC_DRBG_C) case -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG): return( "HMAC_DRBG - Too many random requested in single call" ); case -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG): return( "HMAC_DRBG - Input too large (Entropy + additional)" ); case -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR): return( "HMAC_DRBG - Read/write error in file" ); case -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED): return( "HMAC_DRBG - The entropy source failed" ); #endif /* MBEDTLS_HMAC_DRBG_C */ #if defined(MBEDTLS_LMS_C) case -(MBEDTLS_ERR_LMS_BAD_INPUT_DATA): return( "LMS - Bad data has been input to an LMS function" ); case -(MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS): return( "LMS - Specified LMS key has utilised all of its private keys" ); case -(MBEDTLS_ERR_LMS_VERIFY_FAILED): return( "LMS - LMS signature verification failed" ); case -(MBEDTLS_ERR_LMS_ALLOC_FAILED): return( "LMS - LMS failed to allocate space for a private key" ); case -(MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL): return( "LMS - Input/output buffer is too small to contain requited data" ); #endif /* MBEDTLS_LMS_C */ #if defined(MBEDTLS_NET_C) case -(MBEDTLS_ERR_NET_SOCKET_FAILED): return( "NET - Failed to open a socket" ); case -(MBEDTLS_ERR_NET_CONNECT_FAILED): return( "NET - The connection to the given server / port failed" ); case -(MBEDTLS_ERR_NET_BIND_FAILED): return( "NET - Binding of the socket failed" ); case -(MBEDTLS_ERR_NET_LISTEN_FAILED): return( "NET - Could not listen on the socket" ); case -(MBEDTLS_ERR_NET_ACCEPT_FAILED): return( "NET - Could not accept the incoming connection" ); case -(MBEDTLS_ERR_NET_RECV_FAILED): return( "NET - Reading information from the socket failed" ); case -(MBEDTLS_ERR_NET_SEND_FAILED): return( "NET - Sending information through the socket failed" ); case -(MBEDTLS_ERR_NET_CONN_RESET): return( "NET - Connection was reset by peer" ); case -(MBEDTLS_ERR_NET_UNKNOWN_HOST): return( "NET - Failed to get an IP address for the given hostname" ); case -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL): return( "NET - Buffer is too small to hold the data" ); case -(MBEDTLS_ERR_NET_INVALID_CONTEXT): return( "NET - The context is invalid, eg because it was free()ed" ); case -(MBEDTLS_ERR_NET_POLL_FAILED): return( "NET - Polling the net context failed" ); case -(MBEDTLS_ERR_NET_BAD_INPUT_DATA): return( "NET - Input invalid" ); #endif /* MBEDTLS_NET_C */ #if defined(MBEDTLS_OID_C) case -(MBEDTLS_ERR_OID_NOT_FOUND): return( "OID - OID is not found" ); case -(MBEDTLS_ERR_OID_BUF_TOO_SMALL): return( "OID - output buffer is too small" ); #endif /* MBEDTLS_OID_C */ #if defined(MBEDTLS_POLY1305_C) case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA): return( "POLY1305 - Invalid input parameter(s)" ); #endif /* MBEDTLS_POLY1305_C */ #if defined(MBEDTLS_SHA1_C) case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA): return( "SHA1 - SHA-1 input data was malformed" ); #endif /* MBEDTLS_SHA1_C */ #if defined(MBEDTLS_SHA256_C) case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA): return( "SHA256 - SHA-256 input data was malformed" ); #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA3_C) case -(MBEDTLS_ERR_SHA3_BAD_INPUT_DATA): return( "SHA3 - SHA-3 input data was malformed" ); #endif /* MBEDTLS_SHA3_C */ #if defined(MBEDTLS_SHA512_C) case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA): return( "SHA512 - SHA-512 input data was malformed" ); #endif /* MBEDTLS_SHA512_C */ #if defined(MBEDTLS_THREADING_C) case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA): return( "THREADING - Bad input parameters to function" ); case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR): return( "THREADING - Locking / unlocking / free failed with error code" ); #endif /* MBEDTLS_THREADING_C */ /* End Auto-Generated Code. */ default: break; } return NULL; } void mbedtls_strerror(int ret, char *buf, size_t buflen) { size_t len; int use_ret; const char *high_level_error_description = NULL; const char *low_level_error_description = NULL; if (buflen == 0) { return; } memset(buf, 0x00, buflen); if (ret < 0) { ret = -ret; } if (ret & 0xFF80) { use_ret = ret & 0xFF80; // Translate high level error code. high_level_error_description = mbedtls_high_level_strerr(ret); if (high_level_error_description == NULL) { mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret); } else { mbedtls_snprintf(buf, buflen, "%s", high_level_error_description); } #if defined(MBEDTLS_SSL_TLS_C) // Early return in case of a fatal error - do not try to translate low // level code. if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) { return; } #endif /* MBEDTLS_SSL_TLS_C */ } use_ret = ret & ~0xFF80; if (use_ret == 0) { return; } // If high level code is present, make a concatenation between both // error strings. // len = strlen(buf); if (len > 0) { if (buflen - len < 5) { return; } mbedtls_snprintf(buf + len, buflen - len, " : "); buf += len + 3; buflen -= len + 3; } // Translate low level error code. low_level_error_description = mbedtls_low_level_strerr(ret); if (low_level_error_description == NULL) { mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret); } else { mbedtls_snprintf(buf, buflen, "%s", low_level_error_description); } } #else /* MBEDTLS_ERROR_C */ /* * Provide a dummy implementation when MBEDTLS_ERROR_C is not defined */ void mbedtls_strerror(int ret, char *buf, size_t buflen) { ((void) ret); if (buflen > 0) { buf[0] = '\0'; } } #endif /* MBEDTLS_ERROR_C */ #if defined(MBEDTLS_TEST_HOOKS) void (*mbedtls_test_hook_error_add)(int, int, const char *, int); #endif #endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */ webfakes/src/mbedtls/library/hkdf.c0000644000176200001440000000757114740737024017030 0ustar liggesusers/* * HKDF implementation -- RFC 5869 * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_HKDF_C) #include #include "mbedtls/hkdf.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" int mbedtls_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt, size_t salt_len, const unsigned char *ikm, size_t ikm_len, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char prk[MBEDTLS_MD_MAX_SIZE]; ret = mbedtls_hkdf_extract(md, salt, salt_len, ikm, ikm_len, prk); if (ret == 0) { ret = mbedtls_hkdf_expand(md, prk, mbedtls_md_get_size(md), info, info_len, okm, okm_len); } mbedtls_platform_zeroize(prk, sizeof(prk)); return ret; } int mbedtls_hkdf_extract(const mbedtls_md_info_t *md, const unsigned char *salt, size_t salt_len, const unsigned char *ikm, size_t ikm_len, unsigned char *prk) { unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; if (salt == NULL) { size_t hash_len; if (salt_len != 0) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } hash_len = mbedtls_md_get_size(md); if (hash_len == 0) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } salt = null_salt; salt_len = hash_len; } return mbedtls_md_hmac(md, salt, salt_len, ikm, ikm_len, prk); } int mbedtls_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk, size_t prk_len, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len) { size_t hash_len; size_t where = 0; size_t n; size_t t_len = 0; size_t i; int ret = 0; mbedtls_md_context_t ctx; unsigned char t[MBEDTLS_MD_MAX_SIZE]; if (okm == NULL) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } hash_len = mbedtls_md_get_size(md); if (prk_len < hash_len || hash_len == 0) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } if (info == NULL) { info = (const unsigned char *) ""; info_len = 0; } n = okm_len / hash_len; if (okm_len % hash_len != 0) { n++; } /* * Per RFC 5869 Section 2.3, okm_len must not exceed * 255 times the hash length */ if (n > 255) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } mbedtls_md_init(&ctx); if ((ret = mbedtls_md_setup(&ctx, md, 1)) != 0) { goto exit; } memset(t, 0, hash_len); /* * Compute T = T(1) | T(2) | T(3) | ... | T(N) * Where T(N) is defined in RFC 5869 Section 2.3 */ for (i = 1; i <= n; i++) { size_t num_to_copy; unsigned char c = i & 0xff; ret = mbedtls_md_hmac_starts(&ctx, prk, prk_len); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&ctx, t, t_len); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&ctx, info, info_len); if (ret != 0) { goto exit; } /* The constant concatenated to the end of each T(n) is a single octet. * */ ret = mbedtls_md_hmac_update(&ctx, &c, 1); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_finish(&ctx, t); if (ret != 0) { goto exit; } num_to_copy = i != n ? hash_len : okm_len - where; memcpy(okm + where, t, num_to_copy); where += hash_len; t_len = hash_len; } exit: mbedtls_md_free(&ctx); mbedtls_platform_zeroize(t, sizeof(t)); return ret; } #endif /* MBEDTLS_HKDF_C */ webfakes/src/mbedtls/library/x509.c0000644000176200001440000016022314740737024016613 0ustar liggesusers/* * X.509 common functions for parsing and verification * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. * * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ #include "common.h" #if defined(MBEDTLS_X509_USE_C) #include "x509_internal.h" #include "mbedtls/asn1.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #include "mbedtls/asn1write.h" #include "mbedtls/platform.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_HAVE_TIME_DATE) #include "mbedtls/platform_util.h" #include #endif #define CHECK(code) \ do { \ if ((ret = (code)) != 0) { \ return ret; \ } \ } while (0) #define CHECK_RANGE(min, max, val) \ do { \ if ((val) < (min) || (val) > (max)) { \ return ret; \ } \ } while (0) /* * CertificateSerialNumber ::= INTEGER */ int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *serial) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) && **p != MBEDTLS_ASN1_INTEGER) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } serial->tag = *(*p)++; if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret); } serial->p = *p; *p += serial->len; return 0; } /* Get an algorithm identifier without parameters (eg for signatures) * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } return 0; } /* * Parse an algorithm identifier with (optional) parameters */ int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg, mbedtls_x509_buf *params) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } return 0; } /* * Convert md type to string */ #if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) static inline const char *md_type_to_string(mbedtls_md_type_t md_alg) { switch (md_alg) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_MD_MD5: return "MD5"; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_MD_SHA1: return "SHA1"; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_MD_SHA224: return "SHA224"; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: return "SHA256"; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: return "SHA384"; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_MD_SHA512: return "SHA512"; #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) case MBEDTLS_MD_RIPEMD160: return "RIPEMD160"; #endif case MBEDTLS_MD_NONE: return NULL; default: return NULL; } } #endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */ #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) /* * HashAlgorithm ::= AlgorithmIdentifier * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } * * For HashAlgorithm, parameters MUST be NULL or absent. */ static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p; const unsigned char *end; mbedtls_x509_buf md_oid; size_t len; /* Make sure we got a SEQUENCE and setup bounds */ if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } p = alg->p; end = p + alg->len; if (p >= end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } /* Parse md_oid */ md_oid.tag = *p; if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } md_oid.p = p; p += md_oid.len; /* Get md_alg from md_oid */ if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } /* Make sure params is absent of NULL */ if (p == end) { return 0; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * RSASSA-PSS-params ::= SEQUENCE { * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, * saltLength [2] INTEGER DEFAULT 20, * trailerField [3] INTEGER DEFAULT 1 } * -- Note that the tags in this Sequence are explicit. * * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other * option. Enforce this at parsing time. */ int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, int *salt_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p; const unsigned char *end, *end2; size_t len; mbedtls_x509_buf alg_id, alg_params; /* First set everything to defaults */ *md_alg = MBEDTLS_MD_SHA1; *mgf_md = MBEDTLS_MD_SHA1; *salt_len = 20; /* Make sure params is a SEQUENCE and setup bounds */ if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } p = (unsigned char *) params->p; end = p + params->len; if (p == end) { return 0; } /* * HashAlgorithm */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)) == 0) { end2 = p + len; /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) { return ret; } if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p == end) { return 0; } /* * MaskGenAlgorithm */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1)) == 0) { end2 = p + len; /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) { return ret; } /* Only MFG1 is recognised for now */ if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE, MBEDTLS_ERR_OID_NOT_FOUND); } /* Parse HashAlgorithm */ if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) { return ret; } if (p != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p == end) { return 0; } /* * salt_len */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2)) == 0) { end2 = p + len; if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p == end) { return 0; } /* * trailer_field (if present, must be 1) */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3)) == 0) { int trailer_field; end2 = p + len; if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if (trailer_field != 1) { return MBEDTLS_ERR_X509_INVALID_ALG; } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ /* * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ static int x509_get_attr_type_value(unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; mbedtls_x509_buf *oid; mbedtls_x509_buf *val; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); } end = *p + len; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } oid = &cur->oid; oid->tag = **p; if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); } oid->p = *p; *p += oid->len; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && **p != MBEDTLS_ASN1_BIT_STRING) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } val = &cur->val; val->tag = *(*p)++; if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); } val->p = *p; *p += val->len; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } cur->next = NULL; return 0; } /* * Name ::= CHOICE { -- only one possibility for now -- * rdnSequence RDNSequence } * * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType * * The data structure is optimized for the common case where each RDN has only * one element, which is represented as a list of AttributeTypeAndValue. * For the general case we still use a flat list, but we mark elements of the * same set so that they are "merged" together in the functions that consume * this list, eg mbedtls_x509_dn_gets(). * * On success, this function may allocate a linked list starting at cur->next * that must later be free'd by the caller using mbedtls_free(). In error * cases, this function frees all allocated memory internally and the caller * has no freeing responsibilities. */ int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t set_len; const unsigned char *end_set; mbedtls_x509_name *head = cur; /* don't use recursion, we'd risk stack overflow if not optimized */ while (1) { /* * parse SET */ if ((ret = mbedtls_asn1_get_tag(p, end, &set_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); goto error; } end_set = *p + set_len; while (1) { if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) { goto error; } if (*p == end_set) { break; } /* Mark this item as being no the only one in a set */ cur->next_merged = 1; cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); if (cur->next == NULL) { ret = MBEDTLS_ERR_X509_ALLOC_FAILED; goto error; } cur = cur->next; } /* * continue until end of SEQUENCE is reached */ if (*p == end) { return 0; } cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); if (cur->next == NULL) { ret = MBEDTLS_ERR_X509_ALLOC_FAILED; goto error; } cur = cur->next; } error: /* Skip the first element as we did not allocate it */ mbedtls_asn1_free_named_data_list_shallow(head->next); head->next = NULL; return ret; } static int x509_date_is_valid(const mbedtls_x509_time *t) { unsigned int month_days; unsigned int year; switch (t->mon) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: month_days = 31; break; case 4: case 6: case 9: case 11: month_days = 30; break; case 2: year = (unsigned int) t->year; month_days = ((year & 3) || (!(year % 100) && (year % 400))) ? 28 : 29; break; default: return MBEDTLS_ERR_X509_INVALID_DATE; } if ((unsigned int) (t->day - 1) >= month_days || /* (1 - days in month) */ /* (unsigned int) (t->mon - 1) >= 12 || */ /* (1 - 12) checked above */ (unsigned int) t->year > 9999 || /* (0 - 9999) */ (unsigned int) t->hour > 23 || /* (0 - 23) */ (unsigned int) t->min > 59 || /* (0 - 59) */ (unsigned int) t->sec > 59) { /* (0 - 59) */ return MBEDTLS_ERR_X509_INVALID_DATE; } return 0; } static int x509_parse2_int(const unsigned char *p) { uint32_t d1 = p[0] - '0'; uint32_t d2 = p[1] - '0'; return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1; } /* * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) * field. */ static int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm, size_t yearlen) { int x; /* * Parse year, month, day, hour, minute, second */ tm->year = x509_parse2_int(p); if (tm->year < 0) { return MBEDTLS_ERR_X509_INVALID_DATE; } if (4 == yearlen) { x = tm->year * 100; p += 2; tm->year = x509_parse2_int(p); if (tm->year < 0) { return MBEDTLS_ERR_X509_INVALID_DATE; } } else { x = (tm->year < 50) ? 2000 : 1900; } tm->year += x; tm->mon = x509_parse2_int(p + 2); tm->day = x509_parse2_int(p + 4); tm->hour = x509_parse2_int(p + 6); tm->min = x509_parse2_int(p + 8); tm->sec = x509_parse2_int(p + 10); return x509_date_is_valid(tm); } /* * Time ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime } */ int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, mbedtls_x509_time *tm) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len, year_len; unsigned char tag; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } tag = **p; if (tag == MBEDTLS_ASN1_UTC_TIME) { year_len = 2; } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) { year_len = 4; } else { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } (*p)++; ret = mbedtls_asn1_get_len(p, end, &len); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); } /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */ if (len != year_len + 10 && !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) { return MBEDTLS_ERR_X509_INVALID_DATE; } (*p) += len; return x509_parse_time(*p - len, tm, year_len); } int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; int tag_type; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } tag_type = **p; if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret); } sig->tag = tag_type; sig->len = len; sig->p = *p; *p += len; return 0; } /* * Get signature algorithm from alg OID and optional parameters */ int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, void **sig_opts) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (*sig_opts != NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret); } #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) { mbedtls_pk_rsassa_pss_options *pss_opts; pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options)); if (pss_opts == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } ret = mbedtls_x509_get_rsassa_pss_params(sig_params, md_alg, &pss_opts->mgf1_hash_id, &pss_opts->expected_salt_len); if (ret != 0) { mbedtls_free(pss_opts); return ret; } *sig_opts = (void *) pss_opts; } else #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ { /* Make sure parameters are absent or NULL */ if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) || sig_params->len != 0) { return MBEDTLS_ERR_X509_INVALID_ALG; } } return 0; } /* * X.509 Extensions (No parsing of extensions, pointer should * be either manually updated or extensions should be parsed!) */ int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext, int tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* Extension structure use EXPLICIT tagging. That is, the actual * `Extensions` structure is wrapped by a tag-length pair using * the respective context-specific tag. */ ret = mbedtls_asn1_get_tag(p, end, &ext->len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; ext->p = *p; end = *p + ext->len; /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (end != *p + len) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } static char nibble_to_hex_digit(int i) { return (i < 10) ? (i + '0') : (i - 10 + 'A'); } /* * Store the name in printable form into buf; no more * than size characters will be written */ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start; /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/ unsigned char asn1_tag_len_buf[6]; unsigned char *asn1_len_p; unsigned char c, merge = 0; const mbedtls_x509_name *name; const char *short_name = NULL; char lowbits, highbits; char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; int print_hexstring; memset(s, 0, sizeof(s)); name = dn; p = buf; n = size; while (name != NULL) { if (!name->oid.p) { name = name->next; continue; } if (name != dn) { ret = mbedtls_snprintf(p, n, merge ? " + " : ", "); MBEDTLS_X509_SAFE_SNPRINTF; } print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) && (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) && (name->val.tag != MBEDTLS_ASN1_IA5_STRING); if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) { ret = mbedtls_snprintf(p, n, "%s=", short_name); } else { if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) { n -= ret; p += ret; ret = mbedtls_snprintf(p, n, "="); print_hexstring = 1; } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } else { ret = mbedtls_snprintf(p, n, "\?\?="); } } MBEDTLS_X509_SAFE_SNPRINTF; if (print_hexstring) { s[0] = '#'; asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf); if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } asn1_len_size = ret; if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } asn1_tag_size = ret; asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size; for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) { if (j + 1 >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } c = asn1_tag_len_buf[asn1_tag_len_buf_start+i]; lowbits = (c & 0x0F); highbits = c >> 4; s[j++] = nibble_to_hex_digit(highbits); s[j++] = nibble_to_hex_digit(lowbits); } for (i = 0; i < name->val.len; i++) { if (j + 1 >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } c = name->val.p[i]; lowbits = (c & 0x0F); highbits = c >> 4; s[j++] = nibble_to_hex_digit(highbits); s[j++] = nibble_to_hex_digit(lowbits); } } else { for (i = 0, j = 0; i < name->val.len; i++, j++) { if (j >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } c = name->val.p[i]; // Special characters requiring escaping, RFC 4514 Section 2.4 if (c == '\0') { return MBEDTLS_ERR_X509_INVALID_NAME; } else { if (strchr(",=+<>;\"\\", c) || ((i == 0) && strchr("# ", c)) || ((i == name->val.len-1) && (c == ' '))) { if (j + 1 >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } s[j++] = '\\'; } } if (c < 32 || c >= 127) { if (j + 3 >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } s[j++] = '\\'; lowbits = (c & 0x0F); highbits = c >> 4; s[j++] = nibble_to_hex_digit(highbits); s[j] = nibble_to_hex_digit(lowbits); } else { s[j] = c; } } } s[j] = '\0'; ret = mbedtls_snprintf(p, n, "%s", s); MBEDTLS_X509_SAFE_SNPRINTF; merge = name->next_merged; name = name->next; } return (int) (size - n); } /* * Store the serial in printable form into buf; no more * than size characters will be written */ int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, n, nr; char *p; p = buf; n = size; nr = (serial->len <= 32) ? serial->len : 28; for (i = 0; i < nr; i++) { if (i == 0 && nr > 1 && serial->p[i] == 0x0) { continue; } ret = mbedtls_snprintf(p, n, "%02X%s", serial->p[i], (i < nr - 1) ? ":" : ""); MBEDTLS_X509_SAFE_SNPRINTF; } if (nr != serial->len) { ret = mbedtls_snprintf(p, n, "...."); MBEDTLS_X509_SAFE_SNPRINTF; } return (int) (size - n); } #if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Helper for writing signature algorithms */ int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, const void *sig_opts) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; char *p = buf; size_t n = size; const char *desc = NULL; ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc); if (ret != 0) { ret = mbedtls_snprintf(p, n, "???"); } else { ret = mbedtls_snprintf(p, n, "%s", desc); } MBEDTLS_X509_SAFE_SNPRINTF; #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { const mbedtls_pk_rsassa_pss_options *pss_opts; pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; const char *name = md_type_to_string(md_alg); const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id); ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)", name ? name : "???", mgf_name ? mgf_name : "???", (unsigned int) pss_opts->expected_salt_len); MBEDTLS_X509_SAFE_SNPRINTF; } #else ((void) pk_alg); ((void) md_alg); ((void) sig_opts); #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ return (int) (size - n); } #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Helper for writing "RSA key size", "EC key size", etc */ int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name) { char *p = buf; size_t n = buf_size; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_snprintf(p, n, "%s key size", name); MBEDTLS_X509_SAFE_SNPRINTF; return 0; } int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2) { int x; x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) - ((t2->year << 9) | (t2->mon << 5) | (t2->day))); if (x != 0) { return x; } x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) - ((t2->hour << 12) | (t2->min << 6) | (t2->sec))); return x; } #if defined(MBEDTLS_HAVE_TIME_DATE) int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now) { struct tm tm; if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) { return -1; } now->year = tm.tm_year + 1900; now->mon = tm.tm_mon + 1; now->day = tm.tm_mday; now->hour = tm.tm_hour; now->min = tm.tm_min; now->sec = tm.tm_sec; return 0; } static int x509_get_current_time(mbedtls_x509_time *now) { return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now); } int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) { mbedtls_x509_time now; if (x509_get_current_time(&now) != 0) { return 1; } return mbedtls_x509_time_cmp(to, &now) < 0; } int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) { mbedtls_x509_time now; if (x509_get_current_time(&now) != 0) { return 1; } return mbedtls_x509_time_cmp(from, &now) > 0; } #else /* MBEDTLS_HAVE_TIME_DATE */ int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) { ((void) to); return 0; } int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) { ((void) from); return 0; } #endif /* MBEDTLS_HAVE_TIME_DATE */ /* Common functions for parsing CRT and CSR. */ #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C) /* * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * HardwareModuleName ::= SEQUENCE { * hwType OBJECT IDENTIFIER, * hwSerialNum OCTET STRING } * * NOTE: we currently only parse and use otherName of type HwModuleName, * as defined in RFC 4108. */ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, mbedtls_x509_san_other_name *other_name) { int ret = 0; size_t len; unsigned char *p = subject_alt_name->p; const unsigned char *end = p + subject_alt_name->len; mbedtls_x509_buf cur_oid; if ((subject_alt_name->tag & (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) { /* * The given subject alternative name is not of type "othername". */ return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } cur_oid.tag = MBEDTLS_ASN1_OID; cur_oid.p = p; cur_oid.len = len; /* * Only HwModuleName is currently supported. */ if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) { return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } other_name->type_id = cur_oid; p += len; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (end != p + len) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (end != p + len) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; other_name->value.hardware_module_name.oid.p = p; other_name->value.hardware_module_name.oid.len = len; p += len; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; other_name->value.hardware_module_name.val.p = p; other_name->value.hardware_module_name.val.len = len; p += len; if (p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* Check mbedtls_x509_get_subject_alt_name for detailed description. * * In some cases while parsing subject alternative names the sequence tag is optional * (e.g. CertSerialNumber). This function is designed to handle such case. */ int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t tag_len; mbedtls_asn1_sequence *cur = subject_alt_name; while (*p < end) { mbedtls_x509_subject_alternative_name tmp_san_name; mbedtls_x509_buf tmp_san_buf; memset(&tmp_san_name, 0, sizeof(tmp_san_name)); tmp_san_buf.tag = **p; (*p)++; if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } tmp_san_buf.p = *p; tmp_san_buf.len = tag_len; if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != MBEDTLS_ASN1_CONTEXT_SPECIFIC) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } /* * Check that the SAN is structured correctly by parsing it. * The SAN structure is discarded afterwards. */ ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name); /* * In case the extension is malformed, return an error, * and clear the allocated sequences. */ if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { mbedtls_asn1_sequence_free(subject_alt_name->next); subject_alt_name->next = NULL; return ret; } mbedtls_x509_free_subject_alt_name(&tmp_san_name); /* Allocate and assign next pointer */ if (cur->buf.p != NULL) { if (cur->next != NULL) { return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; } cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); if (cur->next == NULL) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_ALLOC_FAILED); } cur = cur->next; } cur->buf = tmp_san_buf; *p += tmp_san_buf.len; } /* Set final sequence entry's next pointer to NULL */ cur->next = NULL; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * SubjectAltName ::= GeneralNames * * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName * * GeneralName ::= CHOICE { * otherName [0] OtherName, * rfc822Name [1] IA5String, * dNSName [2] IA5String, * x400Address [3] ORAddress, * directoryName [4] Name, * ediPartyName [5] EDIPartyName, * uniformResourceIdentifier [6] IA5String, * iPAddress [7] OCTET STRING, * registeredID [8] OBJECT IDENTIFIER } * * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * EDIPartyName ::= SEQUENCE { * nameAssigner [0] DirectoryString OPTIONAL, * partyName [1] DirectoryString } * * We list all types, but use the following GeneralName types from RFC 5280: * "dnsName", "uniformResourceIdentifier" and "hardware_module_name" * of type "otherName", as defined in RFC 4108. */ int mbedtls_x509_get_subject_alt_name(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* Get main sequence tag */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name); } int mbedtls_x509_get_ns_cert_type(unsigned char **p, const unsigned char *end, unsigned char *ns_cert_type) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_bitstring bs = { 0, 0, NULL }; if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* A bitstring with no flags set is still technically valid, as it will mean that the certificate has no designated purpose at the time of creation. */ if (bs.len == 0) { *ns_cert_type = 0; return 0; } if (bs.len != 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH); } /* Get actual bitstring */ *ns_cert_type = *bs.p; return 0; } int mbedtls_x509_get_key_usage(unsigned char **p, const unsigned char *end, unsigned int *key_usage) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_x509_bitstring bs = { 0, 0, NULL }; if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* A bitstring with no flags set is still technically valid, as it will mean that the certificate has no designated purpose at the time of creation. */ if (bs.len == 0) { *key_usage = 0; return 0; } /* Get actual bitstring */ *key_usage = 0; for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) { *key_usage |= (unsigned int) bs.p[i] << (8*i); } return 0; } int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, mbedtls_x509_subject_alternative_name *san) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (san_buf->tag & (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) { /* * otherName */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME): { mbedtls_x509_san_other_name other_name; ret = x509_get_other_name(san_buf, &other_name); if (ret != 0) { return ret; } memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_OTHER_NAME; memcpy(&san->san.other_name, &other_name, sizeof(other_name)); } break; /* * uniformResourceIdentifier */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER): { memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER; memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); } break; /* * dNSName */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME): { memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_DNS_NAME; memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); } break; /* * IP address */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS): { memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_IP_ADDRESS; // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported if (san_buf->len == 4 || san_buf->len == 16) { memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); } else { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } } break; /* * rfc822Name */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME): { memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_RFC822_NAME; memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); } break; /* * directoryName */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME): { size_t name_len; unsigned char *p = san_buf->p; memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME; ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return ret; } if ((ret = mbedtls_x509_get_name(&p, p + name_len, &san->san.directory_name)) != 0) { return ret; } } break; /* * Type not supported */ default: return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } return 0; } void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san) { if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) { mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next); } } #if !defined(MBEDTLS_X509_REMOVE_INFO) int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, const mbedtls_x509_sequence *subject_alt_name, const char *prefix) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; size_t n = *size; char *p = *buf; const mbedtls_x509_sequence *cur = subject_alt_name; mbedtls_x509_subject_alternative_name san; int parse_ret; while (cur != NULL) { memset(&san, 0, sizeof(san)); parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san); if (parse_ret != 0) { if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { ret = mbedtls_snprintf(p, n, "\n%s ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; } else { ret = mbedtls_snprintf(p, n, "\n%s ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; } cur = cur->next; continue; } switch (san.type) { /* * otherName */ case MBEDTLS_X509_SAN_OTHER_NAME: { mbedtls_x509_san_other_name *other_name = &san.san.other_name; ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &other_name->type_id) == 0) { ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_oid_get_numeric_string(p, n, &other_name->value.hardware_module_name.oid); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) { ret = mbedtls_snprintf(p, n, "%02X", other_name->value.hardware_module_name.val.p[i]); MBEDTLS_X509_SAFE_SNPRINTF; } }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ } break; /* * uniformResourceIdentifier */ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: { ret = mbedtls_snprintf(p, n, "\n%s uniformResourceIdentifier : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if (san.san.unstructured_name.len >= n) { if (n > 0) { *p = '\0'; } return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); p += san.san.unstructured_name.len; n -= san.san.unstructured_name.len; } break; /* * dNSName * RFC822 Name */ case MBEDTLS_X509_SAN_DNS_NAME: case MBEDTLS_X509_SAN_RFC822_NAME: { const char *dns_name = "dNSName"; const char *rfc822_name = "rfc822Name"; ret = mbedtls_snprintf(p, n, "\n%s %s : ", prefix, san.type == MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name); MBEDTLS_X509_SAFE_SNPRINTF; if (san.san.unstructured_name.len >= n) { if (n > 0) { *p = '\0'; } return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); p += san.san.unstructured_name.len; n -= san.san.unstructured_name.len; } break; /* * iPAddress */ case MBEDTLS_X509_SAN_IP_ADDRESS: { ret = mbedtls_snprintf(p, n, "\n%s %s : ", prefix, "iPAddress"); MBEDTLS_X509_SAFE_SNPRINTF; if (san.san.unstructured_name.len >= n) { if (n > 0) { *p = '\0'; } return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } unsigned char *ip = san.san.unstructured_name.p; // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported if (san.san.unstructured_name.len == 4) { ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); MBEDTLS_X509_SAFE_SNPRINTF; } else if (san.san.unstructured_name.len == 16) { ret = mbedtls_snprintf(p, n, "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X", ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]); MBEDTLS_X509_SAFE_SNPRINTF; } else { if (n > 0) { *p = '\0'; } return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } } break; /* * directoryName */ case MBEDTLS_X509_SAN_DIRECTORY_NAME: { ret = mbedtls_snprintf(p, n, "\n%s directoryName : ", prefix); if (ret < 0 || (size_t) ret >= n) { mbedtls_x509_free_subject_alt_name(&san); } MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name); if (ret < 0) { mbedtls_x509_free_subject_alt_name(&san); if (n > 0) { *p = '\0'; } return ret; } p += ret; n -= ret; } break; /* * Type not supported, skip item. */ default: ret = mbedtls_snprintf(p, n, "\n%s ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; break; } /* So far memory is freed only in the case of directoryName * parsing succeeding, as mbedtls_x509_get_name allocates memory. */ mbedtls_x509_free_subject_alt_name(&san); cur = cur->next; } *p = '\0'; *size = n; *buf = p; return 0; } #define PRINT_ITEM(i) \ do { \ ret = mbedtls_snprintf(p, n, "%s" i, sep); \ MBEDTLS_X509_SAFE_SNPRINTF; \ sep = ", "; \ } while (0) #define CERT_TYPE(type, name) \ do { \ if (ns_cert_type & (type)) { \ PRINT_ITEM(name); \ } \ } while (0) int mbedtls_x509_info_cert_type(char **buf, size_t *size, unsigned char ns_cert_type) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n = *size; char *p = *buf; const char *sep = ""; CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA"); *size = n; *buf = p; return 0; } #define KEY_USAGE(code, name) \ do { \ if ((key_usage) & (code)) { \ PRINT_ITEM(name); \ } \ } while (0) int mbedtls_x509_info_key_usage(char **buf, size_t *size, unsigned int key_usage) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n = *size; char *p = *buf; const char *sep = ""; KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature"); KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation"); KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment"); KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment"); KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement"); KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign"); KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign"); KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only"); KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only"); *size = n; *buf = p; return 0; } #endif /* MBEDTLS_X509_REMOVE_INFO */ #endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */ #endif /* MBEDTLS_X509_USE_C */ webfakes/src/mbedtls/library/mps_error.h0000644000176200001440000000612714740737024020125 0ustar liggesusers/* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** * \file mps_error.h * * \brief Error codes used by MPS */ #ifndef MBEDTLS_MPS_ERROR_H #define MBEDTLS_MPS_ERROR_H /* TODO: The error code allocation needs to be revisited: * * - Should we make (some of) the MPS Reader error codes public? * If so, we need to adjust MBEDTLS_MPS_READER_MAKE_ERROR() to hit * a gap in the Mbed TLS public error space. * If not, we have to make sure we don't forward those errors * at the level of the public API -- no risk at the moment as * long as MPS is an experimental component not accessible from * public API. */ /** * \name SECTION: MPS general error codes * * \{ */ #ifndef MBEDTLS_MPS_ERR_BASE #define MBEDTLS_MPS_ERR_BASE (0) #endif #define MBEDTLS_MPS_MAKE_ERROR(code) \ (-(MBEDTLS_MPS_ERR_BASE | (code))) #define MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED MBEDTLS_MPS_MAKE_ERROR(0x1) #define MBEDTLS_ERR_MPS_INTERNAL_ERROR MBEDTLS_MPS_MAKE_ERROR(0x2) /* \} name SECTION: MPS general error codes */ /** * \name SECTION: MPS Reader error codes * * \{ */ #ifndef MBEDTLS_MPS_READER_ERR_BASE #define MBEDTLS_MPS_READER_ERR_BASE (1 << 8) #endif #define MBEDTLS_MPS_READER_MAKE_ERROR(code) \ (-(MBEDTLS_MPS_READER_ERR_BASE | (code))) /*! An attempt to reclaim the data buffer from a reader failed because * the user hasn't yet read and committed all of it. */ #define MBEDTLS_ERR_MPS_READER_DATA_LEFT MBEDTLS_MPS_READER_MAKE_ERROR(0x1) /*! An invalid argument was passed to the reader. */ #define MBEDTLS_ERR_MPS_READER_INVALID_ARG MBEDTLS_MPS_READER_MAKE_ERROR(0x2) /*! An attempt to move a reader to consuming mode through mbedtls_mps_reader_feed() * after pausing failed because the provided data is not sufficient to serve the * read requests that led to the pausing. */ #define MBEDTLS_ERR_MPS_READER_NEED_MORE MBEDTLS_MPS_READER_MAKE_ERROR(0x3) /*! A get request failed because not enough data is available in the reader. */ #define MBEDTLS_ERR_MPS_READER_OUT_OF_DATA MBEDTLS_MPS_READER_MAKE_ERROR(0x4) /*!< A get request after pausing and reactivating the reader failed because * the request is not in line with the request made prior to pausing. The user * must not change it's 'strategy' after pausing and reactivating a reader. */ #define MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS MBEDTLS_MPS_READER_MAKE_ERROR(0x5) /*! An attempt to reclaim the data buffer from a reader failed because the reader * has no accumulator it can use to backup the data that hasn't been processed. */ #define MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR MBEDTLS_MPS_READER_MAKE_ERROR(0x6) /*! An attempt to reclaim the data buffer from a reader failed because the * accumulator passed to the reader is not large enough to hold both the * data that hasn't been processed and the excess of the last read-request. */ #define MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL MBEDTLS_MPS_READER_MAKE_ERROR(0x7) /* \} name SECTION: MPS Reader error codes */ #endif /* MBEDTLS_MPS_ERROR_H */ webfakes/src/mbedtls/library/psa_crypto_cipher.c0000644000176200001440000005536714740737024021637 0ustar liggesusers/* * PSA cipher driver entry points */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include "psa_crypto_cipher.h" #include "psa_crypto_core.h" #include "psa_crypto_random_impl.h" #include "mbedtls/cipher.h" #include "mbedtls/error.h" #include /* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols * are enabled, but it does not provide any compatibility check between them * (i.e. if the specified key works with the specified algorithm). This helper * function is meant to provide this support. * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it * requires CIPHER_C to be enabled. */ static psa_status_t mbedtls_cipher_validate_values( psa_algorithm_t alg, psa_key_type_t key_type) { /* Reduce code size - hinting to the compiler about what it can assume allows the compiler to eliminate bits of the logic below. */ #if !defined(PSA_WANT_KEY_TYPE_AES) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES); #endif #if !defined(PSA_WANT_KEY_TYPE_ARIA) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA); #endif #if !defined(PSA_WANT_KEY_TYPE_CAMELLIA) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA); #endif #if !defined(PSA_WANT_KEY_TYPE_CHACHA20) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20); #endif #if !defined(PSA_WANT_KEY_TYPE_DES) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES); #endif #if !defined(PSA_WANT_ALG_CCM) MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0)); #endif #if !defined(PSA_WANT_ALG_GCM) MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0)); #endif #if !defined(PSA_WANT_ALG_STREAM_CIPHER) MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER); #endif #if !defined(PSA_WANT_ALG_CHACHA20_POLY1305) MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)); #endif #if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG); #endif #if !defined(PSA_WANT_ALG_CTR) MBEDTLS_ASSUME(alg != PSA_ALG_CTR); #endif #if !defined(PSA_WANT_ALG_CFB) MBEDTLS_ASSUME(alg != PSA_ALG_CFB); #endif #if !defined(PSA_WANT_ALG_OFB) MBEDTLS_ASSUME(alg != PSA_ALG_OFB); #endif #if !defined(PSA_WANT_ALG_XTS) MBEDTLS_ASSUME(alg != PSA_ALG_XTS); #endif #if !defined(PSA_WANT_ALG_ECB_NO_PADDING) MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING); #endif #if !defined(PSA_WANT_ALG_CBC_NO_PADDING) MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING); #endif #if !defined(PSA_WANT_ALG_CBC_PKCS7) MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7); #endif #if !defined(PSA_WANT_ALG_CMAC) MBEDTLS_ASSUME(alg != PSA_ALG_CMAC); #endif if (alg == PSA_ALG_STREAM_CIPHER || alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) { if (key_type == PSA_KEY_TYPE_CHACHA20) { return PSA_SUCCESS; } } if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) || alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) || alg == PSA_ALG_CCM_STAR_NO_TAG) { if (key_type == PSA_KEY_TYPE_AES || key_type == PSA_KEY_TYPE_ARIA || key_type == PSA_KEY_TYPE_CAMELLIA) { return PSA_SUCCESS; } } if (alg == PSA_ALG_CTR || alg == PSA_ALG_CFB || alg == PSA_ALG_OFB || alg == PSA_ALG_XTS || alg == PSA_ALG_ECB_NO_PADDING || alg == PSA_ALG_CBC_NO_PADDING || alg == PSA_ALG_CBC_PKCS7 || alg == PSA_ALG_CMAC) { if (key_type == PSA_KEY_TYPE_AES || key_type == PSA_KEY_TYPE_ARIA || key_type == PSA_KEY_TYPE_DES || key_type == PSA_KEY_TYPE_CAMELLIA) { return PSA_SUCCESS; } } return PSA_ERROR_NOT_SUPPORTED; } psa_status_t mbedtls_cipher_values_from_psa( psa_algorithm_t alg, psa_key_type_t key_type, size_t *key_bits, mbedtls_cipher_mode_t *mode, mbedtls_cipher_id_t *cipher_id) { mbedtls_cipher_id_t cipher_id_tmp; /* Only DES modifies key_bits */ #if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) (void) key_bits; #endif if (PSA_ALG_IS_AEAD(alg)) { alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0); } if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) { switch (alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) case PSA_ALG_STREAM_CIPHER: *mode = MBEDTLS_MODE_STREAM; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) case PSA_ALG_CTR: *mode = MBEDTLS_MODE_CTR; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) case PSA_ALG_CFB: *mode = MBEDTLS_MODE_CFB; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) case PSA_ALG_OFB: *mode = MBEDTLS_MODE_OFB; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) case PSA_ALG_ECB_NO_PADDING: *mode = MBEDTLS_MODE_ECB; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) case PSA_ALG_CBC_NO_PADDING: *mode = MBEDTLS_MODE_CBC; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) case PSA_ALG_CBC_PKCS7: *mode = MBEDTLS_MODE_CBC; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) case PSA_ALG_CCM_STAR_NO_TAG: *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): *mode = MBEDTLS_MODE_CCM; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): *mode = MBEDTLS_MODE_GCM; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): *mode = MBEDTLS_MODE_CHACHAPOLY; break; #endif default: return PSA_ERROR_NOT_SUPPORTED; } } else if (alg == PSA_ALG_CMAC) { *mode = MBEDTLS_MODE_ECB; } else { return PSA_ERROR_NOT_SUPPORTED; } switch (key_type) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES) case PSA_KEY_TYPE_AES: cipher_id_tmp = MBEDTLS_CIPHER_ID_AES; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA) case PSA_KEY_TYPE_ARIA: cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) case PSA_KEY_TYPE_DES: /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES, * and 192 for three-key Triple-DES. */ if (*key_bits == 64) { cipher_id_tmp = MBEDTLS_CIPHER_ID_DES; } else { cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES; } /* mbedtls doesn't recognize two-key Triple-DES as an algorithm, * but two-key Triple-DES is functionally three-key Triple-DES * with K1=K3, so that's how we present it to mbedtls. */ if (*key_bits == 128) { *key_bits = 192; } break; #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA) case PSA_KEY_TYPE_CAMELLIA: cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20) case PSA_KEY_TYPE_CHACHA20: cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20; break; #endif default: return PSA_ERROR_NOT_SUPPORTED; } if (cipher_id != NULL) { *cipher_id = cipher_id_tmp; } return mbedtls_cipher_validate_values(alg, key_type); } #if defined(MBEDTLS_CIPHER_C) const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits, mbedtls_cipher_id_t *cipher_id) { mbedtls_cipher_mode_t mode; psa_status_t status; mbedtls_cipher_id_t cipher_id_tmp = MBEDTLS_CIPHER_ID_NONE; status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp); if (status != PSA_SUCCESS) { return NULL; } if (cipher_id != NULL) { *cipher_id = cipher_id_tmp; } return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode); } #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) static psa_status_t psa_cipher_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, mbedtls_operation_t cipher_operation) { int ret = 0; size_t key_bits; const mbedtls_cipher_info_t *cipher_info = NULL; psa_key_type_t key_type = attributes->type; (void) key_buffer_size; mbedtls_cipher_init(&operation->ctx.cipher); operation->alg = alg; key_bits = attributes->bits; cipher_info = mbedtls_cipher_info_from_psa(alg, key_type, key_bits, NULL); if (cipher_info == NULL) { return PSA_ERROR_NOT_SUPPORTED; } ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info); if (ret != 0) { goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) { /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */ uint8_t keys[24]; memcpy(keys, key_buffer, 16); memcpy(keys + 16, key_buffer, 8); ret = mbedtls_cipher_setkey(&operation->ctx.cipher, keys, 192, cipher_operation); } else #endif { ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer, (int) key_bits, cipher_operation); } if (ret != 0) { goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) switch (alg) { case PSA_ALG_CBC_NO_PADDING: ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher, MBEDTLS_PADDING_NONE); break; case PSA_ALG_CBC_PKCS7: ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher, MBEDTLS_PADDING_PKCS7); break; default: /* The algorithm doesn't involve padding. */ ret = 0; break; } if (ret != 0) { goto exit; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING || MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */ operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 : PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type)); operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg); exit: return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_cipher_encrypt_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { return psa_cipher_setup(operation, attributes, key_buffer, key_buffer_size, alg, MBEDTLS_ENCRYPT); } psa_status_t mbedtls_psa_cipher_decrypt_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { return psa_cipher_setup(operation, attributes, key_buffer, key_buffer_size, alg, MBEDTLS_DECRYPT); } psa_status_t mbedtls_psa_cipher_set_iv( mbedtls_psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length) { if (iv_length != operation->iv_length) { return PSA_ERROR_INVALID_ARGUMENT; } return mbedtls_to_psa_error( mbedtls_cipher_set_iv(&operation->ctx.cipher, iv, iv_length)); } #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) /** Process input for which the algorithm is set to ECB mode. * * This requires manual processing, since the PSA API is defined as being * able to process arbitrary-length calls to psa_cipher_update() with ECB mode, * but the underlying mbedtls_cipher_update only takes full blocks. * * \param ctx The mbedtls cipher context to use. It must have been * set up for ECB. * \param[in] input The input plaintext or ciphertext to process. * \param input_length The number of bytes to process from \p input. * This does not need to be aligned to a block boundary. * If there is a partial block at the end of the input, * it is stored in \p ctx for future processing. * \param output The buffer where the output is written. It must be * at least `BS * floor((p + input_length) / BS)` bytes * long, where `p` is the number of bytes in the * unprocessed partial block in \p ctx (with * `0 <= p <= BS - 1`) and `BS` is the block size. * \param output_length On success, the number of bytes written to \p output. * \c 0 on error. * * \return #PSA_SUCCESS or an error from a hardware accelerator */ static psa_status_t psa_cipher_update_ecb( mbedtls_cipher_context_t *ctx, const uint8_t *input, size_t input_length, uint8_t *output, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); size_t internal_output_length = 0; *output_length = 0; if (input_length == 0) { status = PSA_SUCCESS; goto exit; } if (ctx->unprocessed_len > 0) { /* Fill up to block size, and run the block if there's a full one. */ size_t bytes_to_copy = block_size - ctx->unprocessed_len; if (input_length < bytes_to_copy) { bytes_to_copy = input_length; } memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, bytes_to_copy); input_length -= bytes_to_copy; input += bytes_to_copy; ctx->unprocessed_len += bytes_to_copy; if (ctx->unprocessed_len == block_size) { status = mbedtls_to_psa_error( mbedtls_cipher_update(ctx, ctx->unprocessed_data, block_size, output, &internal_output_length)); if (status != PSA_SUCCESS) { goto exit; } output += internal_output_length; *output_length += internal_output_length; ctx->unprocessed_len = 0; } } while (input_length >= block_size) { /* Run all full blocks we have, one by one */ status = mbedtls_to_psa_error( mbedtls_cipher_update(ctx, input, block_size, output, &internal_output_length)); if (status != PSA_SUCCESS) { goto exit; } input_length -= block_size; input += block_size; output += internal_output_length; *output_length += internal_output_length; } if (input_length > 0) { /* Save unprocessed bytes for later processing */ memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, input_length); ctx->unprocessed_len += input_length; } status = PSA_SUCCESS; exit: return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */ psa_status_t mbedtls_psa_cipher_update( mbedtls_psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t expected_output_size; if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) { /* Take the unprocessed partial block left over from previous * update calls, if any, plus the input to this call. Remove * the last partial block, if any. You get the data that will be * output in this call. */ expected_output_size = (operation->ctx.cipher.unprocessed_len + input_length) / operation->block_length * operation->block_length; } else { expected_output_size = input_length; } if (output_size < expected_output_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) if (operation->alg == PSA_ALG_ECB_NO_PADDING) { /* mbedtls_cipher_update has an API inconsistency: it will only * process a single block at a time in ECB mode. Abstract away that * inconsistency here to match the PSA API behaviour. */ status = psa_cipher_update_ecb(&operation->ctx.cipher, input, input_length, output, output_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */ if (input_length == 0) { /* There is no input, nothing to be done */ *output_length = 0; status = PSA_SUCCESS; } else { status = mbedtls_to_psa_error( mbedtls_cipher_update(&operation->ctx.cipher, input, input_length, output, output_length)); if (*output_length > output_size) { return PSA_ERROR_CORRUPTION_DETECTED; } } return status; } psa_status_t mbedtls_psa_cipher_finish( mbedtls_psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; if (operation->ctx.cipher.unprocessed_len != 0) { if (operation->alg == PSA_ALG_ECB_NO_PADDING || operation->alg == PSA_ALG_CBC_NO_PADDING) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } } status = mbedtls_to_psa_error( mbedtls_cipher_finish(&operation->ctx.cipher, temp_output_buffer, output_length)); if (status != PSA_SUCCESS) { goto exit; } if (*output_length == 0) { ; /* Nothing to copy. Note that output may be NULL in this case. */ } else if (output_size >= *output_length) { memcpy(output, temp_output_buffer, *output_length); } else { status = PSA_ERROR_BUFFER_TOO_SMALL; } exit: mbedtls_platform_zeroize(temp_output_buffer, sizeof(temp_output_buffer)); return status; } psa_status_t mbedtls_psa_cipher_abort( mbedtls_psa_cipher_operation_t *operation) { /* Sanity check (shouldn't happen: operation->alg should * always have been initialized to a valid value). */ if (!PSA_ALG_IS_CIPHER(operation->alg)) { return PSA_ERROR_BAD_STATE; } mbedtls_cipher_free(&operation->ctx.cipher); return PSA_SUCCESS; } psa_status_t mbedtls_psa_cipher_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *iv, size_t iv_length, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT; size_t update_output_length, finish_output_length; status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } if (iv_length > 0) { status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length); if (status != PSA_SUCCESS) { goto exit; } } status = mbedtls_psa_cipher_update(&operation, input, input_length, output, output_size, &update_output_length); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_cipher_finish( &operation, mbedtls_buffer_offset(output, update_output_length), output_size - update_output_length, &finish_output_length); if (status != PSA_SUCCESS) { goto exit; } *output_length = update_output_length + finish_output_length; exit: if (status == PSA_SUCCESS) { status = mbedtls_psa_cipher_abort(&operation); } else { mbedtls_psa_cipher_abort(&operation); } return status; } psa_status_t mbedtls_psa_cipher_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT; size_t olength, accumulated_length; status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } if (operation.iv_length > 0) { status = mbedtls_psa_cipher_set_iv(&operation, input, operation.iv_length); if (status != PSA_SUCCESS) { goto exit; } } status = mbedtls_psa_cipher_update( &operation, mbedtls_buffer_offset_const(input, operation.iv_length), input_length - operation.iv_length, output, output_size, &olength); if (status != PSA_SUCCESS) { goto exit; } accumulated_length = olength; status = mbedtls_psa_cipher_finish( &operation, mbedtls_buffer_offset(output, accumulated_length), output_size - accumulated_length, &olength); if (status != PSA_SUCCESS) { goto exit; } *output_length = accumulated_length + olength; exit: if (status == PSA_SUCCESS) { status = mbedtls_psa_cipher_abort(&operation); } else { mbedtls_psa_cipher_abort(&operation); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/ssl_tls13_keys.c0000644000176200001440000017630214740737024020775 0ustar liggesusers/* * TLS 1.3 key schedule * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #include #include #include "mbedtls/hkdf.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "ssl_misc.h" #include "ssl_tls13_keys.h" #include "ssl_tls13_invasive.h" #include "psa/crypto.h" #include "mbedtls/psa_util.h" /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ .name = string, struct mbedtls_ssl_tls13_labels_struct const mbedtls_ssl_tls13_labels = { /* This seems to work in C, despite the string literal being one * character too long due to the 0-termination. */ MBEDTLS_SSL_TLS1_3_LABEL_LIST }; #undef MBEDTLS_SSL_TLS1_3_LABEL /* * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule. * * The HkdfLabel is specified in RFC 8446 as follows: * * struct HkdfLabel { * uint16 length; // Length of expanded key material * opaque label<7..255>; // Always prefixed by "tls13 " * opaque context<0..255>; // Usually a communication transcript hash * }; * * Parameters: * - desired_length: Length of expanded key material * Even though the standard allows expansion to up to * 2**16 Bytes, TLS 1.3 never uses expansion to more than * 255 Bytes, so we require `desired_length` to be at most * 255. This allows us to save a few Bytes of code by * hardcoding the writing of the high bytes. * - (label, label_len): label + label length, without "tls13 " prefix * The label length MUST be less than or equal to * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN * It is the caller's responsibility to ensure this. * All (label, label length) pairs used in TLS 1.3 * can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(). * - (ctx, ctx_len): context + context length * The context length MUST be less than or equal to * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN * It is the caller's responsibility to ensure this. * - dst: Target buffer for HkdfLabel structure, * This MUST be a writable buffer of size * at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes. * - dst_len: Pointer at which to store the actual length of * the HkdfLabel structure on success. */ static const char tls13_label_prefix[6] = "tls13 "; #define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(label_len, context_len) \ (2 /* expansion length */ \ + 1 /* label length */ \ + label_len \ + 1 /* context length */ \ + context_len) #define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN \ SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( \ sizeof(tls13_label_prefix) + \ MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN, \ MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) static void ssl_tls13_hkdf_encode_label( size_t desired_length, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, unsigned char *dst, size_t *dst_len) { size_t total_label_len = sizeof(tls13_label_prefix) + label_len; size_t total_hkdf_lbl_len = SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(total_label_len, ctx_len); unsigned char *p = dst; /* Add the size of the expanded key material. * We're hardcoding the high byte to 0 here assuming that we never use * TLS 1.3 HKDF key expansion to more than 255 Bytes. */ #if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255 #error "The implementation of ssl_tls13_hkdf_encode_label() is not fit for the \ value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN" #endif *p++ = 0; *p++ = MBEDTLS_BYTE_0(desired_length); /* Add label incl. prefix */ *p++ = MBEDTLS_BYTE_0(total_label_len); memcpy(p, tls13_label_prefix, sizeof(tls13_label_prefix)); p += sizeof(tls13_label_prefix); memcpy(p, label, label_len); p += label_len; /* Add context value */ *p++ = MBEDTLS_BYTE_0(ctx_len); if (ctx_len != 0) { memcpy(p, ctx, ctx_len); } /* Return total length to the caller. */ *dst_len = total_hkdf_lbl_len; } int mbedtls_ssl_tls13_hkdf_expand_label( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, unsigned char *buf, size_t buf_len) { unsigned char hkdf_label[SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN]; size_t hkdf_label_len = 0; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; if (label_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN) { /* Should never happen since this is an internal * function, and we know statically which labels * are allowed. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (ctx_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) { /* Should not happen, as above. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (buf_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN) { /* Should not happen, as above. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl_tls13_hkdf_encode_label(buf_len, label, label_len, ctx, ctx_len, hkdf_label, &hkdf_label_len); status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF_EXPAND(hash_alg)); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SECRET, secret, secret_len); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_INFO, hkdf_label, hkdf_label_len); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_output_bytes(&operation, buf, buf_len); if (status != PSA_SUCCESS) { goto cleanup; } cleanup: abort_status = psa_key_derivation_abort(&operation); status = (status == PSA_SUCCESS ? abort_status : status); mbedtls_platform_zeroize(hkdf_label, hkdf_label_len); return PSA_TO_MBEDTLS_ERR(status); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_make_traffic_key( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, unsigned char *key, size_t key_len, unsigned char *iv, size_t iv_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, secret, secret_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(key), NULL, 0, key, key_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, secret, secret_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(iv), NULL, 0, iv, iv_len); return ret; } /* * The traffic keying material is generated from the following inputs: * * - One secret value per sender. * - A purpose value indicating the specific value being generated * - The desired lengths of key and IV. * * The expansion itself is based on HKDF: * * [sender]_write_key = HKDF-Expand-Label( Secret, "key", "", key_length ) * [sender]_write_iv = HKDF-Expand-Label( Secret, "iv" , "", iv_length ) * * [sender] denotes the sending side and the Secret value is provided * by the function caller. Note that we generate server and client side * keys in a single function call. */ int mbedtls_ssl_tls13_make_traffic_keys( psa_algorithm_t hash_alg, const unsigned char *client_secret, const unsigned char *server_secret, size_t secret_len, size_t key_len, size_t iv_len, mbedtls_ssl_key_set *keys) { int ret = 0; ret = ssl_tls13_make_traffic_key( hash_alg, client_secret, secret_len, keys->client_write_key, key_len, keys->client_write_iv, iv_len); if (ret != 0) { return ret; } ret = ssl_tls13_make_traffic_key( hash_alg, server_secret, secret_len, keys->server_write_key, key_len, keys->server_write_iv, iv_len); if (ret != 0) { return ret; } keys->key_len = key_len; keys->iv_len = iv_len; return 0; } int mbedtls_ssl_tls13_derive_secret( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, int ctx_hashed, unsigned char *dstbuf, size_t dstbuf_len) { int ret; unsigned char hashed_context[PSA_HASH_MAX_SIZE]; if (ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_hash_compute(hash_alg, ctx, ctx_len, hashed_context, PSA_HASH_LENGTH(hash_alg), &ctx_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); return ret; } } else { if (ctx_len > sizeof(hashed_context)) { /* This should never happen since this function is internal * and the code sets `ctx_hashed` correctly. * Let's double-check nonetheless to not run at the risk * of getting a stack overflow. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(hashed_context, ctx, ctx_len); } return mbedtls_ssl_tls13_hkdf_expand_label(hash_alg, secret, secret_len, label, label_len, hashed_context, ctx_len, dstbuf, dstbuf_len); } int mbedtls_ssl_tls13_evolve_secret( psa_algorithm_t hash_alg, const unsigned char *secret_old, const unsigned char *input, size_t input_len, unsigned char *secret_new) { int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; size_t hlen; unsigned char tmp_secret[PSA_MAC_MAX_SIZE] = { 0 }; const unsigned char all_zeroes_input[MBEDTLS_TLS1_3_MD_MAX_SIZE] = { 0 }; const unsigned char *l_input = NULL; size_t l_input_len; psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } hlen = PSA_HASH_LENGTH(hash_alg); /* For non-initial runs, call Derive-Secret( ., "derived", "") * on the old secret. */ if (secret_old != NULL) { ret = mbedtls_ssl_tls13_derive_secret( hash_alg, secret_old, hlen, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(derived), NULL, 0, /* context */ MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, tmp_secret, hlen); if (ret != 0) { goto cleanup; } } ret = 0; if (input != NULL && input_len != 0) { l_input = input; l_input_len = input_len; } else { l_input = all_zeroes_input; l_input_len = hlen; } status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF_EXTRACT(hash_alg)); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, tmp_secret, hlen); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SECRET, l_input, l_input_len); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_output_bytes(&operation, secret_new, PSA_HASH_LENGTH(hash_alg)); if (status != PSA_SUCCESS) { goto cleanup; } cleanup: abort_status = psa_key_derivation_abort(&operation); status = (status == PSA_SUCCESS ? abort_status : status); ret = (ret == 0 ? PSA_TO_MBEDTLS_ERR(status) : ret); mbedtls_platform_zeroize(tmp_secret, sizeof(tmp_secret)); return ret; } int mbedtls_ssl_tls13_derive_early_secrets( psa_algorithm_t hash_alg, unsigned char const *early_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_early_secrets *derived) { int ret; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * 0 * | * v * PSK -> HKDF-Extract = Early Secret * | * +-----> Derive-Secret(., "c e traffic", ClientHello) * | = client_early_traffic_secret * | * +-----> Derive-Secret(., "e exp master", ClientHello) * | = early_exporter_master_secret * v */ /* Create client_early_traffic_secret */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, early_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_e_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->client_early_traffic_secret, hash_len); if (ret != 0) { return ret; } /* Create early exporter */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, early_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(e_exp_master), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->early_exporter_master_secret, hash_len); if (ret != 0) { return ret; } return 0; } int mbedtls_ssl_tls13_derive_handshake_secrets( psa_algorithm_t hash_alg, unsigned char const *handshake_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_handshake_secrets *derived) { int ret; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * * Handshake Secret * | * +-----> Derive-Secret( ., "c hs traffic", * | ClientHello...ServerHello ) * | = client_handshake_traffic_secret * | * +-----> Derive-Secret( ., "s hs traffic", * | ClientHello...ServerHello ) * | = server_handshake_traffic_secret * */ /* * Compute client_handshake_traffic_secret with * Derive-Secret( ., "c hs traffic", ClientHello...ServerHello ) */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, handshake_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_hs_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->client_handshake_traffic_secret, hash_len); if (ret != 0) { return ret; } /* * Compute server_handshake_traffic_secret with * Derive-Secret( ., "s hs traffic", ClientHello...ServerHello ) */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, handshake_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_hs_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->server_handshake_traffic_secret, hash_len); if (ret != 0) { return ret; } return 0; } int mbedtls_ssl_tls13_derive_application_secrets( psa_algorithm_t hash_alg, unsigned char const *application_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_application_secrets *derived) { int ret; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Generate {client,server}_application_traffic_secret_0 * * Master Secret * | * +-----> Derive-Secret( ., "c ap traffic", * | ClientHello...server Finished ) * | = client_application_traffic_secret_0 * | * +-----> Derive-Secret( ., "s ap traffic", * | ClientHello...Server Finished ) * | = server_application_traffic_secret_0 * | * +-----> Derive-Secret( ., "exp master", * | ClientHello...server Finished) * | = exporter_master_secret * */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, application_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_ap_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->client_application_traffic_secret_N, hash_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_derive_secret( hash_alg, application_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_ap_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->server_application_traffic_secret_N, hash_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_derive_secret( hash_alg, application_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exp_master), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->exporter_master_secret, hash_len); if (ret != 0) { return ret; } return 0; } /* Generate resumption_master_secret for use with the ticket exchange. * * This is not integrated with mbedtls_ssl_tls13_derive_application_secrets() * because it uses the transcript hash up to and including ClientFinished. */ int mbedtls_ssl_tls13_derive_resumption_master_secret( psa_algorithm_t hash_alg, unsigned char const *application_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_application_secrets *derived) { int ret; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ret = mbedtls_ssl_tls13_derive_secret( hash_alg, application_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_master), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->resumption_master_secret, hash_len); if (ret != 0) { return ret; } return 0; } /** * \brief Transition into application stage of TLS 1.3 key schedule. * * The TLS 1.3 key schedule can be viewed as a simple state machine * with states Initial -> Early -> Handshake -> Application, and * this function represents the Handshake -> Application transition. * * In the handshake stage, ssl_tls13_generate_application_keys() * can be used to derive the handshake traffic keys. * * \param ssl The SSL context to operate on. This must be in key schedule * stage \c Handshake. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_schedule_stage_application(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type( (mbedtls_md_type_t) handshake->ciphersuite_info->mac); /* * Compute MasterSecret */ ret = mbedtls_ssl_tls13_evolve_secret( hash_alg, handshake->tls13_master_secrets.handshake, NULL, 0, handshake->tls13_master_secrets.app); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF( 4, "Master secret", handshake->tls13_master_secrets.app, PSA_HASH_LENGTH(hash_alg)); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_calc_finished_core(psa_algorithm_t hash_alg, unsigned char const *base_key, unsigned char const *transcript, unsigned char *dst, size_t *dst_len) { mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t hash_len = PSA_HASH_LENGTH(hash_alg); unsigned char finished_key[PSA_MAC_MAX_SIZE]; int ret; psa_algorithm_t alg; /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* TLS 1.3 Finished message * * struct { * opaque verify_data[Hash.length]; * } Finished; * * verify_data = * HMAC( finished_key, * Hash( Handshake Context + * Certificate* + * CertificateVerify* ) * ) * * finished_key = * HKDF-Expand-Label( BaseKey, "finished", "", Hash.length ) */ ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, base_key, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(finished), NULL, 0, finished_key, hash_len); if (ret != 0) { goto exit; } alg = PSA_ALG_HMAC(hash_alg); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); status = psa_import_key(&attributes, finished_key, hash_len, &key); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_compute(key, alg, transcript, hash_len, dst, hash_len, dst_len); ret = PSA_TO_MBEDTLS_ERR(status); exit: status = psa_destroy_key(key); if (ret == 0) { ret = PSA_TO_MBEDTLS_ERR(status); } mbedtls_platform_zeroize(finished_key, sizeof(finished_key)); return ret; } int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl, unsigned char *dst, size_t dst_len, size_t *actual_len, int from) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; unsigned char *base_key = NULL; size_t base_key_len = 0; mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = &ssl->handshake->tls13_hs_secrets; mbedtls_md_type_t const md_type = (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac; psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type( (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac); size_t const hash_len = PSA_HASH_LENGTH(hash_alg); MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_tls13_calculate_verify_data")); if (from == MBEDTLS_SSL_IS_CLIENT) { base_key = tls13_hs_secrets->client_handshake_traffic_secret; base_key_len = sizeof(tls13_hs_secrets->client_handshake_traffic_secret); } else { base_key = tls13_hs_secrets->server_handshake_traffic_secret; base_key_len = sizeof(tls13_hs_secrets->server_handshake_traffic_secret); } if (dst_len < hash_len) { ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; goto exit; } ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); goto exit; } MBEDTLS_SSL_DEBUG_BUF(4, "handshake hash", transcript, transcript_len); ret = ssl_tls13_calc_finished_core(hash_alg, base_key, transcript, dst, actual_len); if (ret != 0) { goto exit; } MBEDTLS_SSL_DEBUG_BUF(3, "verify_data for finished message", dst, hash_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_tls13_calculate_verify_data")); exit: /* Erase handshake secrets */ mbedtls_platform_zeroize(base_key, base_key_len); mbedtls_platform_zeroize(transcript, sizeof(transcript)); return ret; } int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl, const psa_algorithm_t hash_alg, unsigned char const *psk, size_t psk_len, int psk_type, unsigned char const *transcript, unsigned char *result) { int ret = 0; unsigned char binder_key[PSA_MAC_MAX_SIZE]; unsigned char early_secret[PSA_MAC_MAX_SIZE]; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); size_t actual_len; #if !defined(MBEDTLS_DEBUG_C) ssl = NULL; /* make sure we don't use it except for debug */ ((void) ssl); #endif /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * 0 * | * v * PSK -> HKDF-Extract = Early Secret * | * +-----> Derive-Secret(., "ext binder" | "res binder", "") * | = binder_key * v */ ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, NULL, /* Old secret */ psk, psk_len, /* Input */ early_secret); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); goto exit; } MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_create_psk_binder", early_secret, hash_len); if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { ret = mbedtls_ssl_tls13_derive_secret( hash_alg, early_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_binder), NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, binder_key, hash_len); MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'res binder'")); } else { ret = mbedtls_ssl_tls13_derive_secret( hash_alg, early_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(ext_binder), NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, binder_key, hash_len); MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'ext binder'")); } if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_secret", ret); goto exit; } /* * The binding_value is computed in the same way as the Finished message * but with the BaseKey being the binder_key. */ ret = ssl_tls13_calc_finished_core(hash_alg, binder_key, transcript, result, &actual_len); if (ret != 0) { goto exit; } MBEDTLS_SSL_DEBUG_BUF(3, "psk binder", result, actual_len); exit: mbedtls_platform_zeroize(early_secret, sizeof(early_secret)); mbedtls_platform_zeroize(binder_key, sizeof(binder_key)); return ret; } int mbedtls_ssl_tls13_populate_transform( mbedtls_ssl_transform *transform, int endpoint, int ciphersuite, mbedtls_ssl_key_set const *traffic_keys, mbedtls_ssl_context *ssl /* DEBUG ONLY */) { #if !defined(MBEDTLS_USE_PSA_CRYPTO) int ret; mbedtls_cipher_info_t const *cipher_info; #endif /* MBEDTLS_USE_PSA_CRYPTO */ const mbedtls_ssl_ciphersuite_t *ciphersuite_info; unsigned char const *key_enc; unsigned char const *iv_enc; unsigned char const *key_dec; unsigned char const *iv_dec; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_type_t key_type; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t alg; size_t key_bits; psa_status_t status = PSA_SUCCESS; #endif #if !defined(MBEDTLS_DEBUG_C) ssl = NULL; /* make sure we don't use it except for those cases */ (void) ssl; #endif ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); if (ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found", ciphersuite)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher); if (cipher_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found", ciphersuite_info->cipher)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * Setup cipher contexts in target transform */ if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc, cipher_info)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); return ret; } if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec, cipher_info)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SRV_C) if (endpoint == MBEDTLS_SSL_IS_SERVER) { key_enc = traffic_keys->server_write_key; key_dec = traffic_keys->client_write_key; iv_enc = traffic_keys->server_write_iv; iv_dec = traffic_keys->client_write_iv; } else #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) if (endpoint == MBEDTLS_SSL_IS_CLIENT) { key_enc = traffic_keys->client_write_key; key_dec = traffic_keys->server_write_key; iv_enc = traffic_keys->client_write_iv; iv_dec = traffic_keys->server_write_iv; } else #endif /* MBEDTLS_SSL_CLI_C */ { /* should not happen */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(transform->iv_enc, iv_enc, traffic_keys->iv_len); memcpy(transform->iv_dec, iv_dec, traffic_keys->iv_len); #if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key_enc, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), MBEDTLS_ENCRYPT)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); return ret; } if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key_dec, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), MBEDTLS_DECRYPT)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Setup other fields in SSL transform */ if ((ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) != 0) { transform->taglen = 8; } else { transform->taglen = 16; } transform->ivlen = traffic_keys->iv_len; transform->maclen = 0; transform->fixed_ivlen = transform->ivlen; transform->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; /* We add the true record content type (1 Byte) to the plaintext and * then pad to the configured granularity. The minimum length of the * type-extended and padded plaintext is therefore the padding * granularity. */ transform->minlen = transform->taglen + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY; #if defined(MBEDTLS_USE_PSA_CRYPTO) /* * Setup psa keys and alg */ if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, transform->taglen, &alg, &key_type, &key_bits)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_cipher_to_psa", PSA_TO_MBEDTLS_ERR(status)); return PSA_TO_MBEDTLS_ERR(status); } transform->psa_alg = alg; if (alg != MBEDTLS_SSL_NULL_CIPHER) { psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, key_type); if ((status = psa_import_key(&attributes, key_enc, PSA_BITS_TO_BYTES(key_bits), &transform->psa_key_enc)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET( 1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status)); return PSA_TO_MBEDTLS_ERR(status); } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); if ((status = psa_import_key(&attributes, key_dec, PSA_BITS_TO_BYTES(key_bits), &transform->psa_key_dec)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET( 1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status)); return PSA_TO_MBEDTLS_ERR(status); } } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_get_cipher_key_info( const mbedtls_ssl_ciphersuite_t *ciphersuite_info, size_t *key_len, size_t *iv_len) { psa_key_type_t key_type; psa_algorithm_t alg; size_t taglen; size_t key_bits; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) { taglen = 8; } else { taglen = 16; } status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, taglen, &alg, &key_type, &key_bits); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } *key_len = PSA_BITS_TO_BYTES(key_bits); /* TLS 1.3 only have AEAD ciphers, IV length is unconditionally 12 bytes */ *iv_len = 12; return 0; } #if defined(MBEDTLS_SSL_EARLY_DATA) /* * ssl_tls13_generate_early_key() generates the key necessary for protecting * the early application data and handshake messages as described in section 7 * of RFC 8446. * * NOTE: Only one key is generated, the key for the traffic from the client to * the server. The TLS 1.3 specification does not define a secret and thus * a key for server early traffic. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_generate_early_key(mbedtls_ssl_context *ssl, mbedtls_ssl_key_set *traffic_keys) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_type; psa_algorithm_t hash_alg; size_t hash_len; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; size_t key_len = 0; size_t iv_len = 0; mbedtls_ssl_tls13_early_secrets tls13_early_secrets; mbedtls_ssl_handshake_params *handshake = ssl->handshake; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_early_key")); ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); goto cleanup; } md_type = (mbedtls_md_type_t) ciphersuite_info->mac; hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); hash_len = PSA_HASH_LENGTH(hash_alg); ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); goto cleanup; } ret = mbedtls_ssl_tls13_derive_early_secrets( hash_alg, handshake->tls13_master_secrets.early, transcript, transcript_len, &tls13_early_secrets); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_derive_early_secrets", ret); goto cleanup; } MBEDTLS_SSL_DEBUG_BUF( 4, "Client early traffic secret", tls13_early_secrets.client_early_traffic_secret, hash_len); /* * Export client handshake traffic secret */ if (ssl->f_export_keys != NULL) { ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET, tls13_early_secrets.client_early_traffic_secret, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); } ret = ssl_tls13_make_traffic_key( hash_alg, tls13_early_secrets.client_early_traffic_secret, hash_len, traffic_keys->client_write_key, key_len, traffic_keys->client_write_iv, iv_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_make_traffic_key", ret); goto cleanup; } traffic_keys->key_len = key_len; traffic_keys->iv_len = iv_len; MBEDTLS_SSL_DEBUG_BUF(4, "client early write_key", traffic_keys->client_write_key, traffic_keys->key_len); MBEDTLS_SSL_DEBUG_BUF(4, "client early write_iv", traffic_keys->client_write_iv, traffic_keys->iv_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_early_key")); cleanup: /* Erase early secrets and transcript */ mbedtls_platform_zeroize( &tls13_early_secrets, sizeof(mbedtls_ssl_tls13_early_secrets)); mbedtls_platform_zeroize(transcript, sizeof(transcript)); return ret; } int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_key_set traffic_keys; mbedtls_ssl_transform *transform_earlydata = NULL; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Next evolution in key schedule: Establish early_data secret and * key material. */ ret = ssl_tls13_generate_early_key(ssl, &traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_early_key", ret); goto cleanup; } transform_earlydata = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); if (transform_earlydata == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto cleanup; } ret = mbedtls_ssl_tls13_populate_transform( transform_earlydata, ssl->conf->endpoint, handshake->ciphersuite_info->id, &traffic_keys, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); goto cleanup; } handshake->transform_earlydata = transform_earlydata; cleanup: mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); if (ret != 0) { mbedtls_free(transform_earlydata); } return ret; } #endif /* MBEDTLS_SSL_EARLY_DATA */ int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_algorithm_t hash_alg; mbedtls_ssl_handshake_params *handshake = ssl->handshake; unsigned char *psk = NULL; size_t psk_len = 0; if (handshake->ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("cipher suite info not found")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_export_handshake_psk", ret); return ret; } } #endif ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, NULL, psk, psk_len, handshake->tls13_master_secrets.early); #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) mbedtls_free((void *) psk); #endif if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_key_schedule_stage_early", handshake->tls13_master_secrets.early, PSA_HASH_LENGTH(hash_alg)); return 0; } /** * \brief Compute TLS 1.3 handshake traffic keys. * * ssl_tls13_generate_handshake_keys() generates keys necessary for * protecting the handshake messages, as described in Section 7 of * RFC 8446. * * \param ssl The SSL context to operate on. This must be in * key schedule stage \c Handshake, see * ssl_tls13_key_schedule_stage_handshake(). * \param traffic_keys The address at which to store the handshake traffic * keys. This must be writable but may be uninitialized. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl, mbedtls_ssl_key_set *traffic_keys) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_type; psa_algorithm_t hash_alg; size_t hash_len; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; size_t key_len = 0; size_t iv_len = 0; mbedtls_ssl_handshake_params *handshake = ssl->handshake; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = &handshake->tls13_hs_secrets; MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_handshake_keys")); ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); return ret; } md_type = (mbedtls_md_type_t) ciphersuite_info->mac; hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); hash_len = PSA_HASH_LENGTH(hash_alg); ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); return ret; } ret = mbedtls_ssl_tls13_derive_handshake_secrets( hash_alg, handshake->tls13_master_secrets.handshake, transcript, transcript_len, tls13_hs_secrets); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_handshake_secrets", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(4, "Client handshake traffic secret", tls13_hs_secrets->client_handshake_traffic_secret, hash_len); MBEDTLS_SSL_DEBUG_BUF(4, "Server handshake traffic secret", tls13_hs_secrets->server_handshake_traffic_secret, hash_len); /* * Export client handshake traffic secret */ if (ssl->f_export_keys != NULL) { ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, tls13_hs_secrets->client_handshake_traffic_secret, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, tls13_hs_secrets->server_handshake_traffic_secret, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); } ret = mbedtls_ssl_tls13_make_traffic_keys( hash_alg, tls13_hs_secrets->client_handshake_traffic_secret, tls13_hs_secrets->server_handshake_traffic_secret, hash_len, key_len, iv_len, traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret); goto exit; } MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_key", traffic_keys->client_write_key, traffic_keys->key_len); MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_key", traffic_keys->server_write_key, traffic_keys->key_len); MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_iv", traffic_keys->client_write_iv, traffic_keys->iv_len); MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_iv", traffic_keys->server_write_iv, traffic_keys->iv_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_handshake_keys")); exit: return ret; } /** * \brief Transition into handshake stage of TLS 1.3 key schedule. * * The TLS 1.3 key schedule can be viewed as a simple state machine * with states Initial -> Early -> Handshake -> Application, and * this function represents the Early -> Handshake transition. * * In the handshake stage, ssl_tls13_generate_handshake_keys() * can be used to derive the handshake traffic keys. * * \param ssl The SSL context to operate on. This must be in key schedule * stage \c Early. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type( (mbedtls_md_type_t) handshake->ciphersuite_info->mac); unsigned char *shared_secret = NULL; size_t shared_secret_len = 0; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) /* * Compute ECDHE secret used to compute the handshake secret from which * client_handshake_traffic_secret and server_handshake_traffic_secret * are derived in the handshake secret derivation stage. */ if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { if (mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) || mbedtls_ssl_tls13_named_group_is_ffdh(handshake->offered_group_id)) { #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) psa_algorithm_t alg = mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) ? PSA_ALG_ECDH : PSA_ALG_FFDH; /* Compute ECDH shared secret. */ psa_status_t status = PSA_ERROR_GENERIC_ERROR; psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; status = psa_get_key_attributes(handshake->xxdh_psa_privkey, &key_attributes); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } shared_secret_len = PSA_BITS_TO_BYTES( psa_get_key_bits(&key_attributes)); shared_secret = mbedtls_calloc(1, shared_secret_len); if (shared_secret == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } status = psa_raw_key_agreement( alg, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, shared_secret, shared_secret_len, &shared_secret_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret); goto cleanup; } status = psa_destroy_key(handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); goto cleanup; } handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ } else { MBEDTLS_SSL_DEBUG_MSG(1, ("Group not supported.")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ /* * Compute the Handshake Secret */ ret = mbedtls_ssl_tls13_evolve_secret( hash_alg, handshake->tls13_master_secrets.early, shared_secret, shared_secret_len, handshake->tls13_master_secrets.handshake); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); goto cleanup; } MBEDTLS_SSL_DEBUG_BUF(4, "Handshake secret", handshake->tls13_master_secrets.handshake, PSA_HASH_LENGTH(hash_alg)); cleanup: if (shared_secret != NULL) { mbedtls_zeroize_and_free(shared_secret, shared_secret_len); } return ret; } /** * \brief Compute TLS 1.3 application traffic keys. * * ssl_tls13_generate_application_keys() generates application traffic * keys, since any record following a 1-RTT Finished message MUST be * encrypted under the application traffic key. * * \param ssl The SSL context to operate on. This must be in * key schedule stage \c Application, see * ssl_tls13_key_schedule_stage_application(). * \param traffic_keys The address at which to store the application traffic * keys. This must be writable but may be uninitialized. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_generate_application_keys( mbedtls_ssl_context *ssl, mbedtls_ssl_key_set *traffic_keys) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Address at which to store the application secrets */ mbedtls_ssl_tls13_application_secrets * const app_secrets = &ssl->session_negotiate->app_secrets; /* Holding the transcript up to and including the ServerFinished */ unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; /* Variables relating to the hash for the chosen ciphersuite. */ mbedtls_md_type_t md_type; psa_algorithm_t hash_alg; size_t hash_len; /* Variables relating to the cipher for the chosen ciphersuite. */ size_t key_len = 0, iv_len = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive application traffic keys")); /* Extract basic information about hash and ciphersuite */ ret = ssl_tls13_get_cipher_key_info(handshake->ciphersuite_info, &key_len, &iv_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); goto cleanup; } md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac; hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac); hash_len = PSA_HASH_LENGTH(hash_alg); /* Compute current handshake transcript. It's the caller's responsibility * to call this at the right time, that is, after the ServerFinished. */ ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { goto cleanup; } /* Compute application secrets from master secret and transcript hash. */ ret = mbedtls_ssl_tls13_derive_application_secrets( hash_alg, handshake->tls13_master_secrets.app, transcript, transcript_len, app_secrets); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_derive_application_secrets", ret); goto cleanup; } /* Derive first epoch of IV + Key for application traffic. */ ret = mbedtls_ssl_tls13_make_traffic_keys( hash_alg, app_secrets->client_application_traffic_secret_N, app_secrets->server_application_traffic_secret_N, hash_len, key_len, iv_len, traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret); goto cleanup; } MBEDTLS_SSL_DEBUG_BUF(4, "Client application traffic secret", app_secrets->client_application_traffic_secret_N, hash_len); MBEDTLS_SSL_DEBUG_BUF(4, "Server application traffic secret", app_secrets->server_application_traffic_secret_N, hash_len); /* * Export client/server application traffic secret 0 */ if (ssl->f_export_keys != NULL) { ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, app_secrets->client_application_traffic_secret_N, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by a new constant for TLS 1.3! */); ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, app_secrets->server_application_traffic_secret_N, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by a new constant for TLS 1.3! */); } MBEDTLS_SSL_DEBUG_BUF(4, "client application_write_key:", traffic_keys->client_write_key, key_len); MBEDTLS_SSL_DEBUG_BUF(4, "server application write key", traffic_keys->server_write_key, key_len); MBEDTLS_SSL_DEBUG_BUF(4, "client application write IV", traffic_keys->client_write_iv, iv_len); MBEDTLS_SSL_DEBUG_BUF(4, "server application write IV", traffic_keys->server_write_iv, iv_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive application traffic keys")); cleanup: /* randbytes is not used again */ mbedtls_platform_zeroize(ssl->handshake->randbytes, sizeof(ssl->handshake->randbytes)); mbedtls_platform_zeroize(transcript, sizeof(transcript)); return ret; } int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_key_set traffic_keys; mbedtls_ssl_transform *transform_handshake = NULL; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Compute handshake secret */ ret = ssl_tls13_key_schedule_stage_handshake(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_master_secret", ret); goto cleanup; } /* Next evolution in key schedule: Establish handshake secret and * key material. */ ret = ssl_tls13_generate_handshake_keys(ssl, &traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_handshake_keys", ret); goto cleanup; } transform_handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); if (transform_handshake == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto cleanup; } ret = mbedtls_ssl_tls13_populate_transform( transform_handshake, ssl->conf->endpoint, handshake->ciphersuite_info->id, &traffic_keys, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); goto cleanup; } handshake->transform_handshake = transform_handshake; cleanup: mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); if (ret != 0) { mbedtls_free(transform_handshake); } return ret; } int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_type; mbedtls_ssl_handshake_params *handshake = ssl->handshake; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; MBEDTLS_SSL_DEBUG_MSG( 2, ("=> mbedtls_ssl_tls13_compute_resumption_master_secret")); md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac; ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_derive_resumption_master_secret( mbedtls_md_psa_alg_from_type(md_type), handshake->tls13_master_secrets.app, transcript, transcript_len, &ssl->session_negotiate->app_secrets); if (ret != 0) { return ret; } /* Erase master secrets */ mbedtls_platform_zeroize(&handshake->tls13_master_secrets, sizeof(handshake->tls13_master_secrets)); MBEDTLS_SSL_DEBUG_BUF( 4, "Resumption master secret", ssl->session_negotiate->app_secrets.resumption_master_secret, PSA_HASH_LENGTH(mbedtls_md_psa_alg_from_type(md_type))); MBEDTLS_SSL_DEBUG_MSG( 2, ("<= mbedtls_ssl_tls13_compute_resumption_master_secret")); return 0; } int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_key_set traffic_keys; mbedtls_ssl_transform *transform_application = NULL; ret = ssl_tls13_key_schedule_stage_application(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_key_schedule_stage_application", ret); goto cleanup; } ret = ssl_tls13_generate_application_keys(ssl, &traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_application_keys", ret); goto cleanup; } transform_application = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); if (transform_application == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto cleanup; } ret = mbedtls_ssl_tls13_populate_transform( transform_application, ssl->conf->endpoint, ssl->handshake->ciphersuite_info->id, &traffic_keys, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); goto cleanup; } ssl->transform_application = transform_application; cleanup: mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); if (ret != 0) { mbedtls_free(transform_application); } return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl, unsigned char **psk, size_t *psk_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; *psk_len = 0; *psk = NULL; if (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } status = psa_get_key_attributes(ssl->handshake->psk_opaque, &key_attributes); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } *psk_len = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attributes)); *psk = mbedtls_calloc(1, *psk_len); if (*psk == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } status = psa_export_key(ssl->handshake->psk_opaque, (uint8_t *) *psk, *psk_len, psk_len); if (status != PSA_SUCCESS) { mbedtls_free((void *) *psk); *psk = NULL; return PSA_TO_MBEDTLS_ERR(status); } return 0; #else *psk = ssl->handshake->psk; *psk_len = ssl->handshake->psk_len; if (*psk == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return 0; #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ webfakes/src/mbedtls/library/bignum_mod_raw.c0000644000176200001440000002217014740737024021075 0ustar liggesusers/* * Low-level modular bignum functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT) #include #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/platform.h" #include "bignum_core.h" #include "bignum_mod_raw.h" #include "bignum_mod.h" #include "constant_time_internal.h" #include "bignum_mod_raw_invasive.h" void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N, unsigned char assign) { mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign)); } void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X, mbedtls_mpi_uint *Y, const mbedtls_mpi_mod_modulus *N, unsigned char swap) { mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap)); } int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N, const unsigned char *input, size_t input_length, mbedtls_mpi_mod_ext_rep ext_rep) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (ext_rep) { case MBEDTLS_MPI_MOD_EXT_REP_LE: ret = mbedtls_mpi_core_read_le(X, N->limbs, input, input_length); break; case MBEDTLS_MPI_MOD_EXT_REP_BE: ret = mbedtls_mpi_core_read_be(X, N->limbs, input, input_length); break; default: return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (ret != 0) { goto cleanup; } if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } cleanup: return ret; } int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N, unsigned char *output, size_t output_length, mbedtls_mpi_mod_ext_rep ext_rep) { switch (ext_rep) { case MBEDTLS_MPI_MOD_EXT_REP_LE: return mbedtls_mpi_core_write_le(A, N->limbs, output, output_length); case MBEDTLS_MPI_MOD_EXT_REP_BE: return mbedtls_mpi_core_write_be(A, N->limbs, output, output_length); default: return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } } void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs); (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); } MBEDTLS_STATIC_TESTABLE void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); } void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *T) { /* Standard (A * B) multiplication stored into pre-allocated T * buffer of fixed limb size of (2N + 1). * * The space may not not fully filled by when * MBEDTLS_MPI_MOD_REP_OPT_RED is used. */ const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2; switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs, N->rep.mont.mm, T); break; case MBEDTLS_MPI_MOD_REP_OPT_RED: mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs); /* Optimised Reduction */ (*N->rep.ored.modp)(T, T_limbs); /* Convert back to canonical representation */ mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N); memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint)); break; default: break; } } size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs) { /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent, * which will be the same size as the modulus and input (AN_limbs), * and additional space to pass to mbedtls_mpi_core_exp_mod(). */ return AN_limbs + mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs); } void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T) { /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and * |G| = N - 1, so we want * g^(|G|-1) = g^(N - 2) */ /* Use the first AN_limbs of T to hold N - 2 */ mbedtls_mpi_uint *Nminus2 = T; (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs); /* Rest of T is given to exp_mod for its working space */ mbedtls_mpi_core_exp_mod(X, A, N, AN_limbs, Nminus2, AN_limbs, RR, T + AN_limbs); } void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_uint carry, borrow; carry = mbedtls_mpi_core_add(X, A, B, N->limbs); borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow)); } int mbedtls_mpi_mod_raw_canonical_to_modulus_rep( mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: return mbedtls_mpi_mod_raw_to_mont_rep(X, N); case MBEDTLS_MPI_MOD_REP_OPT_RED: return 0; default: return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } } int mbedtls_mpi_mod_raw_modulus_to_canonical_rep( mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: return mbedtls_mpi_mod_raw_from_mont_rep(X, N); case MBEDTLS_MPI_MOD_REP_OPT_RED: return 0; default: return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } } int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X, mbedtls_mpi_uint min, const mbedtls_mpi_mod_modulus *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng); if (ret != 0) { return ret; } return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N); } int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_uint *T; const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, N->rep.mont.rr, T); mbedtls_zeroize_and_free(T, t_limbs * ciL); return 0; } int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); mbedtls_mpi_uint *T; if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T); mbedtls_zeroize_and_free(T, t_limbs * ciL); return 0; } void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_core_sub(X, N->p, A, N->limbs); /* If A=0 initially, then X=N now. Detect this by * subtracting N and catching the carry. */ mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow); } #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */ webfakes/src/mbedtls/library/psa_crypto_core.h0000644000176200001440000013010314740737024021300 0ustar liggesusers/* * PSA crypto core internal interfaces */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CORE_H #define PSA_CRYPTO_CORE_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" #include "psa/crypto.h" #include "psa/crypto_se_driver.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /** * Tell if PSA is ready for this hash. * * \note For now, only checks the state of the driver subsystem, * not the algorithm. Might do more in the future. * * \param hash_alg The hash algorithm (ignored for now). * * \return 1 if the driver subsytem is ready, 0 otherwise. */ int psa_can_do_hash(psa_algorithm_t hash_alg); /** * Tell if PSA is ready for this cipher. * * \note For now, only checks the state of the driver subsystem, * not the algorithm. Might do more in the future. * * \param cipher_alg The cipher algorithm (ignored for now). * * \return 1 if the driver subsytem is ready, 0 otherwise. */ int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg); typedef enum { PSA_SLOT_EMPTY = 0, PSA_SLOT_FILLING, PSA_SLOT_FULL, PSA_SLOT_PENDING_DELETION, } psa_key_slot_state_t; /** The data structure representing a key slot, containing key material * and metadata for one key. */ typedef struct { /* This field is accessed in a lot of places. Putting it first * reduces the code size. */ psa_key_attributes_t attr; /* * The current state of the key slot, as described in * docs/architecture/psa-thread-safety/psa-thread-safety.md. * * Library functions can modify the state of a key slot by calling * psa_key_slot_state_transition. * * The state variable is used to help determine whether library functions * which operate on the slot succeed. For example, psa_finish_key_creation, * which transfers the state of a slot from PSA_SLOT_FILLING to * PSA_SLOT_FULL, must fail with error code PSA_ERROR_CORRUPTION_DETECTED * if the state of the slot is not PSA_SLOT_FILLING. * * Library functions which traverse the array of key slots only consider * slots that are in a suitable state for the function. * For example, psa_get_and_lock_key_slot_in_memory, which finds a slot * containing a given key ID, will only check slots whose state variable is * PSA_SLOT_FULL. */ psa_key_slot_state_t state; #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) /* The index of the slice containing this slot. * This field must be filled if the slot contains a key * (including keys being created or destroyed), and can be either * filled or 0 when the slot is free. * * In most cases, the slice index can be deduced from the key identifer. * We keep it in a separate field for robustness (it reduces the chance * that a coding mistake in the key store will result in accessing the * wrong slice), and also so that it's available even on code paths * during creation or destruction where the key identifier might not be * filled in. * */ uint8_t slice_index; #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ union { struct { /* The index of the next slot in the free list for this * slice, relative * to the next array element. * * That is, 0 means the next slot, 1 means the next slot * but one, etc. -1 would mean the slot itself. -2 means * the previous slot, etc. * * If this is beyond the array length, the free list ends with the * current element. * * The reason for this strange encoding is that 0 means the next * element. This way, when we allocate a slice and initialize it * to all-zero, the slice is ready for use, with a free list that * consists of all the slots in order. */ int32_t next_free_relative_to_next; } free; struct { /* * Number of functions registered as reading the material in the key slot. * * Library functions must not write directly to registered_readers * * A function must call psa_register_read(slot) before reading * the current contents of the slot for an operation. * They then must call psa_unregister_read(slot) once they have * finished reading the current contents of the slot. If the key * slot mutex is not held (when mutexes are enabled), this call * must be done via a call to * psa_unregister_read_under_mutex(slot). * A function must call psa_key_slot_has_readers(slot) to check if * the slot is in use for reading. * * This counter is used to prevent resetting the key slot while * the library may access it. For example, such control is needed * in the following scenarios: * . In case of key slot starvation, all key slots contain the * description of a key, and the library asks for the * description of a persistent key not present in the * key slots, the key slots currently accessed by the * library cannot be reclaimed to free a key slot to load * the persistent key. * . In case of a multi-threaded application where one thread * asks to close or purge or destroy a key while it is in use * by the library through another thread. */ size_t registered_readers; } occupied; } var; /* Dynamically allocated key data buffer. * Format as specified in psa_export_key(). */ struct key_data { uint8_t *data; size_t bytes; } key; } psa_key_slot_t; #if defined(MBEDTLS_THREADING_C) /** Perform a mutex operation and return immediately upon failure. * * Returns PSA_ERROR_SERVICE_FAILURE if the operation fails * and status was PSA_SUCCESS. * * Assumptions: * psa_status_t status exists. * f is a mutex operation which returns 0 upon success. */ #define PSA_THREADING_CHK_RET(f) \ do \ { \ if ((f) != 0) { \ if (status == PSA_SUCCESS) { \ return PSA_ERROR_SERVICE_FAILURE; \ } \ return status; \ } \ } while (0); /** Perform a mutex operation and goto exit on failure. * * Sets status to PSA_ERROR_SERVICE_FAILURE if status was PSA_SUCCESS. * * Assumptions: * psa_status_t status exists. * Label exit: exists. * f is a mutex operation which returns 0 upon success. */ #define PSA_THREADING_CHK_GOTO_EXIT(f) \ do \ { \ if ((f) != 0) { \ if (status == PSA_SUCCESS) { \ status = PSA_ERROR_SERVICE_FAILURE; \ } \ goto exit; \ } \ } while (0); #endif /** Test whether a key slot has any registered readers. * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[in] slot The key slot to test. * * \return 1 if the slot has any registered readers, 0 otherwise. */ static inline int psa_key_slot_has_readers(const psa_key_slot_t *slot) { return slot->var.occupied.registered_readers > 0; } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /** Get the SE slot number of a key from the key slot storing its description. * * \param[in] slot The key slot to query. This must be a key slot storing * the description of a key of a dynamically registered * secure element, otherwise the behaviour is undefined. */ static inline psa_key_slot_number_t psa_key_slot_get_slot_number( const psa_key_slot_t *slot) { return *((psa_key_slot_number_t *) (slot->key.data)); } #endif /** Completely wipe a slot in memory, including its policy. * * Persistent storage is not affected. * Sets the slot's state to PSA_SLOT_EMPTY. * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[in,out] slot The key slot to wipe. * * \retval #PSA_SUCCESS * The slot has been successfully wiped. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was PSA_SLOT_FULL or PSA_SLOT_PENDING_DELETION, and * the amount of registered readers was not equal to 1. Or, * the slot's state was PSA_SLOT_EMPTY. Or, * the slot's state was PSA_SLOT_FILLING, and the amount * of registered readers was not equal to 0. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot); /** Try to allocate a buffer to an empty key slot. * * \param[in,out] slot Key slot to attach buffer to. * \param[in] buffer_length Requested size of the buffer. * * \retval #PSA_SUCCESS * The buffer has been successfully allocated. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * Not enough memory was available for allocation. * \retval #PSA_ERROR_ALREADY_EXISTS * Trying to allocate a buffer to a non-empty key slot. */ psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot, size_t buffer_length); /** Wipe key data from a slot. Preserves metadata such as the policy. */ psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot); /** Copy key data (in export format) into an empty key slot. * * This function assumes that the slot does not contain * any key material yet. On failure, the slot content is unchanged. * * \param[in,out] slot Key slot to copy the key into. * \param[in] data Buffer containing the key material. * \param data_length Size of the key buffer. * * \retval #PSA_SUCCESS * The key has been copied successfully. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * Not enough memory was available for allocation of the * copy buffer. * \retval #PSA_ERROR_ALREADY_EXISTS * There was other key material already present in the slot. */ psa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot, const uint8_t *data, size_t data_length); /** Convert an Mbed TLS error code to a PSA error code * * \note This function is provided solely for the convenience of * Mbed TLS and may be removed at any time without notice. * * \param ret An Mbed TLS-thrown error code * * \return The corresponding PSA error code */ psa_status_t mbedtls_to_psa_error(int ret); /** Import a key in binary format. * * \note The signature of this function is that of a PSA driver * import_key entry point. This function behaves as an import_key * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes for the key to import. * \param[in] data The buffer containing the key data in import * format. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] key_buffer The buffer to contain the key data in output * format upon successful return. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p * key_buffer in bytes. * \param[out] bits The key size in number of bits. * * \retval #PSA_SUCCESS The key was imported successfully. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key data is not correctly formatted. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t psa_import_key_into_slot( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits); /** Export a key in binary format * * \note The signature of this function is that of a PSA driver export_key * entry point. This function behaves as an export_key entry point as * defined in the PSA driver interface specification. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data * * \retval #PSA_SUCCESS The key was exported successfully. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t psa_export_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** Export a public key or the public part of a key pair in binary format. * * \note The signature of this function is that of a PSA driver * export_public_key entry point. This function behaves as an * export_public_key entry point as defined in the PSA driver interface * specification. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data * * \retval #PSA_SUCCESS The public key was exported successfully. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t psa_export_public_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** Whether a key custom production parameters structure is the default. * * Calls to a key generation driver with non-default custom production parameters * require a driver supporting custom production parameters. * * \param[in] custom The key custom production parameters to check. * \param custom_data_length Size of the associated variable-length data * in bytes. */ int psa_custom_key_parameters_are_default( const psa_custom_key_parameters_t *custom, size_t custom_data_length); /** * \brief Generate a key. * * \note The signature of the function is that of a PSA driver generate_key * entry point. * * \param[in] attributes The attributes for the key to generate. * \param[in] custom Custom parameters for the key generation. * \param[in] custom_data Variable-length data associated with \c custom. * \param custom_data_length Length of `custom_data` in bytes. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in * \p key_buffer. * * \retval #PSA_SUCCESS * The key was generated successfully. * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED * Key size in bits or type not supported. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. */ psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes, const psa_custom_key_parameters_t *custom, const uint8_t *custom_data, size_t custom_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); /** Sign a message with a private key. For hash-and-sign algorithms, * this includes the hashing step. * * \note The signature of this function is that of a PSA driver * sign_message entry point. This function behaves as a sign_message * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \note This function will call the driver for psa_sign_hash * and go through driver dispatch again. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] input The input message to sign. * \param[in] input_length Size of the \p input buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of the key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t psa_sign_message_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** Verify the signature of a message with a public key, using * a hash-and-sign verification algorithm. * * \note The signature of this function is that of a PSA driver * verify_message entry point. This function behaves as a verify_message * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \note This function will call the driver for psa_verify_hash * and go through driver dispatch again. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] input The message whose signature is to be verified. * \param[in] input_length Size of the \p input buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t psa_verify_message_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length); /** Sign an already-calculated hash with a private key. * * \note The signature of this function is that of a PSA driver * sign_hash entry point. This function behaves as a sign_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] hash The hash or message to sign. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of the key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t psa_sign_hash_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Verify the signature a hash or short message using a public key. * * \note The signature of this function is that of a PSA driver * verify_hash entry point. This function behaves as a verify_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] hash The hash or message whose signature is to be * verified. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t psa_verify_hash_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Validate the key bit size for unstructured keys. * * \note Check that the bit size is acceptable for a given key type for * unstructured keys. * * \param[in] type The key type * \param[in] bits The number of bits of the key * * \retval #PSA_SUCCESS * The key type and size are valid. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size in bits of the key is not valid. * \retval #PSA_ERROR_NOT_SUPPORTED * The type and/or the size in bits of the key or the combination of * the two is not supported. */ psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type, size_t bits); /** Perform a key agreement and return the raw shared secret, using built-in raw key agreement functions. * * \note The signature of this function is that of a PSA driver * key_agreement entry point. This function behaves as a key_agreement * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the private key * context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in * bytes. * \param[in] alg A key agreement algorithm that is * compatible with the type of the key. * \param[in] peer_key The buffer containing the key context * of the peer's public key. * \param[in] peer_key_length Size of the \p peer_key buffer in * bytes. * \param[out] shared_secret The buffer to which the shared secret * is to be written. * \param[in] shared_secret_size Size of the \p shared_secret buffer in * bytes. * \param[out] shared_secret_length On success, the number of bytes that make * up the returned shared secret. * \retval #PSA_SUCCESS * Success. Shared secret successfully calculated. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p alg is not a key agreement algorithm, or * \p private_key is not compatible with \p alg, * or \p peer_key is not valid for \p alg or not compatible with * \p private_key. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p shared_secret_size is too small * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not a supported key agreement algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE \emptydescription */ psa_status_t psa_key_agreement_raw_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length); /** * \brief Set the maximum number of ops allowed to be executed by an * interruptible function in a single call. * * \note The signature of this function is that of a PSA driver * interruptible_set_max_ops entry point. This function behaves as an * interruptible_set_max_ops entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in] max_ops The maximum number of ops to be executed in a * single call, this can be a number from 0 to * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0 * is obviously the least amount of work done per * call. */ void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops); /** * \brief Get the maximum number of ops allowed to be executed by an * interruptible function in a single call. * * \note The signature of this function is that of a PSA driver * interruptible_get_max_ops entry point. This function behaves as an * interruptible_get_max_ops entry point as defined in the PSA driver * interface specification for transparent drivers. * * \return Maximum number of ops allowed to be executed * by an interruptible function in a single call. */ uint32_t mbedtls_psa_interruptible_get_max_ops(void); /** * \brief Get the number of ops that a hash signing operation has taken for the * previous call. If no call or work has taken place, this will return * zero. * * \note The signature of this function is that of a PSA driver * sign_hash_get_num_ops entry point. This function behaves as an * sign_hash_get_num_ops entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \return Number of ops that were completed * in the last call to \c * mbedtls_psa_sign_hash_complete(). */ uint32_t mbedtls_psa_sign_hash_get_num_ops( const mbedtls_psa_sign_hash_interruptible_operation_t *operation); /** * \brief Get the number of ops that a hash verification operation has taken for * the previous call. If no call or work has taken place, this will * return zero. * * \note The signature of this function is that of a PSA driver * verify_hash_get_num_ops entry point. This function behaves as an * verify_hash_get_num_ops entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param operation The \c * mbedtls_psa_verify_hash_interruptible_operation_t * to use. This must be initialized first. * * \return Number of ops that were completed * in the last call to \c * mbedtls_psa_verify_hash_complete(). */ uint32_t mbedtls_psa_verify_hash_get_num_ops( const mbedtls_psa_verify_hash_interruptible_operation_t *operation); /** * \brief Start signing a hash or short message with a private key, in an * interruptible manner. * * \note The signature of this function is that of a PSA driver * sign_hash_start entry point. This function behaves as a * sign_hash_start entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] hash The hash or message to sign. * \param hash_length Size of the \p hash buffer in bytes. * * \retval #PSA_SUCCESS * The operation started successfully - call \c psa_sign_hash_complete() * with the same context to complete the operation * \retval #PSA_ERROR_INVALID_ARGUMENT * An unsupported, incorrectly formatted or incorrect type of key was * used. * \retval #PSA_ERROR_NOT_SUPPORTED Either no internal interruptible operations * are currently supported, or the key type is currently unsupported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * There was insufficient memory to load the key representation. */ psa_status_t mbedtls_psa_sign_hash_start( mbedtls_psa_sign_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length); /** * \brief Continue and eventually complete the action of signing a hash or * short message with a private key, in an interruptible manner. * * \note The signature of this function is that of a PSA driver * sign_hash_complete entry point. This function behaves as a * sign_hash_complete entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \param[out] signature Buffer where the signature is to be written. * \param signature_size Size of the \p signature buffer in bytes. This * must be appropriate for the selected * algorithm and key. * \param[out] signature_length On success, the number of bytes that make up * the returned signature value. * * \retval #PSA_SUCCESS * Operation completed successfully * * \retval #PSA_OPERATION_INCOMPLETE * Operation was interrupted due to the setting of \c * psa_interruptible_set_max_ops(), there is still work to be done, * please call this function again with the same operation object. * * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t mbedtls_psa_sign_hash_complete( mbedtls_psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Abort a sign hash operation. * * \note The signature of this function is that of a PSA driver sign_hash_abort * entry point. This function behaves as a sign_hash_abort entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param[in] operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to abort. * * \retval #PSA_SUCCESS * The operation was aborted successfully. */ psa_status_t mbedtls_psa_sign_hash_abort( mbedtls_psa_sign_hash_interruptible_operation_t *operation); /** * \brief Start reading and verifying a hash or short message, in an * interruptible manner. * * \note The signature of this function is that of a PSA driver * verify_hash_start entry point. This function behaves as a * verify_hash_start entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_verify_hash_interruptible_operation_t * to use. This must be initialized first. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] hash The hash whose signature is to be verified. * \param hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The operation started successfully - call \c psa_sign_hash_complete() * with the same context to complete the operation * \retval #PSA_ERROR_INVALID_ARGUMENT * An unsupported or incorrect type of key was used. * \retval #PSA_ERROR_NOT_SUPPORTED * Either no internal interruptible operations are currently supported, * or the key type is currently unsupported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * There was insufficient memory either to load the key representation, * or to prepare the operation. */ psa_status_t mbedtls_psa_verify_hash_start( mbedtls_psa_verify_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Continue and eventually complete the action of signing a hash or * short message with a private key, in an interruptible manner. * * \note The signature of this function is that of a PSA driver * sign_hash_complete entry point. This function behaves as a * sign_hash_complete entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \retval #PSA_SUCCESS * Operation completed successfully, and the passed signature is valid. * * \retval #PSA_OPERATION_INCOMPLETE * Operation was interrupted due to the setting of \c * psa_interruptible_set_max_ops(), there is still work to be done, * please call this function again with the same operation object. * * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_verify_hash_complete( mbedtls_psa_verify_hash_interruptible_operation_t *operation); /** * \brief Abort a verify signed hash operation. * * \note The signature of this function is that of a PSA driver * verify_hash_abort entry point. This function behaves as a * verify_hash_abort entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_verify_hash_interruptible_operation_t * to abort. * * \retval #PSA_SUCCESS * The operation was aborted successfully. */ psa_status_t mbedtls_psa_verify_hash_abort( mbedtls_psa_verify_hash_interruptible_operation_t *operation); typedef struct psa_crypto_local_input_s { uint8_t *buffer; size_t length; } psa_crypto_local_input_t; #define PSA_CRYPTO_LOCAL_INPUT_INIT ((psa_crypto_local_input_t) { NULL, 0 }) /** Allocate a local copy of an input buffer and copy the contents into it. * * \param[in] input Pointer to input buffer. * \param[in] input_len Length of the input buffer. * \param[out] local_input Pointer to a psa_crypto_local_input_t struct * containing a local input copy. * \return #PSA_SUCCESS, if the buffer was successfully * copied. * \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of * the buffer cannot be allocated. */ psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len, psa_crypto_local_input_t *local_input); /** Free a local copy of an input buffer. * * \param[in] local_input Pointer to a psa_crypto_local_input_t struct * populated by a previous call to * psa_crypto_local_input_alloc(). */ void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input); typedef struct psa_crypto_local_output_s { uint8_t *original; uint8_t *buffer; size_t length; } psa_crypto_local_output_t; #define PSA_CRYPTO_LOCAL_OUTPUT_INIT ((psa_crypto_local_output_t) { NULL, NULL, 0 }) /** Allocate a local copy of an output buffer. * * \note This does not copy any data from the original * output buffer but only allocates a buffer * whose contents will be copied back to the * original in a future call to * psa_crypto_local_output_free(). * * \param[in] output Pointer to output buffer. * \param[in] output_len Length of the output buffer. * \param[out] local_output Pointer to a psa_crypto_local_output_t struct to * populate with the local output copy. * \return #PSA_SUCCESS, if the buffer was successfully * copied. * \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of * the buffer cannot be allocated. */ psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, psa_crypto_local_output_t *local_output); /** Copy from a local copy of an output buffer back to the original, then * free the local copy. * * \param[in] local_output Pointer to a psa_crypto_local_output_t struct * populated by a previous call to * psa_crypto_local_output_alloc(). * \return #PSA_SUCCESS, if the local output was * successfully copied back to the original. * \return #PSA_ERROR_CORRUPTION_DETECTED, if the output * could not be copied back to the original. */ psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output); #endif /* PSA_CRYPTO_CORE_H */ webfakes/src/mbedtls/library/bignum_core.h0000644000176200001440000011306714740737024020410 0ustar liggesusers/** * Core bignum functions * * This interface should only be used by the legacy bignum module (bignum.h) * and the modular bignum modules (bignum_mod.c, bignum_mod_raw.c). All other * modules should use the high-level modular bignum interface (bignum_mod.h) * or the legacy bignum interface (bignum.h). * * This module is about processing non-negative integers with a fixed upper * bound that's of the form 2^n-1 where n is a multiple of #biL. * These can be thought of integers written in base 2^#biL with a fixed * number of digits. Digits in this base are called *limbs*. * Many operations treat these numbers as the principal representation of * a number modulo 2^n or a smaller bound. * * The functions in this module obey the following conventions unless * explicitly indicated otherwise: * * - **Overflow**: some functions indicate overflow from the range * [0, 2^n-1] by returning carry parameters, while others operate * modulo and so cannot overflow. This should be clear from the function * documentation. * - **Bignum parameters**: Bignums are passed as pointers to an array of * limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified: * - Bignum parameters called \p A, \p B, ... are inputs, and are * not modified by the function. * - For operations modulo some number, the modulus is called \p N * and is input-only. * - Bignum parameters called \p X, \p Y are outputs or input-output. * The initial content of output-only parameters is ignored. * - Some functions use different names that reflect traditional * naming of operands of certain operations (e.g. * divisor/dividend/quotient/remainder). * - \p T is a temporary storage area. The initial content of such * parameter is ignored and the final content is unspecified. * - **Bignum sizes**: bignum sizes are always expressed in limbs. * Most functions work on bignums of a given size and take a single * \p limbs parameter that applies to all parameters that are limb arrays. * All bignum sizes must be at least 1 and must be significantly less than * #SIZE_MAX. The behavior if a size is 0 is undefined. The behavior if the * total size of all parameters overflows #SIZE_MAX is undefined. * - **Parameter ordering**: for bignum parameters, outputs come before inputs. * Temporaries come last. * - **Aliasing**: in general, output bignums may be aliased to one or more * inputs. As an exception, parameters that are documented as a modulus value * may not be aliased to an output. Outputs may not be aliased to one another. * Temporaries may not be aliased to any other parameter. * - **Overlap**: apart from aliasing of limb array pointers (where two * arguments are equal pointers), overlap is not supported and may result * in undefined behavior. * - **Error handling**: This is a low-level module. Functions generally do not * try to protect against invalid arguments such as nonsensical sizes or * null pointers. Note that some functions that operate on bignums of * different sizes have constraints about their size, and violating those * constraints may lead to buffer overflows. * - **Modular representatives**: functions that operate modulo \p N expect * all modular inputs to be in the range [0, \p N - 1] and guarantee outputs * in the range [0, \p N - 1]. If an input is out of range, outputs are * fully unspecified, though bignum values out of range should not cause * buffer overflows (beware that this is not extensively tested). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_CORE_H #define MBEDTLS_BIGNUM_CORE_H #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif #include "constant_time_internal.h" #define ciL (sizeof(mbedtls_mpi_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 * Divide first in order to avoid potential overflows */ #define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0)) #define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0)) /* Get a specific byte, without range checks. */ #define GET_BYTE(X, i) \ (((X)[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff) /* Constants to identify whether a value is public or secret. If a parameter is marked as secret by * this constant, the function must be constant time with respect to the parameter. * * This is only needed for functions with the _optionally_safe postfix. All other functions have * fixed behavior that can't be changed at runtime and are constant time with respect to their * parameters as prescribed by their documentation or by conventions in their module's documentation. * * Parameters should be named X_public where X is the name of the * corresponding input parameter. * * Implementation should always check using * if (X_public == MBEDTLS_MPI_IS_PUBLIC) { * // unsafe path * } else { * // safe path * } * not the other way round, in order to prevent misuse. (This is, if a value * other than the two below is passed, default to the safe path.) */ #define MBEDTLS_MPI_IS_PUBLIC 0x2a2a2a2a #define MBEDTLS_MPI_IS_SECRET 0 /** Count leading zero bits in a given integer. * * \warning The result is undefined if \p a == 0 * * \param a Integer to count leading zero bits. * * \return The number of leading zero bits in \p a, if \p a != 0. * If \p a == 0, the result is undefined. */ size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a); /** Return the minimum number of bits required to represent the value held * in the MPI. * * \note This function returns 0 if all the limbs of \p A are 0. * * \param[in] A The address of the MPI. * \param A_limbs The number of limbs of \p A. * * \return The number of bits in \p A. */ size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs); /** Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint * into the storage form used by mbedtls_mpi. * * \param[in,out] A The address of the MPI. * \param A_limbs The number of limbs of \p A. */ void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A, size_t A_limbs); /** \brief Compare a machine integer with an MPI. * * This function operates in constant time with respect * to the values of \p min and \p A. * * \param min A machine integer. * \param[in] A An MPI. * \param A_limbs The number of limbs of \p A. * This must be at least 1. * * \return MBEDTLS_CT_TRUE if \p min is less than or equal to \p A, otherwise MBEDTLS_CT_FALSE. */ mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min, const mbedtls_mpi_uint *A, size_t A_limbs); /** * \brief Check if one unsigned MPI is less than another in constant * time. * * \param A The left-hand MPI. This must point to an array of limbs * with the same allocated length as \p B. * \param B The right-hand MPI. This must point to an array of limbs * with the same allocated length as \p A. * \param limbs The number of limbs in \p A and \p B. * This must not be 0. * * \return MBEDTLS_CT_TRUE if \p A is less than \p B. * MBEDTLS_CT_FALSE if \p A is greater than or equal to \p B. */ mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs); /** * \brief Perform a safe conditional copy of an MPI which doesn't reveal * whether assignment was done or not. * * \param[out] X The address of the destination MPI. * This must be initialized. Must have enough limbs to * store the full value of \p A. * \param[in] A The address of the source MPI. This must be initialized. * \param limbs The number of limbs of \p A. * \param assign The condition deciding whether to perform the * assignment or not. Callers will need to use * the constant time interface (e.g. `mbedtls_ct_bool()`) * to construct this argument. * * \note This function avoids leaking any information about whether * the assignment was done or not. */ void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t limbs, mbedtls_ct_condition_t assign); /** * \brief Perform a safe conditional swap of two MPIs which doesn't reveal * whether the swap was done or not. * * \param[in,out] X The address of the first MPI. * This must be initialized. * \param[in,out] Y The address of the second MPI. * This must be initialized. * \param limbs The number of limbs of \p X and \p Y. * \param swap The condition deciding whether to perform * the swap or not. * * \note This function avoids leaking any information about whether * the swap was done or not. */ void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X, mbedtls_mpi_uint *Y, size_t limbs, mbedtls_ct_condition_t swap); /** Import X from unsigned binary data, little-endian. * * The MPI needs to have enough limbs to store the full value (including any * most significant zero bytes in the input). * * \param[out] X The address of the MPI. * \param X_limbs The number of limbs of \p X. * \param[in] input The input buffer to import from. * \param input_length The length bytes of \p input. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't * large enough to hold the value in \p input. */ int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X, size_t X_limbs, const unsigned char *input, size_t input_length); /** Import X from unsigned binary data, big-endian. * * The MPI needs to have enough limbs to store the full value (including any * most significant zero bytes in the input). * * \param[out] X The address of the MPI. * May only be #NULL if \p X_limbs is 0 and \p input_length * is 0. * \param X_limbs The number of limbs of \p X. * \param[in] input The input buffer to import from. * May only be #NULL if \p input_length is 0. * \param input_length The length in bytes of \p input. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't * large enough to hold the value in \p input. */ int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X, size_t X_limbs, const unsigned char *input, size_t input_length); /** Export A into unsigned binary data, little-endian. * * \note If \p output is shorter than \p A the export is still successful if the * value held in \p A fits in the buffer (that is, if enough of the most * significant bytes of \p A are 0). * * \param[in] A The address of the MPI. * \param A_limbs The number of limbs of \p A. * \param[out] output The output buffer to export to. * \param output_length The length in bytes of \p output. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't * large enough to hold the value of \p A. */ int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A, size_t A_limbs, unsigned char *output, size_t output_length); /** Export A into unsigned binary data, big-endian. * * \note If \p output is shorter than \p A the export is still successful if the * value held in \p A fits in the buffer (that is, if enough of the most * significant bytes of \p A are 0). * * \param[in] A The address of the MPI. * \param A_limbs The number of limbs of \p A. * \param[out] output The output buffer to export to. * \param output_length The length in bytes of \p output. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't * large enough to hold the value of \p A. */ int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A, size_t A_limbs, unsigned char *output, size_t output_length); /** \brief Shift an MPI in-place right by a number of bits. * * Shifting by more bits than there are bit positions * in \p X is valid and results in setting \p X to 0. * * This function's execution time depends on the value * of \p count (and of course \p limbs). * * \param[in,out] X The number to shift. * \param limbs The number of limbs of \p X. This must be at least 1. * \param count The number of bits to shift by. */ void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, size_t count); /** * \brief Shift an MPI in-place left by a number of bits. * * Shifting by more bits than there are bit positions * in \p X will produce an unspecified result. * * This function's execution time depends on the value * of \p count (and of course \p limbs). * \param[in,out] X The number to shift. * \param limbs The number of limbs of \p X. This must be at least 1. * \param count The number of bits to shift by. */ void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs, size_t count); /** * \brief Add two fixed-size large unsigned integers, returning the carry. * * Calculates `A + B` where `A` and `B` have the same size. * * This function operates modulo `2^(biL*limbs)` and returns the carry * (1 if there was a wraparound, and 0 otherwise). * * \p X may be aliased to \p A or \p B. * * \param[out] X The result of the addition. * \param[in] A Little-endian presentation of the left operand. * \param[in] B Little-endian presentation of the right operand. * \param limbs Number of limbs of \p X, \p A and \p B. * * \return 1 if `A + B >= 2^(biL*limbs)`, 0 otherwise. */ mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs); /** * \brief Conditional addition of two fixed-size large unsigned integers, * returning the carry. * * Functionally equivalent to * * ``` * if( cond ) * X += A; * return carry; * ``` * * This function operates modulo `2^(biL*limbs)`. * * \param[in,out] X The pointer to the (little-endian) array * representing the bignum to accumulate onto. * \param[in] A The pointer to the (little-endian) array * representing the bignum to conditionally add * to \p X. This may be aliased to \p X but may not * overlap otherwise. * \param limbs Number of limbs of \p X and \p A. * \param cond Condition bit dictating whether addition should * happen or not. This must be \c 0 or \c 1. * * \warning If \p cond is neither 0 nor 1, the result of this function * is unspecified, and the resulting value in \p X might be * neither its original value nor \p X + \p A. * * \return 1 if `X + cond * A >= 2^(biL*limbs)`, 0 otherwise. */ mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t limbs, unsigned cond); /** * \brief Subtract two fixed-size large unsigned integers, returning the borrow. * * Calculate `A - B` where \p A and \p B have the same size. * This function operates modulo `2^(biL*limbs)` and returns the carry * (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise). * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \param[out] X The result of the subtraction. * \param[in] A Little-endian presentation of left operand. * \param[in] B Little-endian presentation of right operand. * \param limbs Number of limbs of \p X, \p A and \p B. * * \return 1 if `A < B`. * 0 if `A >= B`. */ mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs); /** * \brief Perform a fixed-size multiply accumulate operation: X += b * A * * \p X may be aliased to \p A (when \p X_limbs == \p A_limbs), but may not * otherwise overlap. * * This function operates modulo `2^(biL*X_limbs)`. * * \param[in,out] X The pointer to the (little-endian) array * representing the bignum to accumulate onto. * \param X_limbs The number of limbs of \p X. This must be * at least \p A_limbs. * \param[in] A The pointer to the (little-endian) array * representing the bignum to multiply with. * This may be aliased to \p X but may not overlap * otherwise. * \param A_limbs The number of limbs of \p A. * \param b X scalar to multiply with. * * \return The carry at the end of the operation. */ mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *X, size_t X_limbs, const mbedtls_mpi_uint *A, size_t A_limbs, mbedtls_mpi_uint b); /** * \brief Perform a known-size multiplication * * \p X may not be aliased to any of the inputs for this function. * \p A may be aliased to \p B. * * \param[out] X The pointer to the (little-endian) array to receive * the product of \p A_limbs and \p B_limbs. * This must be of length \p A_limbs + \p B_limbs. * \param[in] A The pointer to the (little-endian) array * representing the first factor. * \param A_limbs The number of limbs in \p A. * \param[in] B The pointer to the (little-endian) array * representing the second factor. * \param B_limbs The number of limbs in \p B. */ void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t A_limbs, const mbedtls_mpi_uint *B, size_t B_limbs); /** * \brief Calculate initialisation value for fast Montgomery modular * multiplication * * \param[in] N Little-endian presentation of the modulus. This must have * at least one limb. * * \return The initialisation value for fast Montgomery modular multiplication */ mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N); /** * \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36) * * \p A and \p B must be in canonical form. That is, < \p N. * * \p X may be aliased to \p A or \p N, or even \p B (if \p AN_limbs == * \p B_limbs) but may not overlap any parameters otherwise. * * \p A and \p B may alias each other, if \p AN_limbs == \p B_limbs. They may * not alias \p N (since they must be in canonical form, they cannot == \p N). * * \param[out] X The destination MPI, as a little-endian array of * length \p AN_limbs. * On successful completion, X contains the result of * the multiplication `A * B * R^-1` mod N where * `R = 2^(biL*AN_limbs)`. * \param[in] A Little-endian presentation of first operand. * Must have the same number of limbs as \p N. * \param[in] B Little-endian presentation of second operand. * \param[in] B_limbs The number of limbs in \p B. * Must be <= \p AN_limbs. * \param[in] N Little-endian presentation of the modulus. * This must be odd, and have exactly the same number * of limbs as \p A. * It may alias \p X, but must not alias or otherwise * overlap any of the other parameters. * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N. * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. * This can be calculated by `mbedtls_mpi_core_montmul_init()`. * \param[in,out] T Temporary storage of size at least 2*AN_limbs+1 limbs. * Its initial content is unused and * its final content is indeterminate. * It must not alias or otherwise overlap any of the * other parameters. */ void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t B_limbs, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, mbedtls_mpi_uint *T); /** * \brief Calculate the square of the Montgomery constant. (Needed * for conversion and operations in Montgomery form.) * * \param[out] X A pointer to the result of the calculation of * the square of the Montgomery constant: * 2^{2*n*biL} mod N. * \param[in] N Little-endian presentation of the modulus, which must be odd. * * \return 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space * to store the value of Montgomery constant squared. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p N modulus is zero. * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p N modulus is negative. */ int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X, const mbedtls_mpi *N); #if defined(MBEDTLS_TEST_HOOKS) /** * Copy an MPI from a table without leaking the index. * * \param dest The destination buffer. This must point to a writable * buffer of at least \p limbs limbs. * \param table The address of the table. This must point to a readable * array of \p count elements of \p limbs limbs each. * \param limbs The number of limbs in each table entry. * \param count The number of entries in \p table. * \param index The (secret) table index to look up. This must be in the * range `0 .. count-1`. */ void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest, const mbedtls_mpi_uint *table, size_t limbs, size_t count, size_t index); #endif /* MBEDTLS_TEST_HOOKS */ /** * \brief Fill an integer with a number of random bytes. * * \param X The destination MPI. * \param X_limbs The number of limbs of \p X. * \param bytes The number of random bytes to generate. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p X does not have * enough room for \p bytes bytes. * \return A negative error code on RNG failure. * * \note The bytes obtained from the RNG are interpreted * as a big-endian representation of an MPI; this can * be relevant in applications like deterministic ECDSA. */ int mbedtls_mpi_core_fill_random(mbedtls_mpi_uint *X, size_t X_limbs, size_t bytes, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Generate a random number uniformly in a range. * * This function generates a random number between \p min inclusive and * \p N exclusive. * * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) * when the RNG is a suitably parametrized instance of HMAC_DRBG * and \p min is \c 1. * * \note There are `N - min` possible outputs. The lower bound * \p min can be reached, but the upper bound \p N cannot. * * \param X The destination MPI, with \p limbs limbs. * It must not be aliased with \p N or otherwise overlap it. * \param min The minimum value to return. * \param N The upper bound of the range, exclusive, with \p limbs limbs. * In other words, this is one plus the maximum value to return. * \p N must be strictly larger than \p min. * \param limbs The number of limbs of \p N and \p X. * This must not be 0. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was * unable to find a suitable value within a limited number * of attempts. This has a negligible probability if \p N * is significantly larger than \p min, which is the case * for all usual cryptographic applications. */ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X, mbedtls_mpi_uint min, const mbedtls_mpi_uint *N, size_t limbs, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Returns the number of limbs of working memory required for * a call to `mbedtls_mpi_core_exp_mod()`. * * \note This will always be at least * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`, * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`. * * \param AN_limbs The number of limbs in the input `A` and the modulus `N` * (they must be the same size) that will be given to * `mbedtls_mpi_core_exp_mod()`. * \param E_limbs The number of limbs in the exponent `E` that will be given * to `mbedtls_mpi_core_exp_mod()`. * * \return The number of limbs of working memory required by * `mbedtls_mpi_core_exp_mod()`. */ size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs); /** * \brief Perform a modular exponentiation with public or secret exponent: * X = A^E mod N, where \p A is already in Montgomery form. * * \warning This function is not constant time with respect to \p E (the exponent). * * \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs == * \p AN_limbs. * * \param[out] X The destination MPI, as a little endian array of length * \p AN_limbs. * \param[in] A The base MPI, as a little endian array of length \p AN_limbs. * Must be in Montgomery form. * \param[in] N The modulus, as a little endian array of length \p AN_limbs. * \param AN_limbs The number of limbs in \p X, \p A, \p N, \p RR. * \param[in] E The exponent, as a little endian array of length \p E_limbs. * \param E_limbs The number of limbs in \p E. * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little * endian array of length \p AN_limbs. * \param[in,out] T Temporary storage of at least the number of limbs returned * by `mbedtls_mpi_core_exp_mod_working_limbs()`. * Its initial content is unused and its final content is * indeterminate. * It must not alias or otherwise overlap any of the other * parameters. * It is up to the caller to zeroize \p T when it is no * longer needed, and before freeing it if it was dynamically * allocated. */ void mbedtls_mpi_core_exp_mod_unsafe(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *E, size_t E_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T); /** * \brief Perform a modular exponentiation with secret exponent: * X = A^E mod N, where \p A is already in Montgomery form. * * \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs == * \p AN_limbs. * * \param[out] X The destination MPI, as a little endian array of length * \p AN_limbs. * \param[in] A The base MPI, as a little endian array of length \p AN_limbs. * Must be in Montgomery form. * \param[in] N The modulus, as a little endian array of length \p AN_limbs. * \param AN_limbs The number of limbs in \p X, \p A, \p N, \p RR. * \param[in] E The exponent, as a little endian array of length \p E_limbs. * \param E_limbs The number of limbs in \p E. * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little * endian array of length \p AN_limbs. * \param[in,out] T Temporary storage of at least the number of limbs returned * by `mbedtls_mpi_core_exp_mod_working_limbs()`. * Its initial content is unused and its final content is * indeterminate. * It must not alias or otherwise overlap any of the other * parameters. * It is up to the caller to zeroize \p T when it is no * longer needed, and before freeing it if it was dynamically * allocated. */ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *E, size_t E_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T); /** * \brief Subtract unsigned integer from known-size large unsigned integers. * Return the borrow. * * \param[out] X The result of the subtraction. * \param[in] A The left operand. * \param b The unsigned scalar to subtract. * \param limbs Number of limbs of \p X and \p A. * * \return 1 if `A < b`. * 0 if `A >= b`. */ mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, mbedtls_mpi_uint b, size_t limbs); /** * \brief Determine if a given MPI has the value \c 0 in constant time with * respect to the value (but not with respect to the number of limbs). * * \param[in] A The MPI to test. * \param limbs Number of limbs in \p A. * * \return MBEDTLS_CT_FALSE if `A == 0` * MBEDTLS_CT_TRUE if `A != 0`. */ mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A, size_t limbs); /** * \brief Returns the number of limbs of working memory required for * a call to `mbedtls_mpi_core_montmul()`. * * \param AN_limbs The number of limbs in the input `A` and the modulus `N` * (they must be the same size) that will be given to * `mbedtls_mpi_core_montmul()` or one of the other functions * that specifies this as the amount of working memory needed. * * \return The number of limbs of working memory required by * `mbedtls_mpi_core_montmul()` (or other similar function). */ static inline size_t mbedtls_mpi_core_montmul_working_limbs(size_t AN_limbs) { return 2 * AN_limbs + 1; } /** Convert an MPI into Montgomery form. * * \p X may be aliased to \p A, but may not otherwise overlap it. * * \p X may not alias \p N (it is in canonical form, so must be strictly less * than \p N). Nor may it alias or overlap \p rr (this is unlikely to be * required in practice.) * * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is * an alternative to calling `mbedtls_mpi_mod_raw_to_mont_rep()` when we * don't want to allocate memory. * * \param[out] X The result of the conversion. * Must have the same number of limbs as \p A. * \param[in] A The MPI to convert into Montgomery form. * Must have the same number of limbs as the modulus. * \param[in] N The address of the modulus, which gives the size of * the base `R` = 2^(biL*N->limbs). * \param[in] AN_limbs The number of limbs in \p X, \p A, \p N and \p rr. * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. * This can be determined by calling * `mbedtls_mpi_core_montmul_init()`. * \param[in] rr The residue for `2^{2*n*biL} mod N`. * \param[in,out] T Temporary storage of size at least * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)` * limbs. * Its initial content is unused and * its final content is indeterminate. * It must not alias or otherwise overlap any of the * other parameters. */ void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, const mbedtls_mpi_uint *rr, mbedtls_mpi_uint *T); /** Convert an MPI from Montgomery form. * * \p X may be aliased to \p A, but may not otherwise overlap it. * * \p X may not alias \p N (it is in canonical form, so must be strictly less * than \p N). * * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is * an alternative to calling `mbedtls_mpi_mod_raw_from_mont_rep()` when we * don't want to allocate memory. * * \param[out] X The result of the conversion. * Must have the same number of limbs as \p A. * \param[in] A The MPI to convert from Montgomery form. * Must have the same number of limbs as the modulus. * \param[in] N The address of the modulus, which gives the size of * the base `R` = 2^(biL*N->limbs). * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N. * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. * This can be determined by calling * `mbedtls_mpi_core_montmul_init()`. * \param[in,out] T Temporary storage of size at least * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)` * limbs. * Its initial content is unused and * its final content is indeterminate. * It must not alias or otherwise overlap any of the * other parameters. */ void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, mbedtls_mpi_uint *T); /* * Can't define thread local variables with our abstraction layer: do nothing if threading is on. */ #if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C) extern int mbedtls_mpi_optionally_safe_codepath; static inline void mbedtls_mpi_optionally_safe_codepath_reset(void) { // Set to a default that is neither MBEDTLS_MPI_IS_PUBLIC nor MBEDTLS_MPI_IS_SECRET mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC + MBEDTLS_MPI_IS_SECRET + 1; } #endif #endif /* MBEDTLS_BIGNUM_CORE_H */ webfakes/src/mbedtls/library/pkwrite.h0000644000176200001440000001106414740737024017576 0ustar liggesusers/** * \file pkwrite.h * * \brief Internal defines shared by the PK write module */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_WRITE_H #define MBEDTLS_PK_WRITE_H #include "mbedtls/build_info.h" #include "mbedtls/pk.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Max sizes of key per types. Shown as tag + len (+ content). */ #if defined(MBEDTLS_RSA_C) /* * RSA public keys: * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 * algorithm AlgorithmIdentifier, 1 + 1 (sequence) * + 1 + 1 + 9 (rsa oid) * + 1 + 1 (params null) * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) * RSAPublicKey ::= SEQUENCE { 1 + 3 * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 * } */ #define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) /* * RSA private keys: * RSAPrivateKey ::= SEQUENCE { 1 + 3 * version Version, 1 + 1 + 1 * modulus INTEGER, 1 + 3 + MPI_MAX + 1 * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) * } */ #define MBEDTLS_MPI_MAX_SIZE_2 (MBEDTLS_MPI_MAX_SIZE / 2 + \ MBEDTLS_MPI_MAX_SIZE % 2) #define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES (47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + 5 * MBEDTLS_MPI_MAX_SIZE_2) #else /* MBEDTLS_RSA_C */ #define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES 0 #define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES 0 #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Find the maximum number of bytes necessary to store an EC point. When USE_PSA * is defined this means looking for the maximum between PSA and built-in * supported curves. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #define MBEDTLS_PK_MAX_ECC_BYTES (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \ MBEDTLS_ECP_MAX_BYTES ? \ PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) : \ MBEDTLS_ECP_MAX_BYTES) #else /* MBEDTLS_USE_PSA_CRYPTO */ #define MBEDTLS_PK_MAX_ECC_BYTES MBEDTLS_ECP_MAX_BYTES #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * EC public keys: * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 * algorithm AlgorithmIdentifier, 1 + 1 (sequence) * + 1 + 1 + 7 (ec oid) * + 1 + 1 + 9 (namedCurve oid) * subjectPublicKey BIT STRING 1 + 2 + 1 [1] * + 1 (point format) [1] * + 2 * ECP_MAX (coords) [1] * } */ #define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_PK_MAX_ECC_BYTES) /* * EC private keys: * ECPrivateKey ::= SEQUENCE { 1 + 2 * version INTEGER , 1 + 1 + 1 * privateKey OCTET STRING, 1 + 1 + ECP_MAX * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above * } */ #define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES (29 + 3 * MBEDTLS_PK_MAX_ECC_BYTES) #else /* MBEDTLS_PK_HAVE_ECC_KEYS */ #define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES 0 #define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES 0 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Define the maximum available public key DER length based on the supported * key types (EC and/or RSA). */ #if (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) #define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES #else #define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES #endif #endif /* MBEDTLS_PK_WRITE_H */ webfakes/src/mbedtls/library/pem.c0000644000176200001440000003452314740737024016672 0ustar liggesusers/* * Privacy Enhanced Mail (PEM) decoding * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #include "mbedtls/base64.h" #include "mbedtls/des.h" #include "mbedtls/aes.h" #include "mbedtls/md.h" #include "mbedtls/cipher.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif #if defined(MBEDTLS_MD_CAN_MD5) && \ defined(MBEDTLS_CIPHER_MODE_CBC) && \ (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)) #define PEM_RFC1421 #endif /* MBEDTLS_MD_CAN_MD5 && MBEDTLS_CIPHER_MODE_CBC && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ #if defined(MBEDTLS_PEM_PARSE_C) void mbedtls_pem_init(mbedtls_pem_context *ctx) { memset(ctx, 0, sizeof(mbedtls_pem_context)); } #if defined(PEM_RFC1421) /* * Read a 16-byte hex string and convert it to binary */ static int pem_get_iv(const unsigned char *s, unsigned char *iv, size_t iv_len) { size_t i, j, k; memset(iv, 0, iv_len); for (i = 0; i < iv_len * 2; i++, s++) { if (*s >= '0' && *s <= '9') { j = *s - '0'; } else if (*s >= 'A' && *s <= 'F') { j = *s - '7'; } else if (*s >= 'a' && *s <= 'f') { j = *s - 'W'; } else { return MBEDTLS_ERR_PEM_INVALID_ENC_IV; } k = ((i & 1) != 0) ? j : j << 4; iv[i >> 1] = (unsigned char) (iv[i >> 1] | k); } return 0; } static int pem_pbkdf1(unsigned char *key, size_t keylen, unsigned char *iv, const unsigned char *pwd, size_t pwdlen) { mbedtls_md_context_t md5_ctx; const mbedtls_md_info_t *md5_info; unsigned char md5sum[16]; size_t use_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_init(&md5_ctx); /* Prepare the context. (setup() errors gracefully on NULL info.) */ md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); if ((ret = mbedtls_md_setup(&md5_ctx, md5_info, 0)) != 0) { goto exit; } /* * key[ 0..15] = MD5(pwd || IV) */ if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { goto exit; } if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) { goto exit; } if (keylen <= 16) { memcpy(key, md5sum, keylen); goto exit; } memcpy(key, md5sum, 16); /* * key[16..23] = MD5(key[ 0..15] || pwd || IV]) */ if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, md5sum, 16)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { goto exit; } if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) { goto exit; } use_len = 16; if (keylen < 32) { use_len = keylen - 16; } memcpy(key + 16, md5sum, use_len); exit: mbedtls_md_free(&md5_ctx); mbedtls_platform_zeroize(md5sum, 16); return ret; } #if defined(MBEDTLS_DES_C) /* * Decrypt with DES-CBC, using PBKDF1 for key derivation */ static int pem_des_decrypt(unsigned char des_iv[8], unsigned char *buf, size_t buflen, const unsigned char *pwd, size_t pwdlen) { mbedtls_des_context des_ctx; unsigned char des_key[8]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_des_init(&des_ctx); if ((ret = pem_pbkdf1(des_key, 8, des_iv, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_des_setkey_dec(&des_ctx, des_key)) != 0) { goto exit; } ret = mbedtls_des_crypt_cbc(&des_ctx, MBEDTLS_DES_DECRYPT, buflen, des_iv, buf, buf); exit: mbedtls_des_free(&des_ctx); mbedtls_platform_zeroize(des_key, 8); return ret; } /* * Decrypt with 3DES-CBC, using PBKDF1 for key derivation */ static int pem_des3_decrypt(unsigned char des3_iv[8], unsigned char *buf, size_t buflen, const unsigned char *pwd, size_t pwdlen) { mbedtls_des3_context des3_ctx; unsigned char des3_key[24]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_des3_init(&des3_ctx); if ((ret = pem_pbkdf1(des3_key, 24, des3_iv, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_des3_set3key_dec(&des3_ctx, des3_key)) != 0) { goto exit; } ret = mbedtls_des3_crypt_cbc(&des3_ctx, MBEDTLS_DES_DECRYPT, buflen, des3_iv, buf, buf); exit: mbedtls_des3_free(&des3_ctx); mbedtls_platform_zeroize(des3_key, 24); return ret; } #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) /* * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation */ static int pem_aes_decrypt(unsigned char aes_iv[16], unsigned int keylen, unsigned char *buf, size_t buflen, const unsigned char *pwd, size_t pwdlen) { mbedtls_aes_context aes_ctx; unsigned char aes_key[32]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_aes_init(&aes_ctx); if ((ret = pem_pbkdf1(aes_key, keylen, aes_iv, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_aes_setkey_dec(&aes_ctx, aes_key, keylen * 8)) != 0) { goto exit; } ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, buflen, aes_iv, buf, buf); exit: mbedtls_aes_free(&aes_ctx); mbedtls_platform_zeroize(aes_key, keylen); return ret; } #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) static int pem_check_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len) { /* input_len > 0 is guaranteed by mbedtls_pem_read_buffer(). */ size_t pad_len = input[input_len - 1]; size_t i; if (pad_len > input_len) { return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH; } *data_len = input_len - pad_len; for (i = *data_len; i < input_len; i++) { if (input[i] != pad_len) { return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH; } } return 0; } #endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */ #endif /* PEM_RFC1421 */ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len) { int ret, enc; size_t len; unsigned char *buf; const unsigned char *s1, *s2, *end; #if defined(PEM_RFC1421) unsigned char pem_iv[16]; mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; #else ((void) pwd); ((void) pwdlen); #endif /* PEM_RFC1421 */ if (ctx == NULL) { return MBEDTLS_ERR_PEM_BAD_INPUT_DATA; } s1 = (unsigned char *) strstr((const char *) data, header); if (s1 == NULL) { return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } s2 = (unsigned char *) strstr((const char *) data, footer); if (s2 == NULL || s2 <= s1) { return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } s1 += strlen(header); if (*s1 == ' ') { s1++; } if (*s1 == '\r') { s1++; } if (*s1 == '\n') { s1++; } else { return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } end = s2; end += strlen(footer); if (*end == ' ') { end++; } if (*end == '\r') { end++; } if (*end == '\n') { end++; } *use_len = (size_t) (end - data); enc = 0; if (s2 - s1 >= 22 && memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) { #if defined(PEM_RFC1421) enc++; s1 += 22; if (*s1 == '\r') { s1++; } if (*s1 == '\n') { s1++; } else { return MBEDTLS_ERR_PEM_INVALID_DATA; } #if defined(MBEDTLS_DES_C) if (s2 - s1 >= 23 && memcmp(s1, "DEK-Info: DES-EDE3-CBC,", 23) == 0) { enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; s1 += 23; if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) { return MBEDTLS_ERR_PEM_INVALID_ENC_IV; } s1 += 16; } else if (s2 - s1 >= 18 && memcmp(s1, "DEK-Info: DES-CBC,", 18) == 0) { enc_alg = MBEDTLS_CIPHER_DES_CBC; s1 += 18; if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) { return MBEDTLS_ERR_PEM_INVALID_ENC_IV; } s1 += 16; } #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) if (s2 - s1 >= 14 && memcmp(s1, "DEK-Info: AES-", 14) == 0) { if (s2 - s1 < 22) { return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG; } else if (memcmp(s1, "DEK-Info: AES-128-CBC,", 22) == 0) { enc_alg = MBEDTLS_CIPHER_AES_128_CBC; } else if (memcmp(s1, "DEK-Info: AES-192-CBC,", 22) == 0) { enc_alg = MBEDTLS_CIPHER_AES_192_CBC; } else if (memcmp(s1, "DEK-Info: AES-256-CBC,", 22) == 0) { enc_alg = MBEDTLS_CIPHER_AES_256_CBC; } else { return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG; } s1 += 22; if (s2 - s1 < 32 || pem_get_iv(s1, pem_iv, 16) != 0) { return MBEDTLS_ERR_PEM_INVALID_ENC_IV; } s1 += 32; } #endif /* MBEDTLS_AES_C */ if (enc_alg == MBEDTLS_CIPHER_NONE) { return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG; } if (*s1 == '\r') { s1++; } if (*s1 == '\n') { s1++; } else { return MBEDTLS_ERR_PEM_INVALID_DATA; } #else return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE; #endif /* PEM_RFC1421 */ } if (s1 >= s2) { return MBEDTLS_ERR_PEM_INVALID_DATA; } ret = mbedtls_base64_decode(NULL, 0, &len, s1, (size_t) (s2 - s1)); if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret); } if (len == 0) { return MBEDTLS_ERR_PEM_BAD_INPUT_DATA; } if ((buf = mbedtls_calloc(1, len)) == NULL) { return MBEDTLS_ERR_PEM_ALLOC_FAILED; } if ((ret = mbedtls_base64_decode(buf, len, &len, s1, (size_t) (s2 - s1))) != 0) { mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret); } if (enc != 0) { #if defined(PEM_RFC1421) if (pwd == NULL) { mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED; } ret = 0; #if defined(MBEDTLS_DES_C) if (enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC) { ret = pem_des3_decrypt(pem_iv, buf, len, pwd, pwdlen); } else if (enc_alg == MBEDTLS_CIPHER_DES_CBC) { ret = pem_des_decrypt(pem_iv, buf, len, pwd, pwdlen); } #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) if (enc_alg == MBEDTLS_CIPHER_AES_128_CBC) { ret = pem_aes_decrypt(pem_iv, 16, buf, len, pwd, pwdlen); } else if (enc_alg == MBEDTLS_CIPHER_AES_192_CBC) { ret = pem_aes_decrypt(pem_iv, 24, buf, len, pwd, pwdlen); } else if (enc_alg == MBEDTLS_CIPHER_AES_256_CBC) { ret = pem_aes_decrypt(pem_iv, 32, buf, len, pwd, pwdlen); } #endif /* MBEDTLS_AES_C */ if (ret != 0) { mbedtls_zeroize_and_free(buf, len); return ret; } /* Check PKCS padding and update data length based on padding info. * This can be used to detect invalid padding data and password * mismatches. */ size_t unpadded_len; ret = pem_check_pkcs_padding(buf, len, &unpadded_len); if (ret != 0) { mbedtls_zeroize_and_free(buf, len); return ret; } len = unpadded_len; #else mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE; #endif /* PEM_RFC1421 */ } ctx->buf = buf; ctx->buflen = len; return 0; } void mbedtls_pem_free(mbedtls_pem_context *ctx) { if (ctx == NULL) { return; } if (ctx->buf != NULL) { mbedtls_zeroize_and_free(ctx->buf, ctx->buflen); } mbedtls_free(ctx->info); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pem_context)); } #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_WRITE_C) int mbedtls_pem_write_buffer(const char *header, const char *footer, const unsigned char *der_data, size_t der_len, unsigned char *buf, size_t buf_len, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *encode_buf = NULL, *c, *p = buf; size_t len = 0, use_len, add_len = 0; mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len); add_len = strlen(header) + strlen(footer) + (((use_len > 2) ? (use_len - 2) : 0) / 64) + 1; if (use_len + add_len > buf_len) { *olen = use_len + add_len; return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; } if (use_len != 0 && ((encode_buf = mbedtls_calloc(1, use_len)) == NULL)) { return MBEDTLS_ERR_PEM_ALLOC_FAILED; } if ((ret = mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data, der_len)) != 0) { mbedtls_free(encode_buf); return ret; } memcpy(p, header, strlen(header)); p += strlen(header); c = encode_buf; while (use_len) { len = (use_len > 64) ? 64 : use_len; memcpy(p, c, len); use_len -= len; p += len; c += len; *p++ = '\n'; } memcpy(p, footer, strlen(footer)); p += strlen(footer); *p++ = '\0'; *olen = (size_t) (p - buf); /* Clean any remaining data previously written to the buffer */ memset(buf + *olen, 0, buf_len - *olen); mbedtls_free(encode_buf); return 0; } #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ webfakes/src/mbedtls/library/constant_time.c0000644000176200001440000002123014740737024020747 0ustar liggesusers/** * Constant-time functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following functions are implemented without using comparison operators, as those * might be translated to branches by some compilers on some platforms. */ #include #include #include "common.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include #if !defined(MBEDTLS_CT_ASM) /* * Define an object with the value zero, such that the compiler cannot prove that it * has the value zero (because it is volatile, it "may be modified in ways unknown to * the implementation"). */ volatile mbedtls_ct_uint_t mbedtls_ct_zero = 0; #endif /* * Define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS where assembly is present to * perform fast unaligned access to volatile data. * * This is needed because mbedtls_get_unaligned_uintXX etc don't support volatile * memory accesses. * * Some of these definitions could be moved into alignment.h but for now they are * only used here. */ #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && \ ((defined(MBEDTLS_CT_ARM_ASM) && (UINTPTR_MAX == 0xfffffffful)) || \ defined(MBEDTLS_CT_AARCH64_ASM)) /* We check pointer sizes to avoid issues with them not matching register size requirements */ #define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p) { /* This is UB, even where it's safe: * return *((volatile uint32_t*)p); * so instead the same thing is expressed in assembly below. */ uint32_t r; #if defined(MBEDTLS_CT_ARM_ASM) asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :); #elif defined(MBEDTLS_CT_AARCH64_ASM) asm volatile ("ldr %w0, [%1]" : "=r" (r) : MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT(p) :); #else #error "No assembly defined for mbedtls_get_unaligned_volatile_uint32" #endif return r; } #endif /* defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && (defined(MBEDTLS_CT_ARM_ASM) || defined(MBEDTLS_CT_AARCH64_ASM)) */ int mbedtls_ct_memcmp(const void *a, const void *b, size_t n) { size_t i = 0; /* * `A` and `B` are cast to volatile to ensure that the compiler * generates code that always fully reads both buffers. * Otherwise it could generate a test to exit early if `diff` has all * bits set early in the loop. */ volatile const unsigned char *A = (volatile const unsigned char *) a; volatile const unsigned char *B = (volatile const unsigned char *) b; uint32_t diff = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS) for (; (i + 4) <= n; i += 4) { uint32_t x = mbedtls_get_unaligned_volatile_uint32(A + i); uint32_t y = mbedtls_get_unaligned_volatile_uint32(B + i); diff |= x ^ y; } #endif for (; i < n; i++) { /* Read volatile data in order before computing diff. * This avoids IAR compiler warning: * 'the order of volatile accesses is undefined ..' */ unsigned char x = A[i], y = B[i]; diff |= x ^ y; } #if (INT_MAX < INT32_MAX) /* We don't support int smaller than 32-bits, but if someone tried to build * with this configuration, there is a risk that, for differing data, the * only bits set in diff are in the top 16-bits, and would be lost by a * simple cast from uint32 to int. * This would have significant security implications, so protect against it. */ #error "mbedtls_ct_memcmp() requires minimum 32-bit ints" #else /* The bit-twiddling ensures that when we cast uint32_t to int, we are casting * a value that is in the range 0..INT_MAX - a value larger than this would * result in implementation defined behaviour. * * This ensures that the value returned by the function is non-zero iff * diff is non-zero. */ return (int) ((diff & 0xffff) | (diff >> 16)); #endif } #if defined(MBEDTLS_NIST_KW_C) int mbedtls_ct_memcmp_partial(const void *a, const void *b, size_t n, size_t skip_head, size_t skip_tail) { unsigned int diff = 0; volatile const unsigned char *A = (volatile const unsigned char *) a; volatile const unsigned char *B = (volatile const unsigned char *) b; size_t valid_end = n - skip_tail; for (size_t i = 0; i < n; i++) { unsigned char x = A[i], y = B[i]; unsigned int d = x ^ y; mbedtls_ct_condition_t valid = mbedtls_ct_bool_and(mbedtls_ct_uint_ge(i, skip_head), mbedtls_ct_uint_lt(i, valid_end)); diff |= mbedtls_ct_uint_if_else_0(valid, d); } /* Since we go byte-by-byte, the only bits set will be in the bottom 8 bits, so the * cast from uint to int is safe. */ return (int) diff; } #endif #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) void mbedtls_ct_memmove_left(void *start, size_t total, size_t offset) { volatile unsigned char *buf = start; for (size_t i = 0; i < total; i++) { mbedtls_ct_condition_t no_op = mbedtls_ct_uint_gt(total - offset, i); /* The first `total - offset` passes are a no-op. The last * `offset` passes shift the data one byte to the left and * zero out the last byte. */ for (size_t n = 0; n < total - 1; n++) { unsigned char current = buf[n]; unsigned char next = buf[n+1]; buf[n] = mbedtls_ct_uint_if(no_op, current, next); } buf[total-1] = mbedtls_ct_uint_if_else_0(no_op, buf[total-1]); } } #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition, unsigned char *dest, const unsigned char *src1, const unsigned char *src2, size_t len) { #if defined(MBEDTLS_CT_SIZE_64) const uint64_t mask = (uint64_t) condition; const uint64_t not_mask = (uint64_t) ~mbedtls_ct_compiler_opaque(condition); #else const uint32_t mask = (uint32_t) condition; const uint32_t not_mask = (uint32_t) ~mbedtls_ct_compiler_opaque(condition); #endif /* If src2 is NULL, setup src2 so that we read from the destination address. * * This means that if src2 == NULL && condition is false, the result will be a * no-op because we read from dest and write the same data back into dest. */ if (src2 == NULL) { src2 = dest; } /* dest[i] = c1 == c2 ? src[i] : dest[i] */ size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) #if defined(MBEDTLS_CT_SIZE_64) for (; (i + 8) <= len; i += 8) { uint64_t a = mbedtls_get_unaligned_uint64(src1 + i) & mask; uint64_t b = mbedtls_get_unaligned_uint64(src2 + i) & not_mask; mbedtls_put_unaligned_uint64(dest + i, a | b); } #else for (; (i + 4) <= len; i += 4) { uint32_t a = mbedtls_get_unaligned_uint32(src1 + i) & mask; uint32_t b = mbedtls_get_unaligned_uint32(src2 + i) & not_mask; mbedtls_put_unaligned_uint32(dest + i, a | b); } #endif /* defined(MBEDTLS_CT_SIZE_64) */ #endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */ for (; i < len; i++) { dest[i] = (src1[i] & mask) | (src2[i] & not_mask); } } void mbedtls_ct_memcpy_offset(unsigned char *dest, const unsigned char *src, size_t offset, size_t offset_min, size_t offset_max, size_t len) { size_t offsetval; for (offsetval = offset_min; offsetval <= offset_max; offsetval++) { mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offsetval, offset), dest, src + offsetval, NULL, len); } } #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len) { uint32_t mask = (uint32_t) ~condition; uint8_t *p = (uint8_t *) buf; size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) for (; (i + 4) <= len; i += 4) { mbedtls_put_unaligned_uint32((void *) (p + i), mbedtls_get_unaligned_uint32((void *) (p + i)) & mask); } #endif for (; i < len; i++) { p[i] = p[i] & mask; } } #endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */ webfakes/src/mbedtls/library/asn1write.c0000644000176200001440000003034314740737024020022 0ustar liggesusers/* * ASN.1 buffer writing functionality * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #endif int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len) { #if SIZE_MAX > 0xFFFFFFFF if (len > 0xFFFFFFFF) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } #endif int required = 1; if (len >= 0x80) { for (size_t l = len; l != 0; l >>= 8) { required++; } } if (required > (*p - start)) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } do { *--(*p) = MBEDTLS_BYTE_0(len); len >>= 8; } while (len); if (required > 1) { *--(*p) = (unsigned char) (0x80 + required - 1); } return required; } int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag) { if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = tag; return 1; } #endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ #if defined(MBEDTLS_ASN1_WRITE_C) static int mbedtls_asn1_write_len_and_tag(unsigned char **p, const unsigned char *start, size_t len, unsigned char tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag)); return (int) len; } int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size) { size_t len = 0; if (*p < start || (size_t) (*p - start) < size) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } len = size; (*p) -= len; memcpy(*p, buf, len); return (int) len; } #if defined(MBEDTLS_BIGNUM_C) int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; // Write the MPI // len = mbedtls_mpi_size(X); /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not * as 0 digits. We need to end up with 020100, not with 0200. */ if (len == 0) { len = 1; } if (*p < start || (size_t) (*p - start) < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } (*p) -= len; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len)); // DER format assumes 2s complement for numbers, so the leftmost bit // should be 0 for positive numbers and 1 for negative numbers. // if (X->s == 1 && **p & 0x80) { if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = 0x00; len += 1; } ret = mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_INTEGER); cleanup: return ret; } #endif /* MBEDTLS_BIGNUM_C */ int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start) { // Write NULL // return mbedtls_asn1_write_len_and_tag(p, start, 0, MBEDTLS_ASN1_NULL); } int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, (const unsigned char *) oid, oid_len)); return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OID); } int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len) { return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1); } int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len, int has_par) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; if (has_par) { if (par_len == 0) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start)); } else { len += par_len; } } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); } int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean) { size_t len = 0; if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = (boolean) ? 255 : 0; len++; return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BOOLEAN); } static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag) { size_t len = 0; do { if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } len += 1; *--(*p) = val & 0xff; val >>= 8; } while (val > 0); if (**p & 0x80) { if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = 0x00; len += 1; } return mbedtls_asn1_write_len_and_tag(p, start, len, tag); } int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val) { return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER); } int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val) { return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED); } int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag, const char *text, size_t text_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, (const unsigned char *) text, text_len)); return mbedtls_asn1_write_len_and_tag(p, start, len, tag); } int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len) { return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len); } int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len) { return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len); } int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len) { return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len); } int mbedtls_asn1_write_named_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits) { size_t unused_bits, byte_len; const unsigned char *cur_byte; unsigned char cur_byte_shifted; unsigned char bit; byte_len = (bits + 7) / 8; unused_bits = (byte_len * 8) - bits; /* * Named bitstrings require that trailing 0s are excluded in the encoding * of the bitstring. Trailing 0s are considered part of the 'unused' bits * when encoding this value in the first content octet */ if (bits != 0) { cur_byte = buf + byte_len - 1; cur_byte_shifted = *cur_byte >> unused_bits; for (;;) { bit = cur_byte_shifted & 0x1; cur_byte_shifted >>= 1; if (bit != 0) { break; } bits--; if (bits == 0) { break; } if (bits % 8 == 0) { cur_byte_shifted = *--cur_byte; } } } return mbedtls_asn1_write_bitstring(p, start, buf, bits); } int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits) { size_t len = 0; size_t unused_bits, byte_len; byte_len = (bits + 7) / 8; unused_bits = (byte_len * 8) - bits; if (*p < start || (size_t) (*p - start) < byte_len + 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } len = byte_len + 1; /* Write the bitstring. Ensure the unused bits are zeroed */ if (byte_len > 0) { byte_len--; *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1); (*p) -= byte_len; memcpy(*p, buf, byte_len); } /* Write unused bits */ *--(*p) = (unsigned char) unused_bits; return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BIT_STRING); } int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size)); return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OCTET_STRING); } #if !defined(MBEDTLS_ASN1_PARSE_C) /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ static mbedtls_asn1_named_data *asn1_find_named_data( mbedtls_asn1_named_data *list, const char *oid, size_t len) { while (list != NULL) { if (list->oid.len == len && memcmp(list->oid.p, oid, len) == 0) { break; } list = list->next; } return list; } #else #define asn1_find_named_data(list, oid, len) \ ((mbedtls_asn1_named_data *) mbedtls_asn1_find_named_data(list, oid, len)) #endif mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len) { mbedtls_asn1_named_data *cur; if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) { // Add new entry if not present yet based on OID // cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1, sizeof(mbedtls_asn1_named_data)); if (cur == NULL) { return NULL; } cur->oid.len = oid_len; cur->oid.p = mbedtls_calloc(1, oid_len); if (cur->oid.p == NULL) { mbedtls_free(cur); return NULL; } memcpy(cur->oid.p, oid, oid_len); cur->val.len = val_len; if (val_len != 0) { cur->val.p = mbedtls_calloc(1, val_len); if (cur->val.p == NULL) { mbedtls_free(cur->oid.p); mbedtls_free(cur); return NULL; } } cur->next = *head; *head = cur; } else if (val_len == 0) { mbedtls_free(cur->val.p); cur->val.p = NULL; } else if (cur->val.len != val_len) { /* * Enlarge existing value buffer if needed * Preserve old data until the allocation succeeded, to leave list in * a consistent state in case allocation fails. */ void *p = mbedtls_calloc(1, val_len); if (p == NULL) { return NULL; } mbedtls_free(cur->val.p); cur->val.p = p; cur->val.len = val_len; } if (val != NULL && val_len != 0) { memcpy(cur->val.p, val, val_len); } return cur; } #endif /* MBEDTLS_ASN1_WRITE_C */ webfakes/src/mbedtls/library/bignum.c0000644000176200001440000020200114740737024017356 0ustar liggesusers/* * Multi-precision integer library * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this Multi-precision * Integer library: * * [1] Handbook of Applied Cryptography - 1997 * Menezes, van Oorschot and Vanstone * * [2] Multi-Precision Math * Tom St Denis * https://github.com/libtom/libtommath/blob/develop/tommath.pdf * * [3] GNU Multi-Precision Arithmetic Library * https://gmplib.org/manual/index.html * */ #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #include "bignum_core.h" #include "bignum_internal.h" #include "bn_mul.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "constant_time_internal.h" #include #include #include "mbedtls/platform.h" /* * Conditionally select an MPI sign in constant time. * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid * values.) */ static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond, signed short sign1, signed short sign2) { return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1; } /* * Compare signed values in constant time */ int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned *ret) { mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result; if (X->n != Y->n) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0. * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. */ X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1); Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1); /* * If the signs are different, then the positive operand is the bigger. * That is if X is negative (X_is_negative == 1), then X < Y is true and it * is false if X is positive (X_is_negative == 0). */ different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign result = mbedtls_ct_bool_and(different_sign, X_is_negative); /* * Assuming signs are the same, compare X and Y. We switch the comparison * order if they are negative so that we get the right result, regardles of * sign. */ /* This array is used to conditionally swap the pointers in const time */ void * const p[2] = { X->p, Y->p }; size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1); mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n); /* * Store in result iff the signs are the same (i.e., iff different_sign == false). If * the signs differ, result has already been set, so we don't change it. */ result = mbedtls_ct_bool_or(result, mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt)); *ret = mbedtls_ct_uint_if_else_0(result, 1); return 0; } /* * Conditionally assign X = Y, without leaking information * about whether the assignment was made or not. * (Leaking information about the respective sizes of X and Y is ok however.) */ #if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ (_MSC_FULL_VER < 193131103) /* * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 */ __declspec(noinline) #endif int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign) { int ret = 0; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); { mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign); X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s); mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign); mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign); for (size_t i = Y->n; i < X->n; i++) { X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]); } } cleanup: return ret; } /* * Conditionally swap X and Y, without leaking information * about whether the swap was made or not. * Here it is not ok to simply swap the pointers, which would lead to * different memory access patterns when X and Y are used afterwards. */ int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap) { int ret = 0; int s; if (X == Y) { return 0; } mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n)); s = X->s; X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s); Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s); mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap); cleanup: return ret; } /* Implementation that should never be optimized out by the compiler */ #define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n)) /* * Initialize one MPI */ void mbedtls_mpi_init(mbedtls_mpi *X) { X->s = 1; X->n = 0; X->p = NULL; } /* * Unallocate one MPI */ void mbedtls_mpi_free(mbedtls_mpi *X) { if (X == NULL) { return; } if (X->p != NULL) { mbedtls_mpi_zeroize_and_free(X->p, X->n); } X->s = 1; X->n = 0; X->p = NULL; } /* * Enlarge to the specified number of limbs */ int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs) { mbedtls_mpi_uint *p; if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } if (X->n < nblimbs) { if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL)) == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } if (X->p != NULL) { memcpy(p, X->p, X->n * ciL); mbedtls_mpi_zeroize_and_free(X->p, X->n); } /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ X->n = (unsigned short) nblimbs; X->p = p; } return 0; } /* * Resize down as much as possible, * while keeping at least the specified number of limbs */ int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs) { mbedtls_mpi_uint *p; size_t i; if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } /* Actually resize up if there are currently fewer than nblimbs limbs. */ if (X->n <= nblimbs) { return mbedtls_mpi_grow(X, nblimbs); } /* After this point, then X->n > nblimbs and in particular X->n > 0. */ for (i = X->n - 1; i > 0; i--) { if (X->p[i] != 0) { break; } } i++; if (i < nblimbs) { i = nblimbs; } if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } if (X->p != NULL) { memcpy(p, X->p, i * ciL); mbedtls_mpi_zeroize_and_free(X->p, X->n); } /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ X->n = (unsigned short) i; X->p = p; return 0; } /* Resize X to have exactly n limbs and set it to 0. */ static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs) { if (limbs == 0) { mbedtls_mpi_free(X); return 0; } else if (X->n == limbs) { memset(X->p, 0, limbs * ciL); X->s = 1; return 0; } else { mbedtls_mpi_free(X); return mbedtls_mpi_grow(X, limbs); } } /* * Copy the contents of Y into X. * * This function is not constant-time. Leading zeros in Y may be removed. * * Ensure that X does not shrink. This is not guaranteed by the public API, * but some code in the bignum module might still rely on this property. */ int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y) { int ret = 0; size_t i; if (X == Y) { return 0; } if (Y->n == 0) { if (X->n != 0) { X->s = 1; memset(X->p, 0, X->n * ciL); } return 0; } for (i = Y->n - 1; i > 0; i--) { if (Y->p[i] != 0) { break; } } i++; X->s = Y->s; if (X->n < i) { MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i)); } else { memset(X->p + i, 0, (X->n - i) * ciL); } memcpy(X->p, Y->p, i * ciL); cleanup: return ret; } /* * Swap the contents of X and Y */ void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y) { mbedtls_mpi T; memcpy(&T, X, sizeof(mbedtls_mpi)); memcpy(X, Y, sizeof(mbedtls_mpi)); memcpy(Y, &T, sizeof(mbedtls_mpi)); } static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z) { if (z >= 0) { return z; } /* Take care to handle the most negative value (-2^(biL-1)) correctly. * A naive -z would have undefined behavior. * Write this in a way that makes popular compilers happy (GCC, Clang, * MSVC). */ return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z; } /* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative. * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */ #define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1) /* * Set value from integer */ int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1)); memset(X->p, 0, X->n * ciL); X->p[0] = mpi_sint_abs(z); X->s = TO_SIGN(z); cleanup: return ret; } /* * Get a specific bit */ int mbedtls_mpi_get_bit(const mbedtls_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 mbedtls_mpi_set_bit(mbedtls_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 MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (X->n * biL <= pos) { if (val == 0) { return 0; } MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1)); } X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx); X->p[off] |= (mbedtls_mpi_uint) val << idx; cleanup: return ret; } /* * Return the number of less significant zero-bits */ size_t mbedtls_mpi_lsb(const mbedtls_mpi *X) { size_t i; #if defined(__has_builtin) #if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz) #define mbedtls_mpi_uint_ctz __builtin_ctz #elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl) #define mbedtls_mpi_uint_ctz __builtin_ctzl #elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll) #define mbedtls_mpi_uint_ctz __builtin_ctzll #endif #endif #if defined(mbedtls_mpi_uint_ctz) for (i = 0; i < X->n; i++) { if (X->p[i] != 0) { return i * biL + mbedtls_mpi_uint_ctz(X->p[i]); } } #else size_t count = 0; for (i = 0; i < X->n; i++) { for (size_t j = 0; j < biL; j++, count++) { if (((X->p[i] >> j) & 1) != 0) { return count; } } } #endif return 0; } /* * Return the number of bits */ size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X) { return mbedtls_mpi_core_bitlen(X->p, X->n); } /* * Return the total size in bytes */ size_t mbedtls_mpi_size(const mbedtls_mpi *X) { return (mbedtls_mpi_bitlen(X) + 7) >> 3; } /* * Convert an ASCII character to digit value */ static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c) { *d = 255; if (c >= 0x30 && c <= 0x39) { *d = c - 0x30; } if (c >= 0x41 && c <= 0x46) { *d = c - 0x37; } if (c >= 0x61 && c <= 0x66) { *d = c - 0x57; } if (*d >= (mbedtls_mpi_uint) radix) { return MBEDTLS_ERR_MPI_INVALID_CHARACTER; } return 0; } /* * Import from an ASCII string */ int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, j, slen, n; int sign = 1; mbedtls_mpi_uint d; mbedtls_mpi T; if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_init(&T); if (s[0] == 0) { mbedtls_mpi_free(X); return 0; } if (s[0] == '-') { ++s; sign = -1; } slen = strlen(s); if (radix == 16) { if (slen > SIZE_MAX >> 2) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } n = BITS_TO_LIMBS(slen << 2); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); for (i = slen, j = 0; i > 0; i--, j++) { MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1])); X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2); } } else { MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); for (i = 0; i < slen; i++) { MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i])); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d)); } } if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) { X->s = -1; } cleanup: mbedtls_mpi_free(&T); return ret; } /* * Helper to write the digits high-order first. */ static int mpi_write_hlp(mbedtls_mpi *X, int radix, char **p, const size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_uint r; size_t length = 0; char *p_end = *p + buflen; do { if (length >= buflen) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix)); MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix)); /* * Write the residue in the current position, as an ASCII character. */ if (r < 0xA) { *(--p_end) = (char) ('0' + r); } else { *(--p_end) = (char) ('A' + (r - 0xA)); } length++; } while (mbedtls_mpi_cmp_int(X, 0) != 0); memmove(*p, p_end, length); *p += length; cleanup: return ret; } /* * Export into an ASCII string */ int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix, char *buf, size_t buflen, size_t *olen) { int ret = 0; size_t n; char *p; mbedtls_mpi T; if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */ if (radix >= 4) { n >>= 1; /* Number of 4-adic digits necessary to present * `n`. If radix > 4, this might be a strict * overapproximation of the number of * radix-adic digits needed to present `n`. */ } if (radix >= 16) { n >>= 1; /* Number of hexadecimal digits necessary to * present `n`. */ } n += 1; /* Terminating null byte */ n += 1; /* Compensate for the divisions above, which round down `n` * in case it's not even. */ n += 1; /* Potential '-'-sign. */ n += (n & 1); /* Make n even to have enough space for hexadecimal writing, * which always uses an even number of hex-digits. */ if (buflen < n) { *olen = n; return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } p = buf; mbedtls_mpi_init(&T); if (X->s == -1) { *p++ = '-'; buflen--; } if (radix == 16) { int c; size_t i, j, k; for (i = X->n, k = 0; i > 0; i--) { for (j = ciL; j > 0; j--) { c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF; if (c == 0 && k == 0 && (i + j) != 2) { continue; } *(p++) = "0123456789ABCDEF" [c / 16]; *(p++) = "0123456789ABCDEF" [c % 16]; k = 1; } } } else { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X)); if (T.s == -1) { T.s = 1; } MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen)); } *p++ = '\0'; *olen = (size_t) (p - buf); cleanup: mbedtls_mpi_free(&T); return ret; } #if defined(MBEDTLS_FS_IO) /* * Read X from an opened file */ int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin) { mbedtls_mpi_uint d; size_t slen; char *p; /* * Buffer should have space for (short) label and decimal formatted MPI, * newline characters and '\0' */ char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } memset(s, 0, sizeof(s)); if (fgets(s, sizeof(s) - 1, fin) == NULL) { return MBEDTLS_ERR_MPI_FILE_IO_ERROR; } slen = strlen(s); if (slen == sizeof(s) - 2) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } if (slen > 0 && s[slen - 1] == '\n') { slen--; s[slen] = '\0'; } if (slen > 0 && s[slen - 1] == '\r') { slen--; s[slen] = '\0'; } p = s + slen; while (p-- > s) { if (mpi_get_digit(&d, radix, *p) != 0) { break; } } return mbedtls_mpi_read_string(X, radix, p + 1); } /* * Write X into an opened file (or stdout if fout == NULL) */ int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n, slen, plen; /* * Buffer should have space for (short) label and decimal formatted MPI, * newline characters and '\0' */ char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } memset(s, 0, sizeof(s)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n)); if (p == NULL) { p = ""; } plen = strlen(p); slen = strlen(s); s[slen++] = '\r'; s[slen++] = '\n'; if (fout != NULL) { if (fwrite(p, 1, plen, fout) != plen || fwrite(s, 1, slen, fout) != slen) { return MBEDTLS_ERR_MPI_FILE_IO_ERROR; } } else { mbedtls_printf("%s%s", p, s); } cleanup: return ret; } #endif /* MBEDTLS_FS_IO */ /* * Import X from unsigned binary data, little endian * * This function is guaranteed to return an MPI with exactly the necessary * number of limbs (in particular, it does not skip 0s in the input). */ int mbedtls_mpi_read_binary_le(mbedtls_mpi *X, const unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t limbs = CHARS_TO_LIMBS(buflen); /* Ensure that target MPI has exactly the necessary number of limbs */ MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen)); cleanup: /* * This function is also used to import keys. However, wiping the buffers * upon failure is not necessary because failure only can happen before any * input is copied. */ return ret; } /* * Import X from unsigned binary data, big endian * * This function is guaranteed to return an MPI with exactly the necessary * number of limbs (in particular, it does not skip 0s in the input). */ int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t limbs = CHARS_TO_LIMBS(buflen); /* Ensure that target MPI has exactly the necessary number of limbs */ MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen)); cleanup: /* * This function is also used to import keys. However, wiping the buffers * upon failure is not necessary because failure only can happen before any * input is copied. */ return ret; } /* * Export X into unsigned binary data, little endian */ int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X, unsigned char *buf, size_t buflen) { return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen); } /* * Export X into unsigned binary data, big endian */ int mbedtls_mpi_write_binary(const mbedtls_mpi *X, unsigned char *buf, size_t buflen) { return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen); } /* * Left-shift: X <<= count */ int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; i = mbedtls_mpi_bitlen(X) + count; if (X->n * biL < i) { MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i))); } ret = 0; mbedtls_mpi_core_shift_l(X->p, X->n, count); cleanup: return ret; } /* * Right-shift: X >>= count */ int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count) { if (X->n != 0) { mbedtls_mpi_core_shift_r(X->p, X->n, count); } return 0; } /* * Compare unsigned values */ int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_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 == j == 0, i.e. abs(X) == abs(Y), * we end up returning 0 at the end of the function. */ 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 mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_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 mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z) { mbedtls_mpi Y; mbedtls_mpi_uint p[1]; *p = mpi_sint_abs(z); Y.s = TO_SIGN(z); Y.n = 1; Y.p = p; return mbedtls_mpi_cmp_mpi(X, &Y); } /* * Unsigned addition: X = |A| + |B| (HAC 14.7) */ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t j; mbedtls_mpi_uint *p; mbedtls_mpi_uint c; if (X == B) { const mbedtls_mpi *T = A; A = X; B = T; } if (X != A) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); } /* * X must 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; } } /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0 * and B is 0 (of any size). */ if (j == 0) { return 0; } MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j)); /* j is the number of non-zero limbs of B. Add those to X. */ p = X->p; c = mbedtls_mpi_core_add(p, p, B->p, j); p += j; /* Now propagate any carry */ while (c != 0) { if (j >= X->n) { MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1)); p = X->p + j; } *p += c; c = (*p < c); j++; p++; } cleanup: return ret; } /* * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) */ int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; mbedtls_mpi_uint carry; for (n = B->n; n > 0; n--) { if (B->p[n - 1] != 0) { break; } } if (n > A->n) { /* B >= (2^ciL)^n > A */ ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n)); /* Set the high limbs of X to match A. Don't touch the lower limbs * because X might be aliased to B, and we must not overwrite the * significant digits of B. */ if (A->n > n && A != X) { memcpy(X->p + n, A->p + n, (A->n - n) * ciL); } if (X->n > A->n) { memset(X->p + A->n, 0, (X->n - A->n) * ciL); } carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n); if (carry != 0) { /* Propagate the carry through the rest of X. */ carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n); /* If we have further carry/borrow, the result is negative. */ if (carry != 0) { ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; goto cleanup; } } /* X should always be positive as a result of unsigned subtractions. */ X->s = 1; cleanup: return ret; } /* Common function for signed addition and subtraction. * Calculate A + B * flip_B where flip_B is 1 or -1. */ static int add_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B, int flip_B) { int ret, s; s = A->s; if (A->s * B->s * flip_B < 0) { int cmp = mbedtls_mpi_cmp_abs(A, B); if (cmp >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B)); /* If |A| = |B|, the result is 0 and we must set the sign bit * to +1 regardless of which of A or B was negative. Otherwise, * since |A| > |B|, the sign is the sign of A. */ X->s = cmp == 0 ? 1 : s; } else { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A)); /* Since |A| < |B|, the sign is the opposite of A. */ X->s = -s; } } else { MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B)); X->s = s; } cleanup: return ret; } /* * Signed addition: X = A + B */ int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { return add_sub_mpi(X, A, B, 1); } /* * Signed subtraction: X = A - B */ int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { return add_sub_mpi(X, A, B, -1); } /* * Signed addition: X = A + b */ int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b) { mbedtls_mpi B; mbedtls_mpi_uint p[1]; p[0] = mpi_sint_abs(b); B.s = TO_SIGN(b); B.n = 1; B.p = p; return mbedtls_mpi_add_mpi(X, A, &B); } /* * Signed subtraction: X = A - b */ int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b) { mbedtls_mpi B; mbedtls_mpi_uint p[1]; p[0] = mpi_sint_abs(b); B.s = TO_SIGN(b); B.n = 1; B.p = p; return mbedtls_mpi_sub_mpi(X, A, &B); } /* * Baseline multiplication: X = A * B (HAC 14.12) */ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, j; mbedtls_mpi TA, TB; int result_is_zero = 0; mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB); if (X == A) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA; } if (X == B) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB; } for (i = A->n; i > 0; i--) { if (A->p[i - 1] != 0) { break; } } if (i == 0) { result_is_zero = 1; } for (j = B->n; j > 0; j--) { if (B->p[j - 1] != 0) { break; } } if (j == 0) { result_is_zero = 1; } MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j); /* If the result is 0, we don't shortcut the operation, which reduces * but does not eliminate side channels leaking the zero-ness. We do * need to take care to set the sign bit properly since the library does * not fully support an MPI object with a value of 0 and s == -1. */ if (result_is_zero) { X->s = 1; } else { X->s = A->s * B->s; } cleanup: mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA); return ret; } /* * Baseline multiplication: X = A * b */ int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b) { size_t n = A->n; while (n > 0 && A->p[n - 1] == 0) { --n; } /* The general method below doesn't work if b==0. */ if (b == 0 || n == 0) { return mbedtls_mpi_lset(X, 0); } /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* In general, A * b requires 1 limb more than b. If * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same * number of limbs as A and the call to grow() is not required since * copy() will take care of the growth if needed. However, experimentally, * making the call to grow() unconditional causes slightly fewer * calls to calloc() in ECP code, presumably because it reuses the * same mpi for a while and this way the mpi is more likely to directly * grow to its final size. * * Note that calculating A*b as 0 + A*b doesn't work as-is because * A,X can be the same. */ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1); cleanup: return ret; } /* * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and * mbedtls_mpi_uint divisor, d */ static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1, mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r) { #if defined(MBEDTLS_HAVE_UDBL) mbedtls_t_udbl dividend, quotient; #else const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1; mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; mbedtls_mpi_uint u0_msw, u0_lsw; size_t s; #endif /* * Check for overflow */ if (0 == d || u1 >= d) { if (r != NULL) { *r = ~(mbedtls_mpi_uint) 0u; } return ~(mbedtls_mpi_uint) 0u; } #if defined(MBEDTLS_HAVE_UDBL) dividend = (mbedtls_t_udbl) u1 << biL; dividend |= (mbedtls_t_udbl) u0; quotient = dividend / d; if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) { quotient = ((mbedtls_t_udbl) 1 << biL) - 1; } if (r != NULL) { *r = (mbedtls_mpi_uint) (dividend - (quotient * d)); } return (mbedtls_mpi_uint) quotient; #else /* * Algorithm D, Section 4.3.1 - The Art of Computer Programming * Vol. 2 - Seminumerical Algorithms, Knuth */ /* * Normalize the divisor, d, and dividend, u0, u1 */ s = mbedtls_mpi_core_clz(d); d = d << s; u1 = u1 << s; u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1)); u0 = u0 << s; d1 = d >> biH; d0 = d & uint_halfword_mask; u0_msw = u0 >> biH; u0_lsw = u0 & uint_halfword_mask; /* * Find the first quotient and remainder */ q1 = u1 / d1; r0 = u1 - d1 * q1; while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) { q1 -= 1; r0 += d1; if (r0 >= radix) { break; } } rAX = (u1 * radix) + (u0_msw - q1 * d); q0 = rAX / d1; r0 = rAX - q0 * d1; while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) { q0 -= 1; r0 += d1; if (r0 >= radix) { break; } } if (r != NULL) { *r = (rAX * radix + u0_lsw - q0 * d) >> s; } quotient = q1 * radix + q0; return quotient; #endif } /* * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) */ int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, n, t, k; mbedtls_mpi X, Y, Z, T1, T2; mbedtls_mpi_uint TP2[3]; if (mbedtls_mpi_cmp_int(B, 0) == 0) { return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; } mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&Z); mbedtls_mpi_init(&T1); /* * Avoid dynamic memory allocations for constant-size T2. * * T2 is used for comparison only and the 3 limbs are assigned explicitly, * so nobody increase the size of the MPI and we're safe to use an on-stack * buffer. */ T2.s = 1; T2.n = sizeof(TP2) / sizeof(*TP2); T2.p = TP2; if (mbedtls_mpi_cmp_abs(A, B) < 0) { if (Q != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0)); } if (R != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A)); } return 0; } MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B)); X.s = Y.s = 1; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2)); k = mbedtls_mpi_bitlen(&Y) % biL; if (k < biL - 1) { k = biL - 1 - k; MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k)); } else { k = 0; } n = X.n - 1; t = Y.n - 1; MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t))); while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) { Z.p[n - t]++; MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y)); } MBEDTLS_MPI_CHK(mbedtls_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] = ~(mbedtls_mpi_uint) 0u; } else { Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1], Y.p[t], NULL); } 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]; Z.p[i - t - 1]++; do { Z.p[i - t - 1]--; MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0)); T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; T1.p[1] = Y.p[t]; MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1])); } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1])); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1))); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1)); if (mbedtls_mpi_cmp_int(&X, 0) < 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1))); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1)); Z.p[i - t - 1]--; } } if (Q != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z)); Q->s = A->s * B->s; } if (R != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k)); X.s = A->s; MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X)); if (mbedtls_mpi_cmp_int(R, 0) == 0) { R->s = 1; } } cleanup: mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z); mbedtls_mpi_free(&T1); mbedtls_platform_zeroize(TP2, sizeof(TP2)); return ret; } /* * Division by int: A = Q * b + R */ int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b) { mbedtls_mpi B; mbedtls_mpi_uint p[1]; p[0] = mpi_sint_abs(b); B.s = TO_SIGN(b); B.n = 1; B.p = p; return mbedtls_mpi_div_mpi(Q, R, A, &B); } /* * Modulo: R = A mod B */ int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (mbedtls_mpi_cmp_int(B, 0) < 0) { return MBEDTLS_ERR_MPI_NEGATIVE_VALUE; } MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B)); while (mbedtls_mpi_cmp_int(R, 0) < 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B)); } while (mbedtls_mpi_cmp_mpi(R, B) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B)); } cleanup: return ret; } /* * Modulo: r = A mod b */ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b) { size_t i; mbedtls_mpi_uint x, y, z; if (b == 0) { return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; } if (b < 0) { return MBEDTLS_ERR_MPI_NEGATIVE_VALUE; } /* * handle trivial cases */ if (b == 1 || A->n == 0) { *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; } /* * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value, * this function is not constant time with respect to the exponent (parameter E). */ static int mbedtls_mpi_exp_mod_optionally_safe(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, int E_public, const mbedtls_mpi *N, mbedtls_mpi *prec_RR) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_cmp_int(E, 0) < 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS || mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* * Ensure that the exponent that we are passing to the core is not NULL. */ if (E->n == 0) { ret = mbedtls_mpi_lset(X, 1); return ret; } /* * Allocate working memory for mbedtls_mpi_core_exp_mod() */ size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n); mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint)); if (T == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } mbedtls_mpi RR; mbedtls_mpi_init(&RR); /* * If 1st call, pre-compute R^2 mod N */ if (prec_RR == NULL || prec_RR->p == NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N)); if (prec_RR != NULL) { *prec_RR = RR; } } else { MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n)); RR = *prec_RR; } /* * To preserve constness we need to make a copy of A. Using X for this to * save memory. */ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); /* * Compensate for negative A (and correct at the end). */ X->s = 1; /* * Make sure that X is in a form that is safe for consumption by * the core functions. * * - The core functions will not touch the limbs of X above N->n. The * result will be correct if those limbs are 0, which the mod call * ensures. * - Also, X must have at least as many limbs as N for the calls to the * core functions. */ if (mbedtls_mpi_cmp_mpi(X, N) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N)); } MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n)); /* * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod(). */ { mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p); mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T); if (E_public == MBEDTLS_MPI_IS_PUBLIC) { mbedtls_mpi_core_exp_mod_unsafe(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T); } else { mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T); } mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T); } /* * Correct for negative A. */ if (A->s == -1 && (E->p[0] & 1) != 0) { mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n); X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X)); } cleanup: mbedtls_mpi_zeroize_and_free(T, T_limbs); if (prec_RR == NULL || prec_RR->p == NULL) { mbedtls_mpi_free(&RR); } return ret; } int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *prec_RR) { return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_SECRET, N, prec_RR); } int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *prec_RR) { return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_PUBLIC, N, prec_RR); } /* * Greatest common divisor: G = gcd(A, B) (HAC 14.54) */ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t lz, lzt; mbedtls_mpi TA, TB; mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); lz = mbedtls_mpi_lsb(&TA); lzt = mbedtls_mpi_lsb(&TB); /* The loop below gives the correct result when A==0 but not when B==0. * So have a special case for B==0. Leverage the fact that we just * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test * slightly more efficient than cmp_int(). */ if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) { ret = mbedtls_mpi_copy(G, A); goto cleanup; } if (lzt < lz) { lz = lzt; } TA.s = TB.s = 1; /* We mostly follow the procedure described in HAC 14.54, but with some * minor differences: * - Sequences of multiplications or divisions by 2 are grouped into a * single shift operation. * - The procedure in HAC assumes that 0 < TB <= TA. * - The condition TB <= TA is not actually necessary for correctness. * TA and TB have symmetric roles except for the loop termination * condition, and the shifts at the beginning of the loop body * remove any significance from the ordering of TA vs TB before * the shifts. * - If TA = 0, the loop goes through 0 iterations and the result is * correctly TB. * - The case TB = 0 was short-circuited above. * * For the correctness proof below, decompose the original values of * A and B as * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'), * and gcd(A',B') is odd or 0. * * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB). * The code maintains the following invariant: * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I) */ /* Proof that the loop terminates: * At each iteration, either the right-shift by 1 is made on a nonzero * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases * by at least 1, or the right-shift by 1 is made on zero and then * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted * since in that case TB is calculated from TB-TA with the condition TB>TA). */ while (mbedtls_mpi_cmp_int(&TA, 0) != 0) { /* Divisions by 2 preserve the invariant (I). */ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA))); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB))); /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd, * TA-TB is even so the division by 2 has an integer result. * Invariant (I) is preserved since any odd divisor of both TA and TB * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also * divides TA. */ if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1)); } else { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1)); } /* Note that one of TA or TB is still odd. */ } /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k. * At the loop exit, TA = 0, so gcd(TA,TB) = TB. * - If there was at least one loop iteration, then one of TA or TB is odd, * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case, * lz = min(a,b) so gcd(A,B) = 2^lz * TB. * - If there was no loop iteration, then A was 0, and gcd(A,B) = B. * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well. */ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB)); cleanup: mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB); return ret; } /* * Fill X with size bytes of random. * The bytes returned from the RNG are used in a specific order which * is suitable for deterministic ECDSA (see the specification of * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()). */ int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t limbs = CHARS_TO_LIMBS(size); /* Ensure that target MPI has exactly the necessary number of limbs */ MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); if (size == 0) { return 0; } ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng); cleanup: return ret; } int mbedtls_mpi_random(mbedtls_mpi *X, mbedtls_mpi_sint min, const mbedtls_mpi *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (min < 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_cmp_int(N, min) <= 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* Ensure that target MPI has exactly the same number of limbs * as the upper bound, even if the upper bound has leading zeros. * This is necessary for mbedtls_mpi_core_random. */ int ret = mbedtls_mpi_resize_clear(X, N->n); if (ret != 0) { return ret; } return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng); } /* * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) */ int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; if (mbedtls_mpi_cmp_int(N, 1) <= 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TU); mbedtls_mpi_init(&U1); mbedtls_mpi_init(&U2); mbedtls_mpi_init(&G); mbedtls_mpi_init(&TB); mbedtls_mpi_init(&TV); mbedtls_mpi_init(&V1); mbedtls_mpi_init(&V2); MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N)); if (mbedtls_mpi_cmp_int(&G, 1) != 0) { ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1)); do { while ((TU.p[0] & 1) == 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1)); if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA)); } MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1)); } while ((TV.p[0] & 1) == 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1)); if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA)); } MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1)); } if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2)); } else { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2)); } } while (mbedtls_mpi_cmp_int(&TU, 0) != 0); while (mbedtls_mpi_cmp_int(&V1, 0) < 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N)); } while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N)); } MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1)); cleanup: mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2); mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV); mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2); return ret; } #if defined(MBEDTLS_GENPRIME) /* Gaps between primes, starting at 3. https://oeis.org/A001223 */ static const unsigned char small_prime_gaps[] = { 2, 2, 4, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2, 4, 14, 4, 6, 2, 10, 2, 6, 6, 4, 6, 6, 2, 10, 2, 4, 2, 12, 12, 4, 2, 4, 6, 2, 10, 6, 6, 6, 2, 6, 4, 2, 10, 14, 4, 2, 4, 14, 6, 10, 2, 4, 6, 8, 6, 6, 4, 6, 8, 4, 8, 10, 2, 10, 2, 6, 4, 6, 8, 4, 2, 4, 12, 8, 4, 8, 4, 6, 12, 2, 18, 6, 10, 6, 6, 2, 6, 10, 6, 6, 2, 6, 6, 4, 2, 12, 10, 2, 4, 6, 6, 2, 12, 4, 6, 8, 10, 8, 10, 8, 6, 6, 4, 8, 6, 4, 8, 4, 14, 10, 12, 2, 10, 2, 4, 2, 10, 14, 4, 2, 4, 14, 4, 2, 4, 20, 4, 8, 10, 8, 4, 6, 6, 14, 4, 6, 6, 8, 6, /*reaches 997*/ 0 /* the last entry is effectively unused */ }; /* * Small divisors test (X must be positive) * * Return values: * 0: no small factor (possible prime, more tests needed) * 1: certain prime * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime * other negative: error */ static int mpi_check_small_factors(const mbedtls_mpi *X) { int ret = 0; size_t i; mbedtls_mpi_uint r; unsigned p = 3; /* The first odd prime */ if ((X->p[0] & 1) == 0) { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) { MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p)); if (r == 0) { if (mbedtls_mpi_cmp_int(X, p) == 0) { return 1; } else { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } } } cleanup: return ret; } /* * Miller-Rabin pseudo-primality test (HAC 4.24) */ static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, count; size_t i, j, k, s; mbedtls_mpi W, R, T, A, RR; mbedtls_mpi_init(&W); mbedtls_mpi_init(&R); mbedtls_mpi_init(&T); mbedtls_mpi_init(&A); mbedtls_mpi_init(&RR); /* * W = |X| - 1 * R = W >> lsb( W ) */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1)); s = mbedtls_mpi_lsb(&W); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s)); for (i = 0; i < rounds; i++) { /* * pick a random A, 1 < A < |X| - 1 */ count = 0; do { MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng)); j = mbedtls_mpi_bitlen(&A); k = mbedtls_mpi_bitlen(&W); if (j > k) { A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1; } if (count++ > 30) { ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; goto cleanup; } } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 || mbedtls_mpi_cmp_int(&A, 1) <= 0); /* * A = A^R mod |X| */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR)); if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 || mbedtls_mpi_cmp_int(&A, 1) == 0) { continue; } j = 1; while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) { /* * A = A * A mod |X| */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X)); if (mbedtls_mpi_cmp_int(&A, 1) == 0) { break; } j++; } /* * not prime if A != |X| - 1 or A == 1 */ if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 || mbedtls_mpi_cmp_int(&A, 1) == 0) { ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; break; } } cleanup: mbedtls_mpi_free(&W); mbedtls_mpi_free(&R); mbedtls_mpi_free(&T); mbedtls_mpi_free(&A); mbedtls_mpi_free(&RR); return ret; } /* * Pseudo-primality test: small factors, then Miller-Rabin */ int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi XX; XX.s = 1; XX.n = X->n; XX.p = X->p; if (mbedtls_mpi_cmp_int(&XX, 0) == 0 || mbedtls_mpi_cmp_int(&XX, 1) == 0) { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } if (mbedtls_mpi_cmp_int(&XX, 2) == 0) { return 0; } if ((ret = mpi_check_small_factors(&XX)) != 0) { if (ret == 1) { return 0; } return ret; } return mpi_miller_rabin(&XX, rounds, f_rng, p_rng); } /* * Prime number generation * * To generate an RSA key in a way recommended by FIPS 186-4, both primes must * be either 1024 bits or 1536 bits long, and flags must contain * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. */ int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #ifdef MBEDTLS_HAVE_INT64 // ceil(2^63.5) #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL #else // ceil(2^31.5) #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U #endif int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; size_t k, n; int rounds; mbedtls_mpi_uint r; mbedtls_mpi Y; if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_init(&Y); n = BITS_TO_LIMBS(nbits); if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) { /* * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 */ rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 : (nbits >= 650) ? 4 : (nbits >= 350) ? 8 : (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27); } else { /* * 2^-100 error probability, number of rounds computed based on HAC, * fact 4.48 */ rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 : (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 : (nbits >= 750) ? 8 : (nbits >= 500) ? 13 : (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51); } while (1) { MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng)); /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) { continue; } k = n * biL; if (k > nbits) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits)); } X->p[0] |= 1; if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) { ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng); if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { goto cleanup; } } else { /* * A necessary condition for Y and X = 2Y + 1 to be prime * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). * Make sure it is satisfied, while keeping X = 3 mod 4 */ X->p[0] |= 2; MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3)); if (r == 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8)); } else if (r == 1) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4)); } /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1)); while (1) { /* * First, check small factors for X and Y * before doing Miller-Rabin on any of them */ if ((ret = mpi_check_small_factors(X)) == 0 && (ret = mpi_check_small_factors(&Y)) == 0 && (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng)) == 0 && (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng)) == 0) { goto cleanup; } if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { goto cleanup; } /* * Next candidates. We want to preserve Y = (X-1) / 2 and * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) * so up Y by 6 and X by 12. */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6)); } } } cleanup: mbedtls_mpi_free(&Y); return ret; } #endif /* MBEDTLS_GENPRIME */ #if defined(MBEDTLS_SELF_TEST) #define GCD_PAIR_COUNT 3 static const int gcd_pairs[GCD_PAIR_COUNT][3] = { { 693, 609, 21 }, { 1764, 868, 28 }, { 768454923, 542167814, 1 } }; /* * Checkup routine */ int mbedtls_mpi_self_test(int verbose) { int ret, i; mbedtls_mpi A, E, N, X, Y, U, V; mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N); mbedtls_mpi_init(&X); mbedtls_mpi_init(&Y); mbedtls_mpi_init(&U); mbedtls_mpi_init(&V); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16, "EFE021C2645FD1DC586E69184AF4A31E" \ "D5F53E93B5F123FA41680867BA110131" \ "944FE7952E2517337780CB0DB80E61AA" \ "E7C8DDC6C5C6AADEB34EB38A2F40D5E6")); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16, "B2E7EFD37075B9F03FF989C7C5051C20" \ "34D2A323810251127E7BF8625A4F49A5" \ "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ "5B5C25763222FEFCCFC38B832366C29E")); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16, "0066A198186C18C10B2F5ED9B522752A" \ "9830B69916E535C8F047518A889A43A5" \ "94B6BED27A168D31D4A52F88925AA8F5")); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, "602AB7ECA597A3D6B56FF9829A5E8B85" \ "9E857EA95A03512E2BAE7391688D264A" \ "A5663B0341DB9CCFD2C4C5F421FEC814" \ "8001B72E848A38CAE1C65F78E56ABDEF" \ "E12D3C039B8A02D6BE593F0BBBDA56F1" \ "ECF677152EF804370C1A305CAF3B5BF1" \ "30879B56C61DE584A0F53A2447A51E")); if (verbose != 0) { mbedtls_printf(" MPI test #1 (mul_mpi): "); } if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, "256567336059E52CAE22925474705F39A94")); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16, "6613F26162223DF488E9CD48CC132C7A" \ "0AC93C701B001B092E4E5B9F73BCD27B" \ "9EE50D0657C77F374E903CDFA4C642")); if (verbose != 0) { mbedtls_printf(" MPI test #2 (div_mpi): "); } if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 || mbedtls_mpi_cmp_mpi(&Y, &V) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, "36E139AEA55215609D2816998ED020BB" \ "BD96C37890F65171D948E9BC7CBAA4D9" \ "325D24D6A3C12710F10A09FA08AB87")); if (verbose != 0) { mbedtls_printf(" MPI test #3 (exp_mod): "); } if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ "C3DBA76456363A10869622EAC2DD84EC" \ "C5B8A74DAC4D09E03B5E0BE779F2DF61")); if (verbose != 0) { mbedtls_printf(" MPI test #4 (inv_mod): "); } if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf(" MPI test #5 (simple gcd): "); } for (i = 0; i < GCD_PAIR_COUNT; i++) { MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0])); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1])); MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y)); if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) { if (verbose != 0) { mbedtls_printf("failed at %d\n", i); } ret = 1; goto cleanup; } } if (verbose != 0) { mbedtls_printf("passed\n"); } cleanup: if (ret != 0 && verbose != 0) { mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret); } mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V); if (verbose != 0) { mbedtls_printf("\n"); } return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_BIGNUM_C */ webfakes/src/mbedtls/library/ecjpake.c0000644000176200001440000012171614740737024017514 0ustar liggesusers/* * Elliptic curve J-PAKE * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References in the code are to the Thread v1.0 Specification, * available to members of the Thread Group http://threadgroup.org/ */ #include "common.h" #if defined(MBEDTLS_ECJPAKE_C) #include "mbedtls/ecjpake.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if !defined(MBEDTLS_ECJPAKE_ALT) /* * Convert a mbedtls_ecjpake_role to identifier string */ static const char * const ecjpake_id[] = { "client", "server" }; #define ID_MINE (ecjpake_id[ctx->role]) #define ID_PEER (ecjpake_id[1 - ctx->role]) /** * Helper to Compute a hash from md_type */ static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type, const unsigned char *input, size_t ilen, unsigned char *output) { return mbedtls_md(mbedtls_md_info_from_type(md_type), input, ilen, output); } /* * Initialize context */ void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx) { ctx->md_type = MBEDTLS_MD_NONE; mbedtls_ecp_group_init(&ctx->grp); ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; mbedtls_ecp_point_init(&ctx->Xm1); mbedtls_ecp_point_init(&ctx->Xm2); mbedtls_ecp_point_init(&ctx->Xp1); mbedtls_ecp_point_init(&ctx->Xp2); mbedtls_ecp_point_init(&ctx->Xp); mbedtls_mpi_init(&ctx->xm1); mbedtls_mpi_init(&ctx->xm2); mbedtls_mpi_init(&ctx->s); } /* * Free context */ void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx) { if (ctx == NULL) { return; } ctx->md_type = MBEDTLS_MD_NONE; mbedtls_ecp_group_free(&ctx->grp); mbedtls_ecp_point_free(&ctx->Xm1); mbedtls_ecp_point_free(&ctx->Xm2); mbedtls_ecp_point_free(&ctx->Xp1); mbedtls_ecp_point_free(&ctx->Xp2); mbedtls_ecp_point_free(&ctx->Xp); mbedtls_mpi_free(&ctx->xm1); mbedtls_mpi_free(&ctx->xm2); mbedtls_mpi_free(&ctx->s); } /* * Setup context */ int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx, mbedtls_ecjpake_role role, mbedtls_md_type_t hash, mbedtls_ecp_group_id curve, const unsigned char *secret, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } ctx->role = role; if ((mbedtls_md_info_from_type(hash)) == NULL) { return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; } ctx->md_type = hash; MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len)); cleanup: if (ret != 0) { mbedtls_ecjpake_free(ctx); } return ret; } int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx, int point_format) { switch (point_format) { case MBEDTLS_ECP_PF_UNCOMPRESSED: case MBEDTLS_ECP_PF_COMPRESSED: ctx->point_format = point_format; return 0; default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } } /* * Check if context is ready for use */ int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx) { if (ctx->md_type == MBEDTLS_MD_NONE || ctx->grp.id == MBEDTLS_ECP_DP_NONE || ctx->s.p == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return 0; } /* * Write a point plus its length to a buffer */ static int ecjpake_write_len_point(unsigned char **p, const unsigned char *end, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *P) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* Need at least 4 for length plus 1 for point */ if (end < *p || end - *p < 5) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } ret = mbedtls_ecp_point_write_binary(grp, P, pf, &len, *p + 4, (size_t) (end - (*p + 4))); if (ret != 0) { return ret; } MBEDTLS_PUT_UINT32_BE(len, *p, 0); *p += 4 + len; return 0; } /* * Size of the temporary buffer for ecjpake_hash: * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) */ #define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6) /* * Compute hash for ZKP (7.4.2.2.2.1) */ static int ecjpake_hash(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, const mbedtls_ecp_point *V, const mbedtls_ecp_point *X, const char *id, mbedtls_mpi *h) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[ECJPAKE_HASH_BUF_LEN]; unsigned char *p = buf; const unsigned char *end = buf + sizeof(buf); const size_t id_len = strlen(id); unsigned char hash[MBEDTLS_MD_MAX_SIZE]; /* Write things to temporary buffer */ MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G)); MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V)); MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X)); if (end - p < 4) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } MBEDTLS_PUT_UINT32_BE(id_len, p, 0); p += 4; if (end < p || (size_t) (end - p) < id_len) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } memcpy(p, id, id_len); p += id_len; /* Compute hash */ MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type, buf, (size_t) (p - buf), hash)); /* Turn it into an integer mod n */ MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash, mbedtls_md_get_size_from_type(md_type))); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N)); cleanup: return ret; } /* * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) */ static int ecjpake_zkp_read(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, const mbedtls_ecp_point *X, const char *id, const unsigned char **p, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point V, VV; mbedtls_mpi r, h; size_t r_len; mbedtls_ecp_point_init(&V); mbedtls_ecp_point_init(&VV); mbedtls_mpi_init(&r); mbedtls_mpi_init(&h); /* * struct { * ECPoint V; * opaque r<1..2^8-1>; * } ECSchnorrZKP; */ if (end < *p) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p))); if (end < *p || (size_t) (end - *p) < 1) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } r_len = *(*p)++; if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len)); *p += r_len; /* * Verification */ MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h)); MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp, &VV, &h, X, &r, G)); if (mbedtls_ecp_point_cmp(&VV, &V) != 0) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } cleanup: mbedtls_ecp_point_free(&V); mbedtls_ecp_point_free(&VV); mbedtls_mpi_free(&r); mbedtls_mpi_free(&h); return ret; } /* * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) */ static int ecjpake_zkp_write(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, const mbedtls_mpi *x, const mbedtls_ecp_point *X, const char *id, unsigned char **p, const unsigned char *end, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point V; mbedtls_mpi v; mbedtls_mpi h; /* later recycled to hold r */ size_t len; if (end < *p) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } mbedtls_ecp_point_init(&V); mbedtls_mpi_init(&v); mbedtls_mpi_init(&h); /* Compute signature */ MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, &v, &V, f_rng, p_rng)); MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */ MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */ /* Write it out */ MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V, pf, &len, *p, (size_t) (end - *p))); *p += len; len = mbedtls_mpi_size(&h); /* actually r */ if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) { ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; goto cleanup; } *(*p)++ = MBEDTLS_BYTE_0(len); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */ *p += len; cleanup: mbedtls_ecp_point_free(&V); mbedtls_mpi_free(&v); mbedtls_mpi_free(&h); return ret; } /* * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof * Output: verified public key X */ static int ecjpake_kkp_read(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, mbedtls_ecp_point *X, const char *id, const unsigned char **p, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (end < *p) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * struct { * ECPoint X; * ECSchnorrZKP zkp; * } ECJPAKEKeyKP; */ MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p))); if (mbedtls_ecp_is_zero(X)) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end)); cleanup: return ret; } /* * Generate an ECJPAKEKeyKP * Output: the serialized structure, plus private/public key pair */ static int ecjpake_kkp_write(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, mbedtls_mpi *x, mbedtls_ecp_point *X, const char *id, unsigned char **p, const unsigned char *end, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if (end < *p) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } /* Generate key (7.4.2.3.1) and write it out */ MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X, pf, &len, *p, (size_t) (end - *p))); *p += len; /* Generate and write proof */ MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id, p, end, f_rng, p_rng)); cleanup: return ret; } /* * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs * Outputs: verified peer public keys Xa, Xb */ static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, mbedtls_ecp_point *Xa, mbedtls_ecp_point *Xb, const char *id, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; const unsigned char *end = buf + len; /* * struct { * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; * } ECJPAKEKeyKPPairList; */ MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end)); MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end)); if (p != end) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } cleanup: return ret; } /* * Generate a ECJPAKEKeyKPPairList * Outputs: the serialized structure, plus two private/public key pairs */ static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, mbedtls_mpi *xm1, mbedtls_ecp_point *Xa, mbedtls_mpi *xm2, mbedtls_ecp_point *Xb, const char *id, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; const unsigned char *end = buf + len; MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id, &p, end, f_rng, p_rng)); MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id, &p, end, f_rng, p_rng)); *olen = (size_t) (p - buf); cleanup: return ret; } /* * Read and process the first round message */ int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len) { return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->Xp1, &ctx->Xp2, ID_PEER, buf, len); } /* * Generate and write the first round message */ int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, ID_MINE, buf, len, olen, f_rng, p_rng); } /* * Compute the sum of three points R = A + B + C */ static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *A, const mbedtls_ecp_point *B, const mbedtls_ecp_point *C) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi one; mbedtls_mpi_init(&one); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1)); MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B)); MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C)); cleanup: mbedtls_mpi_free(&one); return ret; } /* * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) */ int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; const unsigned char *end = buf + len; mbedtls_ecp_group grp; mbedtls_ecp_point G; /* C: GB, S: GA */ mbedtls_ecp_group_init(&grp); mbedtls_ecp_point_init(&G); /* * Server: GA = X3 + X4 + X1 (7.4.2.6.1) * Client: GB = X1 + X2 + X3 (7.4.2.5.1) * Unified: G = Xm1 + Xm2 + Xp1 * We need that before parsing in order to check Xp as we read it */ MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G, &ctx->Xm1, &ctx->Xm2, &ctx->Xp1)); /* * struct { * ECParameters curve_params; // only client reading server msg * ECJPAKEKeyKP ecjpake_key_kp; * } Client/ServerECJPAKEParams; */ if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) { MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len)); if (grp.id != ctx->grp.id) { ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; goto cleanup; } } MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp, ctx->point_format, &G, &ctx->Xp, ID_PEER, &p, end)); if (p != end) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } cleanup: mbedtls_ecp_group_free(&grp); mbedtls_ecp_point_free(&G); return ret; } /* * Compute R = +/- X * S mod N, taking care not to leak S */ static int ecjpake_mul_secret(mbedtls_mpi *R, int sign, const mbedtls_mpi *X, const mbedtls_mpi *S, const mbedtls_mpi *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi b; /* Blinding value, then s + N * blinding */ mbedtls_mpi_init(&b); /* b = s + rnd-128-bit * N */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S)); /* R = sign * X * b mod N */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b)); R->s *= sign; MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N)); cleanup: mbedtls_mpi_free(&b); return ret; } /* * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) */ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point G; /* C: GA, S: GB */ mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ mbedtls_mpi xm; /* C: xc, S: xs */ unsigned char *p = buf; const unsigned char *end = buf + len; size_t ec_len; mbedtls_ecp_point_init(&G); mbedtls_ecp_point_init(&Xm); mbedtls_mpi_init(&xm); /* * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) * * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G */ MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G, &ctx->Xp1, &ctx->Xp2, &ctx->Xm1)); MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s, &ctx->grp.N, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng)); /* * Now write things out * * struct { * ECParameters curve_params; // only server writing its message * ECJPAKEKeyKP ecjpake_key_kp; * } Client/ServerECJPAKEParams; */ if (ctx->role == MBEDTLS_ECJPAKE_SERVER) { if (end < p) { ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len, p, (size_t) (end - p))); p += ec_len; } if (end < p) { ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm, ctx->point_format, &ec_len, p, (size_t) (end - p))); p += ec_len; MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp, ctx->point_format, &G, &xm, &Xm, ID_MINE, &p, end, f_rng, p_rng)); *olen = (size_t) (p - buf); cleanup: mbedtls_ecp_point_free(&G); mbedtls_ecp_point_free(&Xm); mbedtls_mpi_free(&xm); return ret; } /* * Derive PMS (7.4.2.7 / 7.4.2.8) */ static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx, mbedtls_ecp_point *K, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi m_xm2_s, one; mbedtls_mpi_init(&m_xm2_s); mbedtls_mpi_init(&one); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1)); /* * Client: K = ( Xs - X4 * x2 * s ) * x2 * Server: K = ( Xc - X2 * x4 * s ) * x4 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 */ MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s, &ctx->grp.N, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K, &one, &ctx->Xp, &m_xm2_s, &ctx->Xp2)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K, f_rng, p_rng)); cleanup: mbedtls_mpi_free(&m_xm2_s); mbedtls_mpi_free(&one); return ret; } int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point K; unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; size_t x_bytes; *olen = mbedtls_md_get_size_from_type(ctx->md_type); if (len < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } mbedtls_ecp_point_init(&K); ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng); if (ret) { goto cleanup; } /* PMS = SHA-256( K.X ) */ x_bytes = (ctx->grp.pbits + 7) / 8; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes)); MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type, kx, x_bytes, buf)); cleanup: mbedtls_ecp_point_free(&K); return ret; } int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point K; mbedtls_ecp_point_init(&K); ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng); if (ret) { goto cleanup; } ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format, olen, buf, len); if (ret != 0) { goto cleanup; } cleanup: mbedtls_ecp_point_free(&K); return ret; } #undef ID_MINE #undef ID_PEER #endif /* ! MBEDTLS_ECJPAKE_ALT */ #if defined(MBEDTLS_SELF_TEST) #include "mbedtls/platform.h" #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ !defined(MBEDTLS_MD_CAN_SHA256) int mbedtls_ecjpake_self_test(int verbose) { (void) verbose; return 0; } #else static const unsigned char ecjpake_test_password[] = { 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, 0x65, 0x73, 0x74 }; #if !defined(MBEDTLS_ECJPAKE_ALT) static const unsigned char ecjpake_test_x1[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21 }; static const unsigned char ecjpake_test_x2[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 }; static const unsigned char ecjpake_test_x3[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 }; static const unsigned char ecjpake_test_x4[] = { 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1 }; static const unsigned char ecjpake_test_cli_one[] = { 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 }; static const unsigned char ecjpake_test_srv_one[] = { 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 }; static const unsigned char ecjpake_test_srv_two[] = { 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c }; static const unsigned char ecjpake_test_cli_two[] = { 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c }; static const unsigned char ecjpake_test_shared_key[] = { 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80, 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79, 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1, 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0, 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12, 0x17, 0xc3, 0xde, 0x27, 0xb4, }; static const unsigned char ecjpake_test_pms[] = { 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 }; /* * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! * * This is the linear congruential generator from numerical recipes, * except we only use the low byte as the output. See * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use */ static int self_test_rng(void *ctx, unsigned char *out, size_t len) { static uint32_t state = 42; (void) ctx; for (size_t i = 0; i < len; i++) { state = state * 1664525u + 1013904223u; out[i] = (unsigned char) state; } return 0; } /* Load my private keys and generate the corresponding public keys */ static int ecjpake_test_load(mbedtls_ecjpake_context *ctx, const unsigned char *xm1, size_t len1, const unsigned char *xm2, size_t len2) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1, &ctx->grp.G, self_test_rng, NULL)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2, &ctx->grp.G, self_test_rng, NULL)); cleanup: return ret; } #endif /* ! MBEDTLS_ECJPAKE_ALT */ /* For tests we don't need a secure RNG; * use the LGC from Numerical Recipes for simplicity */ static int ecjpake_lgc(void *p, unsigned char *out, size_t len) { static uint32_t x = 42; (void) p; while (len > 0) { size_t use_len = len > 4 ? 4 : len; x = 1664525 * x + 1013904223; memcpy(out, &x, use_len); out += use_len; len -= use_len; } return 0; } #define TEST_ASSERT(x) \ do { \ if (x) \ ret = 0; \ else \ { \ ret = 1; \ goto cleanup; \ } \ } while (0) /* * Checkup routine */ int mbedtls_ecjpake_self_test(int verbose) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecjpake_context cli; mbedtls_ecjpake_context srv; unsigned char buf[512], pms[32]; size_t len, pmslen; mbedtls_ecjpake_init(&cli); mbedtls_ecjpake_init(&srv); if (verbose != 0) { mbedtls_printf(" ECJPAKE test #0 (setup): "); } TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT, MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, ecjpake_test_password, sizeof(ecjpake_test_password)) == 0); TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER, MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, ecjpake_test_password, sizeof(ecjpake_test_password)) == 0); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf(" ECJPAKE test #1 (random handshake): "); } TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0); TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0); TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0); TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli, pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0); TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == pmslen); TEST_ASSERT(memcmp(buf, pms, len) == 0); if (verbose != 0) { mbedtls_printf("passed\n"); } #if !defined(MBEDTLS_ECJPAKE_ALT) /* 'reference handshake' tests can only be run against implementations * for which we have 100% control over how the random ephemeral keys * are generated. This is only the case for the internal Mbed TLS * implementation, so these tests are skipped in case the internal * implementation is swapped out for an alternative one. */ if (verbose != 0) { mbedtls_printf(" ECJPAKE test #2 (reference handshake): "); } /* Simulate generation of round one */ MBEDTLS_MPI_CHK(ecjpake_test_load(&cli, ecjpake_test_x1, sizeof(ecjpake_test_x1), ecjpake_test_x2, sizeof(ecjpake_test_x2))); MBEDTLS_MPI_CHK(ecjpake_test_load(&srv, ecjpake_test_x3, sizeof(ecjpake_test_x3), ecjpake_test_x4, sizeof(ecjpake_test_x4))); /* Read round one */ TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, ecjpake_test_cli_one, sizeof(ecjpake_test_cli_one)) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, ecjpake_test_srv_one, sizeof(ecjpake_test_srv_one)) == 0); /* Skip generation of round two, read round two */ TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, ecjpake_test_srv_two, sizeof(ecjpake_test_srv_two)) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, ecjpake_test_cli_two, sizeof(ecjpake_test_cli_two)) == 0); /* Server derives PMS */ TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == sizeof(ecjpake_test_pms)); TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0); /* Server derives K as unsigned binary data */ TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == sizeof(ecjpake_test_shared_key)); TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0); memset(buf, 0, len); /* Avoid interferences with next step */ /* Client derives PMS */ TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == sizeof(ecjpake_test_pms)); TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0); /* Client derives K as unsigned binary data */ TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == sizeof(ecjpake_test_shared_key)); TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0); if (verbose != 0) { mbedtls_printf("passed\n"); } #endif /* ! MBEDTLS_ECJPAKE_ALT */ cleanup: mbedtls_ecjpake_free(&cli); mbedtls_ecjpake_free(&srv); if (ret != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; } if (verbose != 0) { mbedtls_printf("\n"); } return ret; } #undef TEST_ASSERT #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_ECJPAKE_C */ webfakes/src/mbedtls/library/asn1parse.c0000644000176200001440000002575214740737024020012 0ustar liggesusers/* * Generic ASN.1 parsing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) #include "mbedtls/asn1.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif #include "mbedtls/platform.h" /* * ASN.1 DER decoding routines */ int mbedtls_asn1_get_len(unsigned char **p, const unsigned char *end, size_t *len) { if ((end - *p) < 1) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } if ((**p & 0x80) == 0) { *len = *(*p)++; } else { int n = (**p) & 0x7F; if (n == 0 || n > 4) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } if ((end - *p) <= n) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } *len = 0; (*p)++; while (n--) { *len = (*len << 8) | **p; (*p)++; } } if (*len > (size_t) (end - *p)) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } return 0; } int mbedtls_asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len, int tag) { if ((end - *p) < 1) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } if (**p != tag) { return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG; } (*p)++; return mbedtls_asn1_get_len(p, end, len); } #endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ #if defined(MBEDTLS_ASN1_PARSE_C) int mbedtls_asn1_get_bool(unsigned char **p, const unsigned char *end, int *val) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) { return ret; } if (len != 1) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } *val = (**p != 0) ? 1 : 0; (*p)++; return 0; } static int asn1_get_tagged_int(unsigned char **p, const unsigned char *end, int tag, int *val) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) { return ret; } /* * len==0 is malformed (0 must be represented as 020100 for INTEGER, * or 0A0100 for ENUMERATED tags */ if (len == 0) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } /* This is a cryptography library. Reject negative integers. */ if ((**p & 0x80) != 0) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } /* Skip leading zeros. */ while (len > 0 && **p == 0) { ++(*p); --len; } /* Reject integers that don't fit in an int. This code assumes that * the int type has no padding bit. */ if (len > sizeof(int)) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } if (len == sizeof(int) && (**p & 0x80) != 0) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } *val = 0; while (len-- > 0) { *val = (*val << 8) | **p; (*p)++; } return 0; } int mbedtls_asn1_get_int(unsigned char **p, const unsigned char *end, int *val) { return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val); } int mbedtls_asn1_get_enum(unsigned char **p, const unsigned char *end, int *val) { return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val); } #if defined(MBEDTLS_BIGNUM_C) int mbedtls_asn1_get_mpi(unsigned char **p, const unsigned char *end, mbedtls_mpi *X) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { return ret; } ret = mbedtls_mpi_read_binary(X, *p, len); *p += len; return ret; } #endif /* MBEDTLS_BIGNUM_C */ int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end, mbedtls_asn1_bitstring *bs) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Certificate type is a single byte bitstring */ if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) { return ret; } /* Check length, subtract one for actual bit string length */ if (bs->len < 1) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } bs->len -= 1; /* Get number of unused bits, ensure unused bits <= 7 */ bs->unused_bits = **p; if (bs->unused_bits > 7) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } (*p)++; /* Get actual bitstring */ bs->p = *p; *p += bs->len; if (*p != end) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } return 0; } /* * Traverse an ASN.1 "SEQUENCE OF " * and call a callback for each entry found. */ int mbedtls_asn1_traverse_sequence_of( unsigned char **p, const unsigned char *end, unsigned char tag_must_mask, unsigned char tag_must_val, unsigned char tag_may_mask, unsigned char tag_may_val, int (*cb)(void *ctx, int tag, unsigned char *start, size_t len), void *ctx) { int ret; size_t len; /* Get main sequence tag */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } if (*p + len != end) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } while (*p < end) { unsigned char const tag = *(*p)++; if ((tag & tag_must_mask) != tag_must_val) { return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG; } if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) { return ret; } if ((tag & tag_may_mask) == tag_may_val) { if (cb != NULL) { ret = cb(ctx, tag, *p, len); if (ret != 0) { return ret; } } } *p += len; } return 0; } /* * Get a bit string without unused bits */ int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end, size_t *len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) { return ret; } if (*len == 0) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } --(*len); if (**p != 0) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } ++(*p); return 0; } void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq) { while (seq != NULL) { mbedtls_asn1_sequence *next = seq->next; mbedtls_free(seq); seq = next; } } typedef struct { int tag; mbedtls_asn1_sequence *cur; } asn1_get_sequence_of_cb_ctx_t; static int asn1_get_sequence_of_cb(void *ctx, int tag, unsigned char *start, size_t len) { asn1_get_sequence_of_cb_ctx_t *cb_ctx = (asn1_get_sequence_of_cb_ctx_t *) ctx; mbedtls_asn1_sequence *cur = cb_ctx->cur; if (cur->buf.p != NULL) { cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); if (cur->next == NULL) { return MBEDTLS_ERR_ASN1_ALLOC_FAILED; } cur = cur->next; } cur->buf.p = start; cur->buf.len = len; cur->buf.tag = tag; cb_ctx->cur = cur; return 0; } /* * Parses and splits an ASN.1 "SEQUENCE OF " */ int mbedtls_asn1_get_sequence_of(unsigned char **p, const unsigned char *end, mbedtls_asn1_sequence *cur, int tag) { asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur }; memset(cur, 0, sizeof(mbedtls_asn1_sequence)); return mbedtls_asn1_traverse_sequence_of( p, end, 0xFF, tag, 0, 0, asn1_get_sequence_of_cb, &cb_ctx); } int mbedtls_asn1_get_alg(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } if ((end - *p) < 1) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } alg->tag = **p; end = *p + len; if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) { return ret; } alg->p = *p; *p += alg->len; if (*p == end) { mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf)); return 0; } params->tag = **p; (*p)++; if ((ret = mbedtls_asn1_get_len(p, end, ¶ms->len)) != 0) { return ret; } params->p = *p; *p += params->len; if (*p != end) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } return 0; } int mbedtls_asn1_get_alg_null(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_asn1_buf params; memset(¶ms, 0, sizeof(mbedtls_asn1_buf)); if ((ret = mbedtls_asn1_get_alg(p, end, alg, ¶ms)) != 0) { return ret; } if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } return 0; } #if !defined(MBEDTLS_DEPRECATED_REMOVED) void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur) { if (cur == NULL) { return; } mbedtls_free(cur->oid.p); mbedtls_free(cur->val.p); mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data)); } #endif /* MBEDTLS_DEPRECATED_REMOVED */ void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head) { mbedtls_asn1_named_data *cur; while ((cur = *head) != NULL) { *head = cur->next; mbedtls_free(cur->oid.p); mbedtls_free(cur->val.p); mbedtls_free(cur); } } void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name) { for (mbedtls_asn1_named_data *next; name != NULL; name = next) { next = name->next; mbedtls_free(name); } } const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list, const char *oid, size_t len) { while (list != NULL) { if (list->oid.len == len && memcmp(list->oid.p, oid, len) == 0) { break; } list = list->next; } return list; } #endif /* MBEDTLS_ASN1_PARSE_C */ webfakes/src/mbedtls/library/version_features.c0000644000176200001440000007674514740737024021510 0ustar liggesusers/* * Version feature information * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_VERSION_C) #include "mbedtls/version.h" #include static const char * const features[] = { #if defined(MBEDTLS_VERSION_FEATURES) #if defined(MBEDTLS_HAVE_ASM) "HAVE_ASM", //no-check-names #endif /* MBEDTLS_HAVE_ASM */ #if defined(MBEDTLS_NO_UDBL_DIVISION) "NO_UDBL_DIVISION", //no-check-names #endif /* MBEDTLS_NO_UDBL_DIVISION */ #if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) "NO_64BIT_MULTIPLICATION", //no-check-names #endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ #if defined(MBEDTLS_HAVE_SSE2) "HAVE_SSE2", //no-check-names #endif /* MBEDTLS_HAVE_SSE2 */ #if defined(MBEDTLS_HAVE_TIME) "HAVE_TIME", //no-check-names #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_HAVE_TIME_DATE) "HAVE_TIME_DATE", //no-check-names #endif /* MBEDTLS_HAVE_TIME_DATE */ #if defined(MBEDTLS_PLATFORM_MEMORY) "PLATFORM_MEMORY", //no-check-names #endif /* MBEDTLS_PLATFORM_MEMORY */ #if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) "PLATFORM_NO_STD_FUNCTIONS", //no-check-names #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ #if defined(MBEDTLS_PLATFORM_SETBUF_ALT) "PLATFORM_SETBUF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ #if defined(MBEDTLS_PLATFORM_EXIT_ALT) "PLATFORM_EXIT_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_EXIT_ALT */ #if defined(MBEDTLS_PLATFORM_TIME_ALT) "PLATFORM_TIME_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_TIME_ALT */ #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) "PLATFORM_FPRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) "PLATFORM_PRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) "PLATFORM_SNPRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) "PLATFORM_VSNPRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) "PLATFORM_NV_SEED_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ #if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) "PLATFORM_SETUP_TEARDOWN_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ #if defined(MBEDTLS_PLATFORM_MS_TIME_ALT) "PLATFORM_MS_TIME_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_MS_TIME_ALT */ #if defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) "PLATFORM_GMTIME_R_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_GMTIME_R_ALT */ #if defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) "PLATFORM_ZEROIZE_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ #if defined(MBEDTLS_DEPRECATED_WARNING) "DEPRECATED_WARNING", //no-check-names #endif /* MBEDTLS_DEPRECATED_WARNING */ #if defined(MBEDTLS_DEPRECATED_REMOVED) "DEPRECATED_REMOVED", //no-check-names #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_TIMING_ALT) "TIMING_ALT", //no-check-names #endif /* MBEDTLS_TIMING_ALT */ #if defined(MBEDTLS_AES_ALT) "AES_ALT", //no-check-names #endif /* MBEDTLS_AES_ALT */ #if defined(MBEDTLS_ARIA_ALT) "ARIA_ALT", //no-check-names #endif /* MBEDTLS_ARIA_ALT */ #if defined(MBEDTLS_CAMELLIA_ALT) "CAMELLIA_ALT", //no-check-names #endif /* MBEDTLS_CAMELLIA_ALT */ #if defined(MBEDTLS_CCM_ALT) "CCM_ALT", //no-check-names #endif /* MBEDTLS_CCM_ALT */ #if defined(MBEDTLS_CHACHA20_ALT) "CHACHA20_ALT", //no-check-names #endif /* MBEDTLS_CHACHA20_ALT */ #if defined(MBEDTLS_CHACHAPOLY_ALT) "CHACHAPOLY_ALT", //no-check-names #endif /* MBEDTLS_CHACHAPOLY_ALT */ #if defined(MBEDTLS_CMAC_ALT) "CMAC_ALT", //no-check-names #endif /* MBEDTLS_CMAC_ALT */ #if defined(MBEDTLS_DES_ALT) "DES_ALT", //no-check-names #endif /* MBEDTLS_DES_ALT */ #if defined(MBEDTLS_DHM_ALT) "DHM_ALT", //no-check-names #endif /* MBEDTLS_DHM_ALT */ #if defined(MBEDTLS_ECJPAKE_ALT) "ECJPAKE_ALT", //no-check-names #endif /* MBEDTLS_ECJPAKE_ALT */ #if defined(MBEDTLS_GCM_ALT) "GCM_ALT", //no-check-names #endif /* MBEDTLS_GCM_ALT */ #if defined(MBEDTLS_NIST_KW_ALT) "NIST_KW_ALT", //no-check-names #endif /* MBEDTLS_NIST_KW_ALT */ #if defined(MBEDTLS_MD5_ALT) "MD5_ALT", //no-check-names #endif /* MBEDTLS_MD5_ALT */ #if defined(MBEDTLS_POLY1305_ALT) "POLY1305_ALT", //no-check-names #endif /* MBEDTLS_POLY1305_ALT */ #if defined(MBEDTLS_RIPEMD160_ALT) "RIPEMD160_ALT", //no-check-names #endif /* MBEDTLS_RIPEMD160_ALT */ #if defined(MBEDTLS_RSA_ALT) "RSA_ALT", //no-check-names #endif /* MBEDTLS_RSA_ALT */ #if defined(MBEDTLS_SHA1_ALT) "SHA1_ALT", //no-check-names #endif /* MBEDTLS_SHA1_ALT */ #if defined(MBEDTLS_SHA256_ALT) "SHA256_ALT", //no-check-names #endif /* MBEDTLS_SHA256_ALT */ #if defined(MBEDTLS_SHA512_ALT) "SHA512_ALT", //no-check-names #endif /* MBEDTLS_SHA512_ALT */ #if defined(MBEDTLS_ECP_ALT) "ECP_ALT", //no-check-names #endif /* MBEDTLS_ECP_ALT */ #if defined(MBEDTLS_MD5_PROCESS_ALT) "MD5_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_MD5_PROCESS_ALT */ #if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) "RIPEMD160_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ #if defined(MBEDTLS_SHA1_PROCESS_ALT) "SHA1_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_SHA1_PROCESS_ALT */ #if defined(MBEDTLS_SHA256_PROCESS_ALT) "SHA256_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_SHA256_PROCESS_ALT */ #if defined(MBEDTLS_SHA512_PROCESS_ALT) "SHA512_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_SHA512_PROCESS_ALT */ #if defined(MBEDTLS_DES_SETKEY_ALT) "DES_SETKEY_ALT", //no-check-names #endif /* MBEDTLS_DES_SETKEY_ALT */ #if defined(MBEDTLS_DES_CRYPT_ECB_ALT) "DES_CRYPT_ECB_ALT", //no-check-names #endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ #if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) "DES3_CRYPT_ECB_ALT", //no-check-names #endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ #if defined(MBEDTLS_AES_SETKEY_ENC_ALT) "AES_SETKEY_ENC_ALT", //no-check-names #endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ #if defined(MBEDTLS_AES_SETKEY_DEC_ALT) "AES_SETKEY_DEC_ALT", //no-check-names #endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ #if defined(MBEDTLS_AES_ENCRYPT_ALT) "AES_ENCRYPT_ALT", //no-check-names #endif /* MBEDTLS_AES_ENCRYPT_ALT */ #if defined(MBEDTLS_AES_DECRYPT_ALT) "AES_DECRYPT_ALT", //no-check-names #endif /* MBEDTLS_AES_DECRYPT_ALT */ #if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) "ECDH_GEN_PUBLIC_ALT", //no-check-names #endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ #if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) "ECDH_COMPUTE_SHARED_ALT", //no-check-names #endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ #if defined(MBEDTLS_ECDSA_VERIFY_ALT) "ECDSA_VERIFY_ALT", //no-check-names #endif /* MBEDTLS_ECDSA_VERIFY_ALT */ #if defined(MBEDTLS_ECDSA_SIGN_ALT) "ECDSA_SIGN_ALT", //no-check-names #endif /* MBEDTLS_ECDSA_SIGN_ALT */ #if defined(MBEDTLS_ECDSA_GENKEY_ALT) "ECDSA_GENKEY_ALT", //no-check-names #endif /* MBEDTLS_ECDSA_GENKEY_ALT */ #if defined(MBEDTLS_ECP_INTERNAL_ALT) "ECP_INTERNAL_ALT", //no-check-names #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) "ECP_NO_FALLBACK", //no-check-names #endif /* MBEDTLS_ECP_NO_FALLBACK */ #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) "ECP_RANDOMIZE_JAC_ALT", //no-check-names #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) "ECP_ADD_MIXED_ALT", //no-check-names #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) "ECP_DOUBLE_JAC_ALT", //no-check-names #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) "ECP_NORMALIZE_JAC_MANY_ALT", //no-check-names #endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) "ECP_NORMALIZE_JAC_ALT", //no-check-names #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) "ECP_DOUBLE_ADD_MXZ_ALT", //no-check-names #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) "ECP_RANDOMIZE_MXZ_ALT", //no-check-names #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) "ECP_NORMALIZE_MXZ_ALT", //no-check-names #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) "ENTROPY_HARDWARE_ALT", //no-check-names #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ #if defined(MBEDTLS_AES_ROM_TABLES) "AES_ROM_TABLES", //no-check-names #endif /* MBEDTLS_AES_ROM_TABLES */ #if defined(MBEDTLS_AES_FEWER_TABLES) "AES_FEWER_TABLES", //no-check-names #endif /* MBEDTLS_AES_FEWER_TABLES */ #if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) "AES_ONLY_128_BIT_KEY_LENGTH", //no-check-names #endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) "AES_USE_HARDWARE_ONLY", //no-check-names #endif /* MBEDTLS_AES_USE_HARDWARE_ONLY */ #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) "CAMELLIA_SMALL_MEMORY", //no-check-names #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ #if defined(MBEDTLS_CHECK_RETURN_WARNING) "CHECK_RETURN_WARNING", //no-check-names #endif /* MBEDTLS_CHECK_RETURN_WARNING */ #if defined(MBEDTLS_CIPHER_MODE_CBC) "CIPHER_MODE_CBC", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) "CIPHER_MODE_CFB", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) "CIPHER_MODE_CTR", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_OFB) "CIPHER_MODE_OFB", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_XTS) "CIPHER_MODE_XTS", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) "CIPHER_NULL_CIPHER", //no-check-names #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) "CIPHER_PADDING_PKCS7", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) "CIPHER_PADDING_ONE_AND_ZEROS", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) "CIPHER_PADDING_ZEROS_AND_LEN", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) "CIPHER_PADDING_ZEROS", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) "CTR_DRBG_USE_128_BIT_KEY", //no-check-names #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) "ECDH_VARIANT_EVEREST_ENABLED", //no-check-names #endif /* MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) "ECP_DP_SECP192R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) "ECP_DP_SECP224R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) "ECP_DP_SECP256R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) "ECP_DP_SECP384R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) "ECP_DP_SECP521R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) "ECP_DP_SECP192K1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) "ECP_DP_SECP224K1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) "ECP_DP_SECP256K1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) "ECP_DP_BP256R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) "ECP_DP_BP384R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) "ECP_DP_BP512R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) "ECP_DP_CURVE25519_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) "ECP_DP_CURVE448_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_NIST_OPTIM) "ECP_NIST_OPTIM", //no-check-names #endif /* MBEDTLS_ECP_NIST_OPTIM */ #if defined(MBEDTLS_ECP_RESTARTABLE) "ECP_RESTARTABLE", //no-check-names #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECP_WITH_MPI_UINT) "ECP_WITH_MPI_UINT", //no-check-names #endif /* MBEDTLS_ECP_WITH_MPI_UINT */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) "ECDSA_DETERMINISTIC", //no-check-names #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) "KEY_EXCHANGE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) "KEY_EXCHANGE_DHE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) "KEY_EXCHANGE_ECDHE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) "KEY_EXCHANGE_RSA_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) "KEY_EXCHANGE_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) "KEY_EXCHANGE_DHE_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) "KEY_EXCHANGE_ECDHE_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) "KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) "KEY_EXCHANGE_ECDH_ECDSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) "KEY_EXCHANGE_ECDH_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) "KEY_EXCHANGE_ECJPAKE_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) "PK_PARSE_EC_EXTENDED", //no-check-names #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ #if defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) "PK_PARSE_EC_COMPRESSED", //no-check-names #endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ #if defined(MBEDTLS_ERROR_STRERROR_DUMMY) "ERROR_STRERROR_DUMMY", //no-check-names #endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ #if defined(MBEDTLS_GENPRIME) "GENPRIME", //no-check-names #endif /* MBEDTLS_GENPRIME */ #if defined(MBEDTLS_FS_IO) "FS_IO", //no-check-names #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) "NO_DEFAULT_ENTROPY_SOURCES", //no-check-names #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ #if defined(MBEDTLS_NO_PLATFORM_ENTROPY) "NO_PLATFORM_ENTROPY", //no-check-names #endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ #if defined(MBEDTLS_ENTROPY_FORCE_SHA256) "ENTROPY_FORCE_SHA256", //no-check-names #endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ #if defined(MBEDTLS_ENTROPY_NV_SEED) "ENTROPY_NV_SEED", //no-check-names #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) "PSA_CRYPTO_KEY_ID_ENCODES_OWNER", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ #if defined(MBEDTLS_MEMORY_DEBUG) "MEMORY_DEBUG", //no-check-names #endif /* MBEDTLS_MEMORY_DEBUG */ #if defined(MBEDTLS_MEMORY_BACKTRACE) "MEMORY_BACKTRACE", //no-check-names #endif /* MBEDTLS_MEMORY_BACKTRACE */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) "PK_RSA_ALT_SUPPORT", //no-check-names #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #if defined(MBEDTLS_PKCS1_V15) "PKCS1_V15", //no-check-names #endif /* MBEDTLS_PKCS1_V15 */ #if defined(MBEDTLS_PKCS1_V21) "PKCS1_V21", //no-check-names #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) "PSA_CRYPTO_BUILTIN_KEYS", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) "PSA_CRYPTO_CLIENT", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) "PSA_CRYPTO_EXTERNAL_RNG", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #if defined(MBEDTLS_PSA_CRYPTO_SPM) "PSA_CRYPTO_SPM", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_SPM */ #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) "PSA_KEY_STORE_DYNAMIC", //no-check-names #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) "PSA_P256M_DRIVER_ENABLED", //no-check-names #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) "PSA_INJECT_ENTROPY", //no-check-names #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ #if defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) "PSA_ASSUME_EXCLUSIVE_BUFFERS", //no-check-names #endif /* MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ #if defined(MBEDTLS_RSA_NO_CRT) "RSA_NO_CRT", //no-check-names #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_SELF_TEST) "SELF_TEST", //no-check-names #endif /* MBEDTLS_SELF_TEST */ #if defined(MBEDTLS_SHA256_SMALLER) "SHA256_SMALLER", //no-check-names #endif /* MBEDTLS_SHA256_SMALLER */ #if defined(MBEDTLS_SHA512_SMALLER) "SHA512_SMALLER", //no-check-names #endif /* MBEDTLS_SHA512_SMALLER */ #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) "SSL_ALL_ALERT_MESSAGES", //no-check-names #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) "SSL_DTLS_CONNECTION_ID", //no-check-names #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) "SSL_DTLS_CONNECTION_ID_COMPAT", //no-check-names #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) "SSL_ASYNC_PRIVATE", //no-check-names #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) "SSL_CONTEXT_SERIALIZATION", //no-check-names #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ #if defined(MBEDTLS_SSL_DEBUG_ALL) "SSL_DEBUG_ALL", //no-check-names #endif /* MBEDTLS_SSL_DEBUG_ALL */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) "SSL_ENCRYPT_THEN_MAC", //no-check-names #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) "SSL_EXTENDED_MASTER_SECRET", //no-check-names #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) "SSL_KEEP_PEER_CERTIFICATE", //no-check-names #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #if defined(MBEDTLS_SSL_RENEGOTIATION) "SSL_RENEGOTIATION", //no-check-names #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) "SSL_MAX_FRAGMENT_LENGTH", //no-check-names #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) "SSL_RECORD_SIZE_LIMIT", //no-check-names #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) "SSL_PROTO_TLS1_2", //no-check-names #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) "SSL_PROTO_TLS1_3", //no-check-names #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) "SSL_TLS1_3_COMPATIBILITY_MODE", //no-check-names #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) "SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) "SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED", //no-check-names #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) "SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED", //no-check-names #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_EARLY_DATA) "SSL_EARLY_DATA", //no-check-names #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_PROTO_DTLS) "SSL_PROTO_DTLS", //no-check-names #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_ALPN) "SSL_ALPN", //no-check-names #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) "SSL_DTLS_ANTI_REPLAY", //no-check-names #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) "SSL_DTLS_HELLO_VERIFY", //no-check-names #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ #if defined(MBEDTLS_SSL_DTLS_SRTP) "SSL_DTLS_SRTP", //no-check-names #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) "SSL_DTLS_CLIENT_PORT_REUSE", //no-check-names #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) "SSL_SESSION_TICKETS", //no-check-names #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) "SSL_SERVER_NAME_INDICATION", //no-check-names #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) "SSL_VARIABLE_BUFFER_LENGTH", //no-check-names #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) "TEST_CONSTANT_FLOW_MEMSAN", //no-check-names #endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ #if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) "TEST_CONSTANT_FLOW_VALGRIND", //no-check-names #endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */ #if defined(MBEDTLS_TEST_HOOKS) "TEST_HOOKS", //no-check-names #endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_THREADING_ALT) "THREADING_ALT", //no-check-names #endif /* MBEDTLS_THREADING_ALT */ #if defined(MBEDTLS_THREADING_PTHREAD) "THREADING_PTHREAD", //no-check-names #endif /* MBEDTLS_THREADING_PTHREAD */ #if defined(MBEDTLS_USE_PSA_CRYPTO) "USE_PSA_CRYPTO", //no-check-names #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) "PSA_CRYPTO_CONFIG", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ #if defined(MBEDTLS_VERSION_FEATURES) "VERSION_FEATURES", //no-check-names #endif /* MBEDTLS_VERSION_FEATURES */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) "X509_TRUSTED_CERTIFICATE_CALLBACK", //no-check-names #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #if defined(MBEDTLS_X509_REMOVE_INFO) "X509_REMOVE_INFO", //no-check-names #endif /* MBEDTLS_X509_REMOVE_INFO */ #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) "X509_RSASSA_PSS_SUPPORT", //no-check-names #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ #if defined(MBEDTLS_AESNI_C) "AESNI_C", //no-check-names #endif /* MBEDTLS_AESNI_C */ #if defined(MBEDTLS_AESCE_C) "AESCE_C", //no-check-names #endif /* MBEDTLS_AESCE_C */ #if defined(MBEDTLS_AES_C) "AES_C", //no-check-names #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_ASN1_PARSE_C) "ASN1_PARSE_C", //no-check-names #endif /* MBEDTLS_ASN1_PARSE_C */ #if defined(MBEDTLS_ASN1_WRITE_C) "ASN1_WRITE_C", //no-check-names #endif /* MBEDTLS_ASN1_WRITE_C */ #if defined(MBEDTLS_BASE64_C) "BASE64_C", //no-check-names #endif /* MBEDTLS_BASE64_C */ #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) "BLOCK_CIPHER_NO_DECRYPT", //no-check-names #endif /* MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_BIGNUM_C) "BIGNUM_C", //no-check-names #endif /* MBEDTLS_BIGNUM_C */ #if defined(MBEDTLS_CAMELLIA_C) "CAMELLIA_C", //no-check-names #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_ARIA_C) "ARIA_C", //no-check-names #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_CCM_C) "CCM_C", //no-check-names #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHA20_C) "CHACHA20_C", //no-check-names #endif /* MBEDTLS_CHACHA20_C */ #if defined(MBEDTLS_CHACHAPOLY_C) "CHACHAPOLY_C", //no-check-names #endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CIPHER_C) "CIPHER_C", //no-check-names #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_CMAC_C) "CMAC_C", //no-check-names #endif /* MBEDTLS_CMAC_C */ #if defined(MBEDTLS_CTR_DRBG_C) "CTR_DRBG_C", //no-check-names #endif /* MBEDTLS_CTR_DRBG_C */ #if defined(MBEDTLS_DEBUG_C) "DEBUG_C", //no-check-names #endif /* MBEDTLS_DEBUG_C */ #if defined(MBEDTLS_DES_C) "DES_C", //no-check-names #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_DHM_C) "DHM_C", //no-check-names #endif /* MBEDTLS_DHM_C */ #if defined(MBEDTLS_ECDH_C) "ECDH_C", //no-check-names #endif /* MBEDTLS_ECDH_C */ #if defined(MBEDTLS_ECDSA_C) "ECDSA_C", //no-check-names #endif /* MBEDTLS_ECDSA_C */ #if defined(MBEDTLS_ECJPAKE_C) "ECJPAKE_C", //no-check-names #endif /* MBEDTLS_ECJPAKE_C */ #if defined(MBEDTLS_ECP_C) "ECP_C", //no-check-names #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_ENTROPY_C) "ENTROPY_C", //no-check-names #endif /* MBEDTLS_ENTROPY_C */ #if defined(MBEDTLS_ERROR_C) "ERROR_C", //no-check-names #endif /* MBEDTLS_ERROR_C */ #if defined(MBEDTLS_GCM_C) "GCM_C", //no-check-names #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_GCM_LARGE_TABLE) "GCM_LARGE_TABLE", //no-check-names #endif /* MBEDTLS_GCM_LARGE_TABLE */ #if defined(MBEDTLS_HKDF_C) "HKDF_C", //no-check-names #endif /* MBEDTLS_HKDF_C */ #if defined(MBEDTLS_HMAC_DRBG_C) "HMAC_DRBG_C", //no-check-names #endif /* MBEDTLS_HMAC_DRBG_C */ #if defined(MBEDTLS_LMS_C) "LMS_C", //no-check-names #endif /* MBEDTLS_LMS_C */ #if defined(MBEDTLS_LMS_PRIVATE) "LMS_PRIVATE", //no-check-names #endif /* MBEDTLS_LMS_PRIVATE */ #if defined(MBEDTLS_NIST_KW_C) "NIST_KW_C", //no-check-names #endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_MD_C) "MD_C", //no-check-names #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_MD5_C) "MD5_C", //no-check-names #endif /* MBEDTLS_MD5_C */ #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) "MEMORY_BUFFER_ALLOC_C", //no-check-names #endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ #if defined(MBEDTLS_NET_C) "NET_C", //no-check-names #endif /* MBEDTLS_NET_C */ #if defined(MBEDTLS_OID_C) "OID_C", //no-check-names #endif /* MBEDTLS_OID_C */ #if defined(MBEDTLS_PADLOCK_C) "PADLOCK_C", //no-check-names #endif /* MBEDTLS_PADLOCK_C */ #if defined(MBEDTLS_PEM_PARSE_C) "PEM_PARSE_C", //no-check-names #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_WRITE_C) "PEM_WRITE_C", //no-check-names #endif /* MBEDTLS_PEM_WRITE_C */ #if defined(MBEDTLS_PK_C) "PK_C", //no-check-names #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_PK_PARSE_C) "PK_PARSE_C", //no-check-names #endif /* MBEDTLS_PK_PARSE_C */ #if defined(MBEDTLS_PK_WRITE_C) "PK_WRITE_C", //no-check-names #endif /* MBEDTLS_PK_WRITE_C */ #if defined(MBEDTLS_PKCS5_C) "PKCS5_C", //no-check-names #endif /* MBEDTLS_PKCS5_C */ #if defined(MBEDTLS_PKCS7_C) "PKCS7_C", //no-check-names #endif /* MBEDTLS_PKCS7_C */ #if defined(MBEDTLS_PKCS12_C) "PKCS12_C", //no-check-names #endif /* MBEDTLS_PKCS12_C */ #if defined(MBEDTLS_PLATFORM_C) "PLATFORM_C", //no-check-names #endif /* MBEDTLS_PLATFORM_C */ #if defined(MBEDTLS_POLY1305_C) "POLY1305_C", //no-check-names #endif /* MBEDTLS_POLY1305_C */ #if defined(MBEDTLS_PSA_CRYPTO_C) "PSA_CRYPTO_C", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_C */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) "PSA_CRYPTO_SE_C", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) "PSA_CRYPTO_STORAGE_C", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ #if defined(MBEDTLS_PSA_ITS_FILE_C) "PSA_ITS_FILE_C", //no-check-names #endif /* MBEDTLS_PSA_ITS_FILE_C */ #if defined(MBEDTLS_RIPEMD160_C) "RIPEMD160_C", //no-check-names #endif /* MBEDTLS_RIPEMD160_C */ #if defined(MBEDTLS_RSA_C) "RSA_C", //no-check-names #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_SHA1_C) "SHA1_C", //no-check-names #endif /* MBEDTLS_SHA1_C */ #if defined(MBEDTLS_SHA224_C) "SHA224_C", //no-check-names #endif /* MBEDTLS_SHA224_C */ #if defined(MBEDTLS_SHA256_C) "SHA256_C", //no-check-names #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) "SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT", //no-check-names #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) "SHA256_USE_A64_CRYPTO_IF_PRESENT", //no-check-names #endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */ #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) "SHA256_USE_ARMV8_A_CRYPTO_ONLY", //no-check-names #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) "SHA256_USE_A64_CRYPTO_ONLY", //no-check-names #endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA384_C) "SHA384_C", //no-check-names #endif /* MBEDTLS_SHA384_C */ #if defined(MBEDTLS_SHA512_C) "SHA512_C", //no-check-names #endif /* MBEDTLS_SHA512_C */ #if defined(MBEDTLS_SHA3_C) "SHA3_C", //no-check-names #endif /* MBEDTLS_SHA3_C */ #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) "SHA512_USE_A64_CRYPTO_IF_PRESENT", //no-check-names #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) "SHA512_USE_A64_CRYPTO_ONLY", //no-check-names #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_SSL_CACHE_C) "SSL_CACHE_C", //no-check-names #endif /* MBEDTLS_SSL_CACHE_C */ #if defined(MBEDTLS_SSL_COOKIE_C) "SSL_COOKIE_C", //no-check-names #endif /* MBEDTLS_SSL_COOKIE_C */ #if defined(MBEDTLS_SSL_TICKET_C) "SSL_TICKET_C", //no-check-names #endif /* MBEDTLS_SSL_TICKET_C */ #if defined(MBEDTLS_SSL_CLI_C) "SSL_CLI_C", //no-check-names #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) "SSL_SRV_C", //no-check-names #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_TLS_C) "SSL_TLS_C", //no-check-names #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_THREADING_C) "THREADING_C", //no-check-names #endif /* MBEDTLS_THREADING_C */ #if defined(MBEDTLS_TIMING_C) "TIMING_C", //no-check-names #endif /* MBEDTLS_TIMING_C */ #if defined(MBEDTLS_VERSION_C) "VERSION_C", //no-check-names #endif /* MBEDTLS_VERSION_C */ #if defined(MBEDTLS_X509_USE_C) "X509_USE_C", //no-check-names #endif /* MBEDTLS_X509_USE_C */ #if defined(MBEDTLS_X509_CRT_PARSE_C) "X509_CRT_PARSE_C", //no-check-names #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_X509_CRL_PARSE_C) "X509_CRL_PARSE_C", //no-check-names #endif /* MBEDTLS_X509_CRL_PARSE_C */ #if defined(MBEDTLS_X509_CSR_PARSE_C) "X509_CSR_PARSE_C", //no-check-names #endif /* MBEDTLS_X509_CSR_PARSE_C */ #if defined(MBEDTLS_X509_CREATE_C) "X509_CREATE_C", //no-check-names #endif /* MBEDTLS_X509_CREATE_C */ #if defined(MBEDTLS_X509_CRT_WRITE_C) "X509_CRT_WRITE_C", //no-check-names #endif /* MBEDTLS_X509_CRT_WRITE_C */ #if defined(MBEDTLS_X509_CSR_WRITE_C) "X509_CSR_WRITE_C", //no-check-names #endif /* MBEDTLS_X509_CSR_WRITE_C */ #endif /* MBEDTLS_VERSION_FEATURES */ NULL }; int mbedtls_version_check_feature(const char *feature) { const char * const *idx = features; if (*idx == NULL) { return -2; } if (feature == NULL) { return -1; } if (strncmp(feature, "MBEDTLS_", 8)) { return -1; } feature += 8; while (*idx != NULL) { if (!strcmp(*idx, feature)) { return 0; } idx++; } return -1; } #endif /* MBEDTLS_VERSION_C */ webfakes/src/mbedtls/library/pkparse.c0000644000176200001440000012475714740737024017567 0ustar liggesusers/* * Public Key layer for parsing key files and structures * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PK_PARSE_C) #include "mbedtls/pk.h" #include "mbedtls/asn1.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include "mbedtls/platform.h" #include "mbedtls/error.h" #include "mbedtls/ecp.h" #include "pk_internal.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/psa_util.h" #include "psa/crypto.h" #endif /* Key types */ #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #include "rsa_internal.h" #endif /* Extended formats */ #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_PKCS5_C) #include "mbedtls/pkcs5.h" #endif #if defined(MBEDTLS_PKCS12_C) #include "mbedtls/pkcs12.h" #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /*********************************************************************** * * Low-level ECC parsing: optional support for SpecifiedECDomain * * There are two functions here that are used by the rest of the code: * - pk_ecc_tag_is_speficied_ec_domain() * - pk_ecc_group_id_from_specified() * * All the other functions are internal to this section. * * The two "public" functions have a dummy variant provided * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an * abstraction layer for this macro, which should not appear outside * this section. * **********************************************************************/ #if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED) /* See the "real" version for documentation */ static int pk_ecc_tag_is_specified_ec_domain(int tag) { (void) tag; return 0; } /* See the "real" version for documentation */ static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group_id *grp_id) { (void) params; (void) grp_id; return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } #else /* MBEDTLS_PK_PARSE_EC_EXTENDED */ /* * Tell if the passed tag might be the start of SpecifiedECDomain * (that is, a sequence). */ static int pk_ecc_tag_is_specified_ec_domain(int tag) { return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); } /* * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. * WARNING: the resulting group should only be used with * pk_ecc_group_id_from_specified(), since its base point may not be set correctly * if it was encoded compressed. * * SpecifiedECDomain ::= SEQUENCE { * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), * fieldID FieldID {{FieldTypes}}, * curve Curve, * base ECPoint, * order INTEGER, * cofactor INTEGER OPTIONAL, * hash HashAlgorithm OPTIONAL, * ... * } * * We only support prime-field as field type, and ignore hash and cofactor. */ static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = params->p; const unsigned char *const end = params->p + params->len; const unsigned char *end_field, *end_curve; size_t len; int ver; /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (ver < 1 || ver > 3) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field * fieldType FIELD-ID.&id({IOSet}), * parameters FIELD-ID.&Type({IOSet}{@fieldType}) * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } end_field = p + len; /* * FIELD-ID ::= TYPE-IDENTIFIER * FieldTypes FIELD-ID ::= { * { Prime-p IDENTIFIED BY prime-field } | * { Characteristic-two IDENTIFIED BY characteristic-two-field } * } * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } */ if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) { return ret; } if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) || memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } p += len; /* Prime-p ::= INTEGER -- Field of size p. */ if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } grp->pbits = mbedtls_mpi_bitlen(&grp->P); if (p != end_field) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * Curve ::= SEQUENCE { * a FieldElement, * b FieldElement, * seed BIT STRING OPTIONAL * -- Shall be present if used in SpecifiedECDomain * -- with version equal to ecdpVer2 or ecdpVer3 * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } end_curve = p + len; /* * FieldElement ::= OCTET STRING * containing an integer in the case of a prime field */ if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } p += len; if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } p += len; /* Ignore seed BIT STRING OPTIONAL */ if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) { p += len; } if (p != end_curve) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * ECPoint ::= OCTET STRING */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G, (const unsigned char *) p, len)) != 0) { /* * If we can't read the point because it's compressed, cheat by * reading only the X coordinate and the parity bit of Y. */ if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || (p[0] != 0x02 && p[0] != 0x03) || len != mbedtls_mpi_size(&grp->P) + 1 || mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 || mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 || mbedtls_mpi_lset(&grp->G.Z, 1) != 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } } p += len; /* * order INTEGER */ if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } grp->nbits = mbedtls_mpi_bitlen(&grp->N); /* * Allow optional elements by purposefully not enforcing p == end here. */ return 0; } /* * Find the group id associated with an (almost filled) group as generated by * pk_group_from_specified(), or return an error if unknown. */ static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id) { int ret = 0; mbedtls_ecp_group ref; const mbedtls_ecp_group_id *id; mbedtls_ecp_group_init(&ref); for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) { /* Load the group associated to that id */ mbedtls_ecp_group_free(&ref); MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id)); /* Compare to the group we were given, starting with easy tests */ if (grp->pbits == ref.pbits && grp->nbits == ref.nbits && mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 && mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 && mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 && mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 && mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 && mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 && /* For Y we may only know the parity bit, so compare only that */ mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { break; } } cleanup: mbedtls_ecp_group_free(&ref); *grp_id = *id; if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) { ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } return ret; } /* * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID */ static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group_id *grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group grp; mbedtls_ecp_group_init(&grp); if ((ret = pk_group_from_specified(params, &grp)) != 0) { goto cleanup; } ret = pk_group_id_from_group(&grp, grp_id); cleanup: /* The API respecting lifecycle for mbedtls_ecp_group struct is * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the * temporary grp breaks that flow and it's members are populated * by pk_group_id_from_group(). As such mbedtls_ecp_group_free() * which is assuming a group populated by _setup() may not clean-up * properly -> Manually free it's members. */ mbedtls_mpi_free(&grp.N); mbedtls_mpi_free(&grp.P); mbedtls_mpi_free(&grp.A); mbedtls_mpi_free(&grp.B); mbedtls_ecp_point_free(&grp.G); return ret; } #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ /*********************************************************************** * * Unsorted (yet!) from this point on until the next section header * **********************************************************************/ /* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf * * ECParameters ::= CHOICE { * namedCurve OBJECT IDENTIFIER * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } * -- implicitCurve NULL * } */ static int pk_get_ecparams(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *params) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (end - *p < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } /* Acceptable tags: OID for namedCurve, or specifiedECDomain */ params->tag = **p; if (params->tag != MBEDTLS_ASN1_OID && !pk_ecc_tag_is_specified_ec_domain(params->tag)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } params->p = *p; *p += params->len; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Use EC parameters to initialise an EC group * * ECParameters ::= CHOICE { * namedCurve OBJECT IDENTIFIER * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } * -- implicitCurve NULL */ static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group_id grp_id; if (params->tag == MBEDTLS_ASN1_OID) { if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) { return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE; } } else { ret = pk_ecc_group_id_from_specified(params, &grp_id); if (ret != 0) { return ret; } } return mbedtls_pk_ecc_set_group(pk, grp_id); } #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) /* * Load an RFC8410 EC key, which doesn't have any parameters */ static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params, mbedtls_ecp_group_id grp_id, mbedtls_pk_context *pk) { if (params->tag != 0 || params->len != 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } return mbedtls_pk_ecc_set_group(pk, grp_id); } /* * Parse an RFC 8410 encoded private EC key * * CurvePrivateKey ::= OCTET STRING */ static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk, unsigned char *key, size_t keylen, const unsigned char *end, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (key + len != end) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* * Load the private key */ ret = mbedtls_pk_ecc_set_key(pk, key, len); if (ret != 0) { return ret; } /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys, * which never contain a public key. As such, derive the public key * unconditionally. */ if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) { return ret; } return 0; } #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Get a PK algorithm identifier * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ static int pk_get_pk_alg(unsigned char **p, const unsigned char *end, mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params, mbedtls_ecp_group_id *ec_grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_asn1_buf alg_oid; memset(params, 0, sizeof(mbedtls_asn1_buf)); if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret); } ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (ret == MBEDTLS_ERR_OID_NOT_FOUND) { ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id); if (ret == 0) { *pk_alg = MBEDTLS_PK_ECKEY; } } #else (void) ec_grp_id; #endif if (ret != 0) { return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } /* * No parameters with RSA (only for EC) */ if (*pk_alg == MBEDTLS_PK_RSA && ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) || params->len != 0)) { return MBEDTLS_ERR_PK_INVALID_ALG; } return 0; } /* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, mbedtls_pk_context *pk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; mbedtls_asn1_buf alg_params; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; const mbedtls_pk_info_t *pk_info; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } end = *p + len; if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) { return ret; } if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); } if (*p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { return ret; } #if defined(MBEDTLS_RSA_C) if (pk_alg == MBEDTLS_PK_RSA) { ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p)); if (ret == 0) { /* On success all the input has been consumed by the parsing function. */ *p += end - *p; } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) && (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) { /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */ ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); } else { ret = MBEDTLS_ERR_PK_INVALID_PUBKEY; } } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) { #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk); } else #endif { ret = pk_use_ecparams(&alg_params, pk); } if (ret == 0) { ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p)); *p += end - *p; } } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; if (ret == 0 && *p != end) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if (ret != 0) { mbedtls_pk_free(pk); } return ret; } #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * Parse a SEC1 encoded private EC key */ static int pk_parse_key_sec1_der(mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int version, pubkey_done; size_t len, d_len; mbedtls_asn1_buf params = { 0, 0, NULL }; unsigned char *p = (unsigned char *) key; unsigned char *d; unsigned char *end = p + keylen; unsigned char *end2; /* * RFC 5915, or SEC1 Appendix C.4 * * ECPrivateKey ::= SEQUENCE { * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), * privateKey OCTET STRING, * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, * publicKey [1] BIT STRING OPTIONAL * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } end = p + len; if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (version != 1) { return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } /* Keep a reference to the position fo the private key. It will be used * later in this function. */ d = p; d_len = len; p += len; pubkey_done = 0; if (p != end) { /* * Is 'parameters' present? */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)) == 0) { if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || (ret = pk_use_ecparams(¶ms, pk)) != 0) { return ret; } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } } /* * Load the private key */ ret = mbedtls_pk_ecc_set_key(pk, d, d_len); if (ret != 0) { return ret; } if (p != end) { /* * Is 'publickey' present? If not, or if we can't read it (eg because it * is compressed), create it from the private key. */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1)) == 0) { end2 = p + len; if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (p + len != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) { pubkey_done = 1; } else { /* * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above * is if the point format is not recognized. */ if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } } if (!pubkey_done) { if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) { return ret; } } return 0; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /*********************************************************************** * * PKCS#8 parsing functions * **********************************************************************/ /* * Parse an unencrypted PKCS#8 encoded private key * * Notes: * * - This function does not own the key buffer. It is the * responsibility of the caller to take care of zeroizing * and freeing it after use. * * - The function is responsible for freeing the provided * PK context on failure. * */ static int pk_parse_key_pkcs8_unencrypted_der( mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, version; size_t len; mbedtls_asn1_buf params; unsigned char *p = (unsigned char *) key; unsigned char *end = p + keylen; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; const mbedtls_pk_info_t *pk_info; #if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) (void) f_rng; (void) p_rng; #endif /* * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) * * PrivateKeyInfo ::= SEQUENCE { * version Version, * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, * privateKey PrivateKey, * attributes [0] IMPLICIT Attributes OPTIONAL } * * Version ::= INTEGER * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier * PrivateKey ::= OCTET STRING * * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } end = p + len; if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (version != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret); } if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms, &ec_grp_id)) != 0) { return ret; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (len < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { return ret; } #if defined(MBEDTLS_RSA_C) if (pk_alg == MBEDTLS_PK_RSA) { if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) { mbedtls_pk_free(pk); return ret; } } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { if ((ret = pk_use_ecparams_rfc8410(¶ms, ec_grp_id, pk)) != 0 || (ret = pk_parse_key_rfc8410_der(pk, p, len, end, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); return ret; } } else #endif { if ((ret = pk_use_ecparams(¶ms, pk)) != 0 || (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); return ret; } } } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; end = p + len; if (end != (key + keylen)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse an encrypted PKCS#8 encoded private key * * To save space, the decryption happens in-place on the given key buffer. * Also, while this function may modify the keybuffer, it doesn't own it, * and instead it is the responsibility of the caller to zeroize and properly * free it after use. * */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der( mbedtls_pk_context *pk, unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, decrypted = 0; size_t len; unsigned char *buf; unsigned char *p, *end; mbedtls_asn1_buf pbe_alg_oid, pbe_params; #if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) mbedtls_cipher_type_t cipher_alg; mbedtls_md_type_t md_alg; #endif size_t outlen = 0; p = key; end = p + keylen; if (pwdlen == 0) { return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; } /* * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) * * EncryptedPrivateKeyInfo ::= SEQUENCE { * encryptionAlgorithm EncryptionAlgorithmIdentifier, * encryptedData EncryptedData * } * * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier * * EncryptedData ::= OCTET STRING * * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo * */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } end = p + len; if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } buf = p; /* * Decrypt EncryptedData with appropriate PBE */ #if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) { if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, cipher_alg, md_alg, pwd, pwdlen, p, len, buf, len, &outlen)) != 0) { if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } return ret; } decrypted = 1; } else #endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, p, len, buf, len, &outlen)) != 0) { if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } return ret; } decrypted = 1; } else #endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */ { ((void) pwd); } if (decrypted == 0) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng); } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ /*********************************************************************** * * Top-level functions, with format auto-discovery * **********************************************************************/ /* * Parse a private key */ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_pk_info_t *pk_info; #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; #endif if (keylen == 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init(&pem); #if defined(MBEDTLS_RSA_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA, key, pwd, pwdlen, &len); } if (ret == 0) { pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), pem.buf, pem.buflen)) != 0) { mbedtls_pk_free(pk); } mbedtls_pem_free(&pem); return ret; } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PRIVATE_KEY_EC, PEM_END_PRIVATE_KEY_EC, key, pwd, pwdlen, &len); } if (ret == 0) { pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || (ret = pk_parse_key_sec1_der(pk, pem.buf, pem.buflen, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); } mbedtls_pem_free(&pem); return ret; } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8, key, NULL, 0, &len); } if (ret == 0) { if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, pem.buf, pem.buflen, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); } mbedtls_pem_free(&pem); return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8, PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8, key, NULL, 0, &len); } if (ret == 0) { if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, pwd, pwdlen, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); } mbedtls_pem_free(&pem); return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ #else ((void) pwd); ((void) pwdlen); #endif /* MBEDTLS_PEM_PARSE_C */ /* * At this point we only know it's not a PEM formatted key. Could be any * of the known DER encoded private key formats * * We try the different DER format parsers to see if one passes without * error */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) if (pwdlen != 0) { unsigned char *key_copy; if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } memcpy(key_copy, key, keylen); ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, pwd, pwdlen, f_rng, p_rng); mbedtls_zeroize_and_free(key_copy, keylen); } if (ret == 0) { return 0; } mbedtls_pk_free(pk); mbedtls_pk_init(pk); if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { return ret; } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng); if (ret == 0) { return 0; } mbedtls_pk_free(pk); mbedtls_pk_init(pk); #if defined(MBEDTLS_RSA_C) pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if (mbedtls_pk_setup(pk, pk_info) == 0 && mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) { return 0; } mbedtls_pk_free(pk); mbedtls_pk_init(pk); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); if (mbedtls_pk_setup(pk, pk_info) == 0 && pk_parse_key_sec1_der(pk, key, keylen, f_rng, p_rng) == 0) { return 0; } mbedtls_pk_free(pk); #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't, * it is ok to leave the PK context initialized but not * freed: It is the caller's responsibility to call pk_init() * before calling this function, and to call pk_free() * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C * isn't, this leads to mbedtls_pk_free() being called * twice, once here and once by the caller, but this is * also ok and in line with the mbedtls_pk_free() calls * on failed PEM parsing attempts. */ return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* * Parse a public key */ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p; #if defined(MBEDTLS_RSA_C) const mbedtls_pk_info_t *pk_info; #endif #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; #endif if (keylen == 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init(&pem); #if defined(MBEDTLS_RSA_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA, key, NULL, 0, &len); } if (ret == 0) { p = pem.buf; if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { mbedtls_pem_free(&pem); return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { mbedtls_pem_free(&pem); return ret; } if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) { mbedtls_pk_free(ctx); } mbedtls_pem_free(&pem); return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { mbedtls_pem_free(&pem); return ret; } #endif /* MBEDTLS_RSA_C */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, key, NULL, 0, &len); } if (ret == 0) { /* * Was PEM encoded */ p = pem.buf; ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx); mbedtls_pem_free(&pem); return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { mbedtls_pem_free(&pem); return ret; } mbedtls_pem_free(&pem); #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_RSA_C) if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { return ret; } p = (unsigned char *) key; ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen); if (ret == 0) { return ret; } mbedtls_pk_free(ctx); if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return ret; } #endif /* MBEDTLS_RSA_C */ p = (unsigned char *) key; ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx); return ret; } /*********************************************************************** * * Top-level functions, with filesystem support * **********************************************************************/ #if defined(MBEDTLS_FS_IO) /* * Load all data from a file into a given buffer. * * The file is expected to contain either PEM or DER encoded data. * A terminating null byte is always appended. It is included in the announced * length only if the data looks like it is PEM encoded. */ int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) { FILE *f; long size; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_PK_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); fseek(f, 0, SEEK_END); if ((size = ftell(f)) == -1) { fclose(f); return MBEDTLS_ERR_PK_FILE_IO_ERROR; } fseek(f, 0, SEEK_SET); *n = (size_t) size; if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { fclose(f); return MBEDTLS_ERR_PK_ALLOC_FAILED; } if (fread(*buf, 1, *n, f) != *n) { fclose(f); mbedtls_zeroize_and_free(*buf, *n); return MBEDTLS_ERR_PK_FILE_IO_ERROR; } fclose(f); (*buf)[*n] = '\0'; if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { ++*n; } return 0; } /* * Load and parse a private key */ int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, const char *path, const char *pwd, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } if (pwd == NULL) { ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng); } else { ret = mbedtls_pk_parse_key(ctx, buf, n, (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng); } mbedtls_zeroize_and_free(buf, n); return ret; } /* * Load and parse a public key */ int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_pk_parse_public_key(ctx, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_PK_PARSE_C */ webfakes/src/mbedtls/library/aesce.h0000644000176200001440000001076514740737024017200 0ustar liggesusers/** * \file aesce.h * * \brief Support hardware AES acceleration on Armv8-A processors with * the Armv8-A Cryptographic Extension. * * \warning These functions are only for internal use by other library * functions; you must not call them directly. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_AESCE_H #define MBEDTLS_AESCE_H #include "mbedtls/build_info.h" #include "common.h" #include "mbedtls/aes.h" #if defined(MBEDTLS_AESCE_C) \ && defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_HAVE_NEON_INTRINSICS) \ && (defined(MBEDTLS_COMPILER_IS_GCC) || defined(__clang__) || defined(MSC_VER)) /* MBEDTLS_AESCE_HAVE_CODE is defined if we have a suitable target platform, and a * potentially suitable compiler (compiler version & flags are not checked when defining * this). */ #define MBEDTLS_AESCE_HAVE_CODE #ifdef __cplusplus extern "C" { #endif #if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) extern signed char mbedtls_aesce_has_support_result; /** * \brief Internal function to detect the crypto extension in CPUs. * * \return 1 if CPU has support for the feature, 0 otherwise */ int mbedtls_aesce_has_support_impl(void); #define MBEDTLS_AESCE_HAS_SUPPORT() (mbedtls_aesce_has_support_result == -1 ? \ mbedtls_aesce_has_support_impl() : \ mbedtls_aesce_has_support_result) #else /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */ /* If we are not on Linux, we can't detect support so assume that it's supported. * Similarly, assume support if MBEDTLS_AES_USE_HARDWARE_ONLY is set. */ #define MBEDTLS_AESCE_HAS_SUPPORT() 1 #endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */ /** * \brief Internal AES-ECB block encryption and decryption * * \warning This assumes that the context specifies either 10, 12 or 14 * rounds and will behave incorrectly if this is not the case. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT * \param input 16-byte input block * \param output 16-byte output block * * \return 0 on success (cannot fail) */ int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); /** * \brief Internal GCM multiplication: c = a * b in GF(2^128) * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param c Result * \param a First operand * \param b Second operand * * \note Both operands and result are bit strings interpreted as * elements of GF(2^128) as per the GCM spec. */ void mbedtls_aesce_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Internal round key inversion. This function computes * decryption round keys from the encryption round keys. * * \param invkey Round keys for the equivalent inverse cipher * \param fwdkey Original round keys (for encryption) * \param nr Number of rounds (that is, number of round keys minus one) */ void mbedtls_aesce_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief Internal key expansion for encryption * * \param rk Destination buffer where the round keys are written * \param key Encryption key * \param bits Key size in bits (must be 128, 192 or 256) * * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH */ int mbedtls_aesce_setkey_enc(unsigned char *rk, const unsigned char *key, size_t bits); #ifdef __cplusplus } #endif #else #if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) && defined(MBEDTLS_ARCH_IS_ARMV8_A) #error "AES hardware acceleration not supported on this platform / compiler" #endif #endif /* MBEDTLS_AESCE_C && MBEDTLS_ARCH_IS_ARMV8_A && MBEDTLS_HAVE_NEON_INTRINSICS && (MBEDTLS_COMPILER_IS_GCC || __clang__ || MSC_VER) */ #endif /* MBEDTLS_AESCE_H */ webfakes/src/mbedtls/library/ecp_invasive.h0000644000176200001440000003252214740737024020566 0ustar liggesusers/** * \file ecp_invasive.h * * \brief ECP module: interfaces for invasive testing only. * * The interfaces in this file are intended for testing purposes only. * They SHOULD NOT be made available in library integrations except when * building the library for testing. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECP_INVASIVE_H #define MBEDTLS_ECP_INVASIVE_H #include "common.h" #include "mbedtls/bignum.h" #include "bignum_mod.h" #include "mbedtls/ecp.h" /* * Curve modulus types */ typedef enum { MBEDTLS_ECP_MOD_NONE = 0, MBEDTLS_ECP_MOD_COORDINATE, MBEDTLS_ECP_MOD_SCALAR } mbedtls_ecp_modulus_type; typedef enum { MBEDTLS_ECP_VARIANT_NONE = 0, MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT, MBEDTLS_ECP_VARIANT_WITH_MPI_UINT } mbedtls_ecp_variant; #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_LIGHT) /** Queries the ecp variant. * * \return The id of the ecp variant. */ MBEDTLS_STATIC_TESTABLE mbedtls_ecp_variant mbedtls_ecp_get_variant(void); #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) /** Generate a private key on a Montgomery curve (Curve25519 or Curve448). * * This function implements key generation for the set of secret keys * specified in [Curve25519] p. 5 and in [Curve448]. The resulting value * has the lower bits masked but is not necessarily canonical. * * \note - [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf * - [RFC7748] https://tools.ietf.org/html/rfc7748 * * \p high_bit The position of the high-order bit of the key to generate. * This is the bit-size of the key minus 1: * 254 for Curve25519 or 447 for Curve448. * \param d The randomly generated key. This is a number of size * exactly \p high_bit + 1 bits, with the least significant bits * masked as specified in [Curve25519] and in [RFC7748] §5. * \param f_rng The RNG function. * \param p_rng The RNG context to be passed to \p f_rng. * * \return \c 0 on success. * \return \c MBEDTLS_ERR_ECP_xxx or MBEDTLS_ERR_MPI_xxx on failure. */ int mbedtls_ecp_gen_privkey_mx(size_t high_bit, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) /** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) * * This operation expects a 384 bit MPI and the result of the reduction * is a 192 bit MPI. * * \param[in,out] Np The address of the MPI to be converted. * Must have twice as many limbs as the modulus. * Upon return this holds the reduced value. The bitlength * of the reduced value is the same as that of the modulus * (192 bits). * \param[in] Nn The length of \p Np in limbs. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) /** Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 448-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (224 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the * limb size that sores a 448-bit MPI. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) /** Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 512-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (256 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the * limb size that sores a 512-bit MPI. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) /** Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5) * * \param[in,out] X The address of the MPI to be converted. * Must have twice as many limbs as the modulus * (the modulus is 521 bits long). Upon return this * holds the reduced value. The reduced value is * in range `0 <= X < 2 * N` (where N is the modulus). * and its the bitlength is one plus the bitlength * of the modulus. * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs does not have * twice as many limbs as the modulus. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /** Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 768-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (384 bits). * \param[in] X_limbs The length of \p N in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p N_n does not have * twice as many limbs as the modulus. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) /** Fast quasi-reduction modulo p192k1 = 2^192 - R, * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 384-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (192 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) /** Fast quasi-reduction modulo p224k1 = 2^224 - R, * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 448-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (224 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /** Fast quasi-reduction modulo p256k1 = 2^256 - R, * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 512-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (256 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /** Fast quasi-reduction modulo p255 = 2^255 - 19 * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 510-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /** Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 + * (B0 + B1) * 2^224. * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 896-bit MPI * (double the bitlength of the modulus). Upon return * holds the reduced value which is in range `0 <= X < * N` (where N is the modulus). The bitlength of the * reduced value is the same as that of the modulus * (448 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on Success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation * failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ /** Initialise a modulus with hard-coded const curve data. * * \note The caller is responsible for the \p N modulus' memory. * mbedtls_mpi_mod_modulus_free(&N) should be invoked at the * end of its lifecycle. * * \param[in,out] N The address of the modulus structure to populate. * Must be initialized. * \param[in] id The mbedtls_ecp_group_id for which to initialise the modulus. * \param[in] ctype The mbedtls_ecp_modulus_type identifier for a coordinate modulus (P) * or a scalar modulus (N). * * \return \c 0 if successful. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the given MPIs do not * have the correct number of limbs. * */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_ecp_group_id id, const mbedtls_ecp_modulus_type ctype); #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_INVASIVE_H */ webfakes/src/mbedtls/library/des.c0000644000176200001440000007663214740737024016673 0ustar liggesusers/* * FIPS-46-3 compliant Triple-DES implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * DES, on which TDES is based, was originally designed by Horst Feistel * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). * * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf */ #include "common.h" #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_DES_ALT) /* * Expanded DES S-boxes */ static const uint32_t SB1[64] = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 }; static const uint32_t SB2[64] = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 }; static const uint32_t SB3[64] = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 }; static const uint32_t SB4[64] = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 }; static const uint32_t SB5[64] = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 }; static const uint32_t SB6[64] = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 }; static const uint32_t SB7[64] = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 }; static const uint32_t SB8[64] = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 }; /* * PC1: left and right halves bit-swap */ static const uint32_t LHs[16] = { 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101, 0x01010000, 0x01010001, 0x01010100, 0x01010101 }; static const uint32_t RHs[16] = { 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100, 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001, 0x00000101, 0x01000101, 0x00010101, 0x01010101, }; /* * Initial Permutation macro */ #define DES_IP(X, Y) \ do \ { \ T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ (Y) = (((Y) << 1) | ((Y) >> 31)) & 0xFFFFFFFF; \ T = ((X) ^ (Y)) & 0xAAAAAAAA; (Y) ^= T; (X) ^= T; \ (X) = (((X) << 1) | ((X) >> 31)) & 0xFFFFFFFF; \ } while (0) /* * Final Permutation macro */ #define DES_FP(X, Y) \ do \ { \ (X) = (((X) << 31) | ((X) >> 1)) & 0xFFFFFFFF; \ T = ((X) ^ (Y)) & 0xAAAAAAAA; (X) ^= T; (Y) ^= T; \ (Y) = (((Y) << 31) | ((Y) >> 1)) & 0xFFFFFFFF; \ T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ } while (0) /* * DES round macro */ #define DES_ROUND(X, Y) \ do \ { \ T = *SK++ ^ (X); \ (Y) ^= SB8[(T) & 0x3F] ^ \ SB6[(T >> 8) & 0x3F] ^ \ SB4[(T >> 16) & 0x3F] ^ \ SB2[(T >> 24) & 0x3F]; \ \ T = *SK++ ^ (((X) << 28) | ((X) >> 4)); \ (Y) ^= SB7[(T) & 0x3F] ^ \ SB5[(T >> 8) & 0x3F] ^ \ SB3[(T >> 16) & 0x3F] ^ \ SB1[(T >> 24) & 0x3F]; \ } while (0) #define SWAP(a, b) \ do \ { \ uint32_t t = (a); (a) = (b); (b) = t; t = 0; \ } while (0) void mbedtls_des_init(mbedtls_des_context *ctx) { memset(ctx, 0, sizeof(mbedtls_des_context)); } void mbedtls_des_free(mbedtls_des_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_des_context)); } void mbedtls_des3_init(mbedtls_des3_context *ctx) { memset(ctx, 0, sizeof(mbedtls_des3_context)); } void mbedtls_des3_free(mbedtls_des3_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_des3_context)); } static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, 254 }; void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) { key[i] = odd_parity_table[key[i] / 2]; } } /* * Check the given key's parity, returns 1 on failure, 0 on SUCCESS */ int mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) { if (key[i] != odd_parity_table[key[i] / 2]) { return 1; } } return 0; } /* * Table of weak and semi-weak keys * * Source: http://en.wikipedia.org/wiki/Weak_key * * Weak: * Alternating ones + zeros (0x0101010101010101) * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) * '0xE0E0E0E0F1F1F1F1' * '0x1F1F1F1F0E0E0E0E' * * Semi-weak: * 0x011F011F010E010E and 0x1F011F010E010E01 * 0x01E001E001F101F1 and 0xE001E001F101F101 * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 * */ #define WEAK_KEY_COUNT 16 static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } }; int mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; for (i = 0; i < WEAK_KEY_COUNT; i++) { if (memcmp(weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0) { return 1; } } return 0; } #if !defined(MBEDTLS_DES_SETKEY_ALT) void mbedtls_des_setkey(uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; uint32_t X, Y, T; X = MBEDTLS_GET_UINT32_BE(key, 0); Y = MBEDTLS_GET_UINT32_BE(key, 4); /* * Permuted Choice 1 */ T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); T = ((Y) ^ X) & 0x10101010; X ^= T; Y ^= (T); X = (LHs[(X) & 0xF] << 3) | (LHs[(X >> 8) & 0xF] << 2) | (LHs[(X >> 16) & 0xF] << 1) | (LHs[(X >> 24) & 0xF]) | (LHs[(X >> 5) & 0xF] << 7) | (LHs[(X >> 13) & 0xF] << 6) | (LHs[(X >> 21) & 0xF] << 5) | (LHs[(X >> 29) & 0xF] << 4); Y = (RHs[(Y >> 1) & 0xF] << 3) | (RHs[(Y >> 9) & 0xF] << 2) | (RHs[(Y >> 17) & 0xF] << 1) | (RHs[(Y >> 25) & 0xF]) | (RHs[(Y >> 4) & 0xF] << 7) | (RHs[(Y >> 12) & 0xF] << 6) | (RHs[(Y >> 20) & 0xF] << 5) | (RHs[(Y >> 28) & 0xF] << 4); X &= 0x0FFFFFFF; Y &= 0x0FFFFFFF; /* * calculate subkeys */ for (i = 0; i < 16; i++) { if (i < 2 || i == 8 || i == 15) { X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; } else { X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; } *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) | ((Y >> 14) & 0x00000200) | ((Y) & 0x00000100) | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) | ((Y) & 0x00000200) | ((Y << 7) & 0x00000100) | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); } } #endif /* !MBEDTLS_DES_SETKEY_ALT */ /* * DES key schedule (56-bit, encryption) */ int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { mbedtls_des_setkey(ctx->sk, key); return 0; } /* * DES key schedule (56-bit, decryption) */ int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; mbedtls_des_setkey(ctx->sk, key); for (i = 0; i < 16; i += 2) { SWAP(ctx->sk[i], ctx->sk[30 - i]); SWAP(ctx->sk[i + 1], ctx->sk[31 - i]); } return 0; } static void des3_set2key(uint32_t esk[96], uint32_t dsk[96], const unsigned char key[MBEDTLS_DES_KEY_SIZE*2]) { int i; mbedtls_des_setkey(esk, key); mbedtls_des_setkey(dsk + 32, key + 8); for (i = 0; i < 32; i += 2) { dsk[i] = esk[30 - i]; dsk[i + 1] = esk[31 - i]; esk[i + 32] = dsk[62 - i]; esk[i + 33] = dsk[63 - i]; esk[i + 64] = esk[i]; esk[i + 65] = esk[i + 1]; dsk[i + 64] = dsk[i]; dsk[i + 65] = dsk[i + 1]; } } /* * Triple-DES key schedule (112-bit, encryption) */ int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]) { uint32_t sk[96]; des3_set2key(ctx->sk, sk, key); mbedtls_platform_zeroize(sk, sizeof(sk)); return 0; } /* * Triple-DES key schedule (112-bit, decryption) */ int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]) { uint32_t sk[96]; des3_set2key(sk, ctx->sk, key); mbedtls_platform_zeroize(sk, sizeof(sk)); return 0; } static void des3_set3key(uint32_t esk[96], uint32_t dsk[96], const unsigned char key[24]) { int i; mbedtls_des_setkey(esk, key); mbedtls_des_setkey(dsk + 32, key + 8); mbedtls_des_setkey(esk + 64, key + 16); for (i = 0; i < 32; i += 2) { dsk[i] = esk[94 - i]; dsk[i + 1] = esk[95 - i]; esk[i + 32] = dsk[62 - i]; esk[i + 33] = dsk[63 - i]; dsk[i + 64] = esk[30 - i]; dsk[i + 65] = esk[31 - i]; } } /* * Triple-DES key schedule (168-bit, encryption) */ int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]) { uint32_t sk[96]; des3_set3key(ctx->sk, sk, key); mbedtls_platform_zeroize(sk, sizeof(sk)); return 0; } /* * Triple-DES key schedule (168-bit, decryption) */ int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]) { uint32_t sk[96]; des3_set3key(sk, ctx->sk, key); mbedtls_platform_zeroize(sk, sizeof(sk)); return 0; } /* * DES-ECB block encryption/decryption */ #if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx, const unsigned char input[8], unsigned char output[8]) { int i; uint32_t X, Y, T, *SK; SK = ctx->sk; X = MBEDTLS_GET_UINT32_BE(input, 0); Y = MBEDTLS_GET_UINT32_BE(input, 4); DES_IP(X, Y); for (i = 0; i < 8; i++) { DES_ROUND(Y, X); DES_ROUND(X, Y); } DES_FP(Y, X); MBEDTLS_PUT_UINT32_BE(Y, output, 0); MBEDTLS_PUT_UINT32_BE(X, output, 4); return 0; } #endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * DES-CBC buffer encryption/decryption */ int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, int mode, size_t length, unsigned char iv[8], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char temp[8]; if (length % 8) { return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH; } if (mode == MBEDTLS_DES_ENCRYPT) { while (length > 0) { mbedtls_xor(output, input, iv, 8); ret = mbedtls_des_crypt_ecb(ctx, output, output); if (ret != 0) { goto exit; } memcpy(iv, output, 8); input += 8; output += 8; length -= 8; } } else { /* MBEDTLS_DES_DECRYPT */ while (length > 0) { memcpy(temp, input, 8); ret = mbedtls_des_crypt_ecb(ctx, input, output); if (ret != 0) { goto exit; } mbedtls_xor(output, output, iv, 8); memcpy(iv, temp, 8); input += 8; output += 8; length -= 8; } } ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ /* * 3DES-ECB block encryption/decryption */ #if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx, const unsigned char input[8], unsigned char output[8]) { int i; uint32_t X, Y, T, *SK; SK = ctx->sk; X = MBEDTLS_GET_UINT32_BE(input, 0); Y = MBEDTLS_GET_UINT32_BE(input, 4); DES_IP(X, Y); for (i = 0; i < 8; i++) { DES_ROUND(Y, X); DES_ROUND(X, Y); } for (i = 0; i < 8; i++) { DES_ROUND(X, Y); DES_ROUND(Y, X); } for (i = 0; i < 8; i++) { DES_ROUND(Y, X); DES_ROUND(X, Y); } DES_FP(Y, X); MBEDTLS_PUT_UINT32_BE(Y, output, 0); MBEDTLS_PUT_UINT32_BE(X, output, 4); return 0; } #endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * 3DES-CBC buffer encryption/decryption */ int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, int mode, size_t length, unsigned char iv[8], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char temp[8]; if (length % 8) { return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH; } if (mode == MBEDTLS_DES_ENCRYPT) { while (length > 0) { mbedtls_xor(output, input, iv, 8); ret = mbedtls_des3_crypt_ecb(ctx, output, output); if (ret != 0) { goto exit; } memcpy(iv, output, 8); input += 8; output += 8; length -= 8; } } else { /* MBEDTLS_DES_DECRYPT */ while (length > 0) { memcpy(temp, input, 8); ret = mbedtls_des3_crypt_ecb(ctx, input, output); if (ret != 0) { goto exit; } mbedtls_xor(output, output, iv, 8); memcpy(iv, temp, 8); input += 8; output += 8; length -= 8; } } ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* !MBEDTLS_DES_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * DES and 3DES test vectors from: * * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip */ static const unsigned char des3_test_keys[24] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 }; static const unsigned char des3_test_buf[8] = { 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 }; static const unsigned char des3_test_ecb_dec[3][8] = { { 0x37, 0x2B, 0x98, 0xBF, 0x52, 0x65, 0xB0, 0x59 }, { 0xC2, 0x10, 0x19, 0x9C, 0x38, 0x5A, 0x65, 0xA1 }, { 0xA2, 0x70, 0x56, 0x68, 0x69, 0xE5, 0x15, 0x1D } }; static const unsigned char des3_test_ecb_enc[3][8] = { { 0x1C, 0xD5, 0x97, 0xEA, 0x84, 0x26, 0x73, 0xFB }, { 0xB3, 0x92, 0x4D, 0xF3, 0xC5, 0xB5, 0x42, 0x93 }, { 0xDA, 0x37, 0x64, 0x41, 0xBA, 0x6F, 0x62, 0x6F } }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const unsigned char des3_test_iv[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, }; static const unsigned char des3_test_cbc_dec[3][8] = { { 0x58, 0xD9, 0x48, 0xEF, 0x85, 0x14, 0x65, 0x9A }, { 0x5F, 0xC8, 0x78, 0xD4, 0xD7, 0x92, 0xD9, 0x54 }, { 0x25, 0xF9, 0x75, 0x85, 0xA8, 0x1E, 0x48, 0xBF } }; static const unsigned char des3_test_cbc_enc[3][8] = { { 0x91, 0x1C, 0x6D, 0xCF, 0x48, 0xA7, 0xC3, 0x4D }, { 0x60, 0x1A, 0x76, 0x8F, 0xA1, 0xF9, 0x66, 0xF1 }, { 0xA1, 0x50, 0x0F, 0x99, 0xB2, 0xCD, 0x64, 0x76 } }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ /* * Checkup routine */ int mbedtls_des_self_test(int verbose) { int i, j, u, v, ret = 0; mbedtls_des_context ctx; mbedtls_des3_context ctx3; unsigned char buf[8]; #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char prv[8]; unsigned char iv[8]; #endif mbedtls_des_init(&ctx); mbedtls_des3_init(&ctx3); /* * ECB mode */ for (i = 0; i < 6; i++) { u = i >> 1; v = i & 1; if (verbose != 0) { mbedtls_printf(" DES%c-ECB-%3d (%s): ", (u == 0) ? ' ' : '3', 56 + u * 56, (v == MBEDTLS_DES_DECRYPT) ? "dec" : "enc"); } memcpy(buf, des3_test_buf, 8); switch (i) { case 0: ret = mbedtls_des_setkey_dec(&ctx, des3_test_keys); break; case 1: ret = mbedtls_des_setkey_enc(&ctx, des3_test_keys); break; case 2: ret = mbedtls_des3_set2key_dec(&ctx3, des3_test_keys); break; case 3: ret = mbedtls_des3_set2key_enc(&ctx3, des3_test_keys); break; case 4: ret = mbedtls_des3_set3key_dec(&ctx3, des3_test_keys); break; case 5: ret = mbedtls_des3_set3key_enc(&ctx3, des3_test_keys); break; default: return 1; } if (ret != 0) { goto exit; } for (j = 0; j < 100; j++) { if (u == 0) { ret = mbedtls_des_crypt_ecb(&ctx, buf, buf); } else { ret = mbedtls_des3_crypt_ecb(&ctx3, buf, buf); } if (ret != 0) { goto exit; } } if ((v == MBEDTLS_DES_DECRYPT && memcmp(buf, des3_test_ecb_dec[u], 8) != 0) || (v != MBEDTLS_DES_DECRYPT && memcmp(buf, des3_test_ecb_enc[u], 8) != 0)) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * CBC mode */ for (i = 0; i < 6; i++) { u = i >> 1; v = i & 1; if (verbose != 0) { mbedtls_printf(" DES%c-CBC-%3d (%s): ", (u == 0) ? ' ' : '3', 56 + u * 56, (v == MBEDTLS_DES_DECRYPT) ? "dec" : "enc"); } memcpy(iv, des3_test_iv, 8); memcpy(prv, des3_test_iv, 8); memcpy(buf, des3_test_buf, 8); switch (i) { case 0: ret = mbedtls_des_setkey_dec(&ctx, des3_test_keys); break; case 1: ret = mbedtls_des_setkey_enc(&ctx, des3_test_keys); break; case 2: ret = mbedtls_des3_set2key_dec(&ctx3, des3_test_keys); break; case 3: ret = mbedtls_des3_set2key_enc(&ctx3, des3_test_keys); break; case 4: ret = mbedtls_des3_set3key_dec(&ctx3, des3_test_keys); break; case 5: ret = mbedtls_des3_set3key_enc(&ctx3, des3_test_keys); break; default: return 1; } if (ret != 0) { goto exit; } if (v == MBEDTLS_DES_DECRYPT) { for (j = 0; j < 100; j++) { if (u == 0) { ret = mbedtls_des_crypt_cbc(&ctx, v, 8, iv, buf, buf); } else { ret = mbedtls_des3_crypt_cbc(&ctx3, v, 8, iv, buf, buf); } if (ret != 0) { goto exit; } } } else { for (j = 0; j < 100; j++) { unsigned char tmp[8]; if (u == 0) { ret = mbedtls_des_crypt_cbc(&ctx, v, 8, iv, buf, buf); } else { ret = mbedtls_des3_crypt_cbc(&ctx3, v, 8, iv, buf, buf); } if (ret != 0) { goto exit; } memcpy(tmp, prv, 8); memcpy(prv, buf, 8); memcpy(buf, tmp, 8); } memcpy(buf, prv, 8); } if ((v == MBEDTLS_DES_DECRYPT && memcmp(buf, des3_test_cbc_dec[u], 8) != 0) || (v != MBEDTLS_DES_DECRYPT && memcmp(buf, des3_test_cbc_enc[u], 8) != 0)) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } #endif /* MBEDTLS_CIPHER_MODE_CBC */ if (verbose != 0) { mbedtls_printf("\n"); } exit: mbedtls_des_free(&ctx); mbedtls_des3_free(&ctx3); if (ret != 0) { ret = 1; } return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_DES_C */ webfakes/src/mbedtls/library/psa_crypto_ffdh.h0000644000176200001440000001240014740737024021256 0ustar liggesusers/* * PSA FFDH layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_FFDH_H #define PSA_CRYPTO_FFDH_H #include /** Perform a key agreement and return the FFDH shared secret. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] peer_key The buffer containing the key context * of the peer's public key. * \param[in] peer_key_length Size of the \p peer_key buffer in * bytes. * \param[in] key_buffer The buffer containing the private key * context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in * bytes. * \param[out] shared_secret The buffer to which the shared secret * is to be written. * \param[in] shared_secret_size Size of the \p shared_secret buffer in * bytes. * \param[out] shared_secret_length On success, the number of bytes that make * up the returned shared secret. * \retval #PSA_SUCCESS * Success. Shared secret successfully calculated. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key_buffer_size, \p peer_key_length, \p shared_secret_size * do not match * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_ffdh_key_agreement( const psa_key_attributes_t *attributes, const uint8_t *peer_key, size_t peer_key_length, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length); /** Export a public key or the public part of a DH key pair in binary format. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data * * \retval #PSA_SUCCESS The public key was exported successfully. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_ffdh_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** * \brief Generate DH key. * * \note The signature of the function is that of a PSA driver generate_key * entry point. * * \param[in] attributes The attributes for the key to generate. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in * \p key_buffer. * * \retval #PSA_SUCCESS * The key was generated successfully. * \retval #PSA_ERROR_NOT_SUPPORTED * Key size in bits is invalid. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_ffdh_generate_key( const psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); /** * \brief Import DH key. * * \note The signature of the function is that of a PSA driver import_key * entry point. * * \param[in] attributes The attributes for the key to import. * \param[in] data The buffer containing the key data in import * format. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] key_buffer The buffer containing the key data in output * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p * key_buffer in bytes. * \param[out] bits The key size in number of bits. * * \retval #PSA_SUCCESS * The key was generated successfully. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. */ psa_status_t mbedtls_psa_ffdh_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits); #endif /* PSA_CRYPTO_FFDH_H */ webfakes/src/mbedtls/library/ecp_curves.c0000644000176200001440000115242314740737024020250 0ustar liggesusers/* * Elliptic curves over GF(p): curve-specific data and functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if !defined(MBEDTLS_ECP_WITH_MPI_UINT) #if defined(MBEDTLS_ECP_LIGHT) #include "mbedtls/ecp.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "bn_mul.h" #include "bignum_core.h" #include "ecp_invasive.h" #include #if !defined(MBEDTLS_ECP_ALT) #define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) } #define ECP_MPI_INIT_ARRAY(x) \ ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) #define ECP_POINT_INIT_XY_Z0(x, y) { \ ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) } #define ECP_POINT_INIT_XY_Z1(x, y) { \ ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) } #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* For these curves, we build the group parameters dynamically. */ #define ECP_LOAD_GROUP static const mbedtls_mpi_uint mpi_one[] = { 1 }; #endif /* * Note: the constants are in little-endian order * to be directly usable in MPIs */ /* * Domain parameters for secp192r1 */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static const mbedtls_mpi_uint secp192r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp192r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64), }; static const mbedtls_mpi_uint secp192r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), }; static const mbedtls_mpi_uint secp192r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), }; static const mbedtls_mpi_uint secp192r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp192r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), }; static const mbedtls_mpi_uint secp192r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), }; static const mbedtls_mpi_uint secp192r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED), }; static const mbedtls_mpi_uint secp192r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E), }; static const mbedtls_mpi_uint secp192r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E), }; static const mbedtls_mpi_uint secp192r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14), }; static const mbedtls_mpi_uint secp192r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2), }; static const mbedtls_mpi_uint secp192r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB), }; static const mbedtls_mpi_uint secp192r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7), }; static const mbedtls_mpi_uint secp192r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2), }; static const mbedtls_mpi_uint secp192r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62), }; static const mbedtls_mpi_uint secp192r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC), }; static const mbedtls_mpi_uint secp192r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F), }; static const mbedtls_mpi_uint secp192r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55), }; static const mbedtls_mpi_uint secp192r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF), }; static const mbedtls_mpi_uint secp192r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31), }; static const mbedtls_mpi_uint secp192r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC), }; static const mbedtls_mpi_uint secp192r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83), }; static const mbedtls_mpi_uint secp192r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98), }; static const mbedtls_mpi_uint secp192r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5), }; static const mbedtls_mpi_uint secp192r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD), }; static const mbedtls_mpi_uint secp192r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F), }; static const mbedtls_mpi_uint secp192r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD), }; static const mbedtls_mpi_uint secp192r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A), }; static const mbedtls_mpi_uint secp192r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66), }; static const mbedtls_mpi_uint secp192r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7), }; static const mbedtls_mpi_uint secp192r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45), }; static const mbedtls_mpi_uint secp192r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71), }; static const mbedtls_mpi_uint secp192r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC), }; static const mbedtls_mpi_uint secp192r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2), }; static const mbedtls_mpi_uint secp192r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48), }; static const mbedtls_mpi_uint secp192r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C), }; static const mbedtls_ecp_point secp192r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y), }; #else #define secp192r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ /* * Domain parameters for secp224r1 */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static const mbedtls_mpi_uint secp224r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C), MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4), }; static const mbedtls_mpi_uint secp224r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7), }; static const mbedtls_mpi_uint secp224r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD), }; static const mbedtls_mpi_uint secp224r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp224r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp224r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y), }; #else #define secp224r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ /* * Domain parameters for secp256r1 */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) static const mbedtls_mpi_uint secp256r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp256r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A), }; static const mbedtls_mpi_uint secp256r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), }; static const mbedtls_mpi_uint secp256r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), }; static const mbedtls_mpi_uint secp256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp256r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), }; static const mbedtls_mpi_uint secp256r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), }; static const mbedtls_mpi_uint secp256r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C), }; static const mbedtls_mpi_uint secp256r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4), }; static const mbedtls_mpi_uint secp256r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6), }; static const mbedtls_mpi_uint secp256r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20), }; static const mbedtls_mpi_uint secp256r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62), }; static const mbedtls_mpi_uint secp256r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7), }; static const mbedtls_mpi_uint secp256r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00), }; static const mbedtls_mpi_uint secp256r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03), }; static const mbedtls_mpi_uint secp256r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C), }; static const mbedtls_mpi_uint secp256r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3), }; static const mbedtls_mpi_uint secp256r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED), }; static const mbedtls_mpi_uint secp256r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3), }; static const mbedtls_mpi_uint secp256r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95), }; static const mbedtls_mpi_uint secp256r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68), }; static const mbedtls_mpi_uint secp256r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54), }; static const mbedtls_mpi_uint secp256r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6), }; static const mbedtls_mpi_uint secp256r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE), }; static const mbedtls_mpi_uint secp256r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4), }; static const mbedtls_mpi_uint secp256r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86), }; static const mbedtls_mpi_uint secp256r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16), }; static const mbedtls_mpi_uint secp256r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18), }; static const mbedtls_mpi_uint secp256r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C), }; static const mbedtls_mpi_uint secp256r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6), }; static const mbedtls_mpi_uint secp256r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF), }; static const mbedtls_mpi_uint secp256r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E), }; static const mbedtls_mpi_uint secp256r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44), }; static const mbedtls_mpi_uint secp256r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4), }; static const mbedtls_mpi_uint secp256r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7), }; static const mbedtls_mpi_uint secp256r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82), }; static const mbedtls_mpi_uint secp256r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43), }; static const mbedtls_ecp_point secp256r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y), }; #else #define secp256r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ /* * Domain parameters for secp384r1 */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) static const mbedtls_mpi_uint secp384r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp384r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3), }; static const mbedtls_mpi_uint secp384r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), }; static const mbedtls_mpi_uint secp384r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), }; static const mbedtls_mpi_uint secp384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp384r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), }; static const mbedtls_mpi_uint secp384r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD), }; static const mbedtls_mpi_uint secp384r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23), }; static const mbedtls_mpi_uint secp384r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE), }; static const mbedtls_mpi_uint secp384r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3), }; static const mbedtls_mpi_uint secp384r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD), }; static const mbedtls_mpi_uint secp384r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F), }; static const mbedtls_mpi_uint secp384r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48), }; static const mbedtls_mpi_uint secp384r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A), }; static const mbedtls_mpi_uint secp384r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08), }; static const mbedtls_mpi_uint secp384r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F), }; static const mbedtls_mpi_uint secp384r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74), }; static const mbedtls_mpi_uint secp384r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03), }; static const mbedtls_mpi_uint secp384r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB), }; static const mbedtls_mpi_uint secp384r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF), }; static const mbedtls_mpi_uint secp384r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97), }; static const mbedtls_mpi_uint secp384r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71), }; static const mbedtls_mpi_uint secp384r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5), }; static const mbedtls_mpi_uint secp384r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91), }; static const mbedtls_mpi_uint secp384r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5), }; static const mbedtls_mpi_uint secp384r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15), }; static const mbedtls_mpi_uint secp384r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98), }; static const mbedtls_mpi_uint secp384r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F), }; static const mbedtls_mpi_uint secp384r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10), }; static const mbedtls_mpi_uint secp384r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1), }; static const mbedtls_mpi_uint secp384r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0), }; static const mbedtls_mpi_uint secp384r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC), }; static const mbedtls_mpi_uint secp384r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6), }; static const mbedtls_mpi_uint secp384r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A), }; static const mbedtls_mpi_uint secp384r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53), }; static const mbedtls_mpi_uint secp384r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC), }; static const mbedtls_mpi_uint secp384r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85), }; static const mbedtls_mpi_uint secp384r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23), }; static const mbedtls_mpi_uint secp384r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3), }; static const mbedtls_mpi_uint secp384r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6), }; static const mbedtls_mpi_uint secp384r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67), }; static const mbedtls_mpi_uint secp384r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC), }; static const mbedtls_mpi_uint secp384r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE), }; static const mbedtls_mpi_uint secp384r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05), }; static const mbedtls_mpi_uint secp384r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA), }; static const mbedtls_mpi_uint secp384r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF), }; static const mbedtls_mpi_uint secp384r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63), }; static const mbedtls_mpi_uint secp384r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1), }; static const mbedtls_mpi_uint secp384r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D), }; static const mbedtls_mpi_uint secp384r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D), }; static const mbedtls_mpi_uint secp384r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF), }; static const mbedtls_mpi_uint secp384r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71), }; static const mbedtls_mpi_uint secp384r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B), }; static const mbedtls_mpi_uint secp384r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F), }; static const mbedtls_mpi_uint secp384r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E), }; static const mbedtls_mpi_uint secp384r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2), }; static const mbedtls_mpi_uint secp384r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7), }; static const mbedtls_mpi_uint secp384r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21), }; static const mbedtls_mpi_uint secp384r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6), }; static const mbedtls_mpi_uint secp384r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E), }; static const mbedtls_mpi_uint secp384r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6), }; static const mbedtls_mpi_uint secp384r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42), }; static const mbedtls_mpi_uint secp384r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12), }; static const mbedtls_mpi_uint secp384r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77), }; static const mbedtls_mpi_uint secp384r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B), }; static const mbedtls_mpi_uint secp384r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41), }; static const mbedtls_ecp_point secp384r1_T[32] = { ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y), }; #else #define secp384r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ /* * Domain parameters for secp521r1 */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) static const mbedtls_mpi_uint secp521r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), }; static const mbedtls_mpi_uint secp521r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95), MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00), }; static const mbedtls_mpi_uint secp521r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00), }; static const mbedtls_mpi_uint secp521r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01), }; static const mbedtls_mpi_uint secp521r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp521r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp521r1_T[32] = { ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y), }; #else #define secp521r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static const mbedtls_mpi_uint secp192k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp192k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp192k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00), }; static const mbedtls_mpi_uint secp192k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), }; static const mbedtls_mpi_uint secp192k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), }; static const mbedtls_mpi_uint secp192k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp192k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), }; static const mbedtls_mpi_uint secp192k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), }; static const mbedtls_mpi_uint secp192k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E), }; static const mbedtls_mpi_uint secp192k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7), }; static const mbedtls_mpi_uint secp192k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28), }; static const mbedtls_mpi_uint secp192k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4), }; static const mbedtls_mpi_uint secp192k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C), }; static const mbedtls_mpi_uint secp192k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A), }; static const mbedtls_mpi_uint secp192k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF), }; static const mbedtls_mpi_uint secp192k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F), }; static const mbedtls_mpi_uint secp192k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9), }; static const mbedtls_mpi_uint secp192k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D), }; static const mbedtls_mpi_uint secp192k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5), }; static const mbedtls_mpi_uint secp192k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B), }; static const mbedtls_mpi_uint secp192k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC), }; static const mbedtls_mpi_uint secp192k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E), }; static const mbedtls_mpi_uint secp192k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82), }; static const mbedtls_mpi_uint secp192k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22), }; static const mbedtls_mpi_uint secp192k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05), }; static const mbedtls_mpi_uint secp192k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96), }; static const mbedtls_mpi_uint secp192k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D), }; static const mbedtls_mpi_uint secp192k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D), }; static const mbedtls_mpi_uint secp192k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67), }; static const mbedtls_mpi_uint secp192k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C), }; static const mbedtls_mpi_uint secp192k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF), }; static const mbedtls_mpi_uint secp192k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD), }; static const mbedtls_mpi_uint secp192k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8), }; static const mbedtls_mpi_uint secp192k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9), }; static const mbedtls_mpi_uint secp192k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76), }; static const mbedtls_mpi_uint secp192k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35), }; static const mbedtls_mpi_uint secp192k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63), }; static const mbedtls_mpi_uint secp192k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8), }; static const mbedtls_ecp_point secp192k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y), }; #else #define secp192k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) static const mbedtls_mpi_uint secp224k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp224k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00), }; static const mbedtls_mpi_uint secp224k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1), }; static const mbedtls_mpi_uint secp224k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E), }; static const mbedtls_mpi_uint secp224k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp224k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp224k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y), }; #else #define secp224k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) static const mbedtls_mpi_uint secp256k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp256k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp256k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00), }; static const mbedtls_mpi_uint secp256k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), }; static const mbedtls_mpi_uint secp256k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), }; static const mbedtls_mpi_uint secp256k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp256k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), }; static const mbedtls_mpi_uint secp256k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), }; static const mbedtls_mpi_uint secp256k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0), }; static const mbedtls_mpi_uint secp256k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC), }; static const mbedtls_mpi_uint secp256k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF), }; static const mbedtls_mpi_uint secp256k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4), }; static const mbedtls_mpi_uint secp256k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54), }; static const mbedtls_mpi_uint secp256k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE), }; static const mbedtls_mpi_uint secp256k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E), }; static const mbedtls_mpi_uint secp256k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0), }; static const mbedtls_mpi_uint secp256k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B), }; static const mbedtls_mpi_uint secp256k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1), }; static const mbedtls_mpi_uint secp256k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15), }; static const mbedtls_mpi_uint secp256k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05), }; static const mbedtls_mpi_uint secp256k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72), }; static const mbedtls_mpi_uint secp256k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22), }; static const mbedtls_mpi_uint secp256k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16), }; static const mbedtls_mpi_uint secp256k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E), }; static const mbedtls_mpi_uint secp256k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E), }; static const mbedtls_mpi_uint secp256k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D), }; static const mbedtls_mpi_uint secp256k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0), }; static const mbedtls_mpi_uint secp256k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01), }; static const mbedtls_mpi_uint secp256k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12), }; static const mbedtls_mpi_uint secp256k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25), }; static const mbedtls_mpi_uint secp256k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B), }; static const mbedtls_mpi_uint secp256k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B), }; static const mbedtls_mpi_uint secp256k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64), }; static const mbedtls_mpi_uint secp256k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F), }; static const mbedtls_mpi_uint secp256k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07), }; static const mbedtls_mpi_uint secp256k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9), }; static const mbedtls_mpi_uint secp256k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89), }; static const mbedtls_mpi_uint secp256k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB), }; static const mbedtls_ecp_point secp256k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y), }; #else #define secp256k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ /* * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) static const mbedtls_mpi_uint brainpoolP256r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), }; static const mbedtls_mpi_uint brainpoolP256r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D), }; static const mbedtls_mpi_uint brainpoolP256r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26), }; static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), }; static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), }; static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80), }; static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23), }; static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36), }; static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18), }; static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47), }; static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30), }; static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87), }; static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28), }; static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10), }; static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C), }; static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19), }; static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D), }; static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E), }; static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30), }; static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C), }; static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39), }; static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57), }; static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53), }; static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E), }; static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A), }; static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51), }; static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02), }; static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17), }; static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70), }; static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72), }; static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10), }; static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85), }; static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98), }; static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F), }; static const mbedtls_ecp_point brainpoolP256r1_T[16] = { ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y), }; #else #define brainpoolP256r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ /* * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) static const mbedtls_mpi_uint brainpoolP384r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), }; static const mbedtls_mpi_uint brainpoolP384r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B), }; static const mbedtls_mpi_uint brainpoolP384r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), }; static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), }; static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), }; static const mbedtls_mpi_uint brainpoolP384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E), }; static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63), }; static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73), }; static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22), }; static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17), }; static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C), }; static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68), }; static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82), }; static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E), }; static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03), }; static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39), }; static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35), }; static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31), }; static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28), }; static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61), }; static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03), }; static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27), }; static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31), }; static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00), }; static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55), }; static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78), }; static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81), }; static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63), }; static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54), }; static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77), }; static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81), }; static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01), }; static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79), }; static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89), }; static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68), }; static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88), }; static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44), }; static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59), }; static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42), }; static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01), }; static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12), }; static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18), }; static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12), }; static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19), }; static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10), }; static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70), }; static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73), }; static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22), }; static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F), }; static const mbedtls_ecp_point brainpoolP384r1_T[32] = { ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y), }; #else #define brainpoolP384r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ /* * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) static const mbedtls_mpi_uint brainpoolP512r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), }; static const mbedtls_mpi_uint brainpoolP512r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78), }; static const mbedtls_mpi_uint brainpoolP512r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D), }; static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), }; static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), }; static const mbedtls_mpi_uint brainpoolP512r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), }; static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22), }; static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41), }; static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88), }; static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36), }; static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26), }; static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2), }; static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49), }; static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20), }; static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99), }; static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33), }; static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01), }; static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14), }; static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42), }; static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37), }; static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12), }; static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16), }; static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34), }; static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02), }; static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5), }; static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11), }; static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54), }; static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F), }; static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31), }; static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A), }; static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63), }; static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54), }; static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24), }; static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20), }; static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93), }; static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82), }; static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11), }; static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35), }; static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61), }; static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A), }; static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90), }; static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18), }; static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F), }; static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34), }; static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42), }; static const mbedtls_ecp_point brainpoolP512r1_T[32] = { ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y), }; #else #define brainpoolP512r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(ECP_LOAD_GROUP) /* * Create an MPI from embedded constants * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint)) */ static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len) { X->s = 1; X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint)); X->p = (mbedtls_mpi_uint *) p; } /* * Set an MPI to static value 1 */ static inline void ecp_mpi_set1(mbedtls_mpi *X) { X->s = 1; X->n = 1; X->p = (mbedtls_mpi_uint *) mpi_one; /* X->p will not be modified so the cast is safe */ } /* * Make group available from embedded constants */ static int ecp_group_load(mbedtls_ecp_group *grp, const mbedtls_mpi_uint *p, size_t plen, const mbedtls_mpi_uint *a, size_t alen, const mbedtls_mpi_uint *b, size_t blen, const mbedtls_mpi_uint *gx, size_t gxlen, const mbedtls_mpi_uint *gy, size_t gylen, const mbedtls_mpi_uint *n, size_t nlen, const mbedtls_ecp_point *T) { ecp_mpi_load(&grp->P, p, plen); if (a != NULL) { ecp_mpi_load(&grp->A, a, alen); } ecp_mpi_load(&grp->B, b, blen); ecp_mpi_load(&grp->N, n, nlen); ecp_mpi_load(&grp->G.X, gx, gxlen); ecp_mpi_load(&grp->G.Y, gy, gylen); ecp_mpi_set1(&grp->G.Z); grp->pbits = mbedtls_mpi_bitlen(&grp->P); grp->nbits = mbedtls_mpi_bitlen(&grp->N); grp->h = 1; grp->T = (mbedtls_ecp_point *) T; /* * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free. */ grp->T_size = 0; return 0; } #endif /* ECP_LOAD_GROUP */ #if defined(MBEDTLS_ECP_NIST_OPTIM) /* Forward declarations */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static int ecp_mod_p192(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static int ecp_mod_p224(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) static int ecp_mod_p256(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) static int ecp_mod_p384(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) static int ecp_mod_p521(mbedtls_mpi *); #endif #define NIST_MODP(P) grp->modp = ecp_mod_ ## P; #else #define NIST_MODP(P) #endif /* MBEDTLS_ECP_NIST_OPTIM */ /* Additional forward declarations */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) static int ecp_mod_p255(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) static int ecp_mod_p448(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static int ecp_mod_p192k1(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) static int ecp_mod_p224k1(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) static int ecp_mod_p256k1(mbedtls_mpi *); #endif #if defined(ECP_LOAD_GROUP) #define LOAD_GROUP_A(G) ecp_group_load(grp, \ G ## _p, sizeof(G ## _p), \ G ## _a, sizeof(G ## _a), \ G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ G ## _n, sizeof(G ## _n), \ G ## _T \ ) #define LOAD_GROUP(G) ecp_group_load(grp, \ G ## _p, sizeof(G ## _p), \ NULL, 0, \ G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ G ## _n, sizeof(G ## _n), \ G ## _T \ ) #endif /* ECP_LOAD_GROUP */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /* Constants used by ecp_use_curve25519() */ static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42; static const unsigned char curve25519_part_of_n[] = { 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED, }; /* * Specialized function for creating the Curve25519 group */ static int ecp_use_curve25519(mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Actually ( A + 2 ) / 4 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24)); /* P = 2^255 - 19 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 255)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 19)); grp->pbits = mbedtls_mpi_bitlen(&grp->P); /* N = 2^252 + 27742317777372353535851937790883648493 */ MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&grp->N, curve25519_part_of_n, sizeof(curve25519_part_of_n))); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&grp->N, 252, 1)); /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); mbedtls_mpi_free(&grp->G.Y); /* Actually, the required msb for private keys */ grp->nbits = 254; cleanup: if (ret != 0) { mbedtls_ecp_group_free(grp); } return ret; } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* Constants used by ecp_use_curve448() */ static const mbedtls_mpi_sint curve448_a24 = 0x98AA; static const unsigned char curve448_part_of_n[] = { 0x83, 0x35, 0xDC, 0x16, 0x3B, 0xB1, 0x24, 0xB6, 0x51, 0x29, 0xC9, 0x6F, 0xDE, 0x93, 0x3D, 0x8D, 0x72, 0x3A, 0x70, 0xAA, 0xDC, 0x87, 0x3D, 0x6D, 0x54, 0xA7, 0xBB, 0x0D, }; /* * Specialized function for creating the Curve448 group */ static int ecp_use_curve448(mbedtls_ecp_group *grp) { mbedtls_mpi Ns; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_init(&Ns); /* Actually ( A + 2 ) / 4 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24)); /* P = 2^448 - 2^224 - 1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 224)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 224)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 1)); grp->pbits = mbedtls_mpi_bitlen(&grp->P); /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); mbedtls_mpi_free(&grp->G.Y); /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&grp->N, 446, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&Ns, curve448_part_of_n, sizeof(curve448_part_of_n))); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&grp->N, &grp->N, &Ns)); /* Actually, the required msb for private keys */ grp->nbits = 447; cleanup: mbedtls_mpi_free(&Ns); if (ret != 0) { mbedtls_ecp_group_free(grp); } return ret; } #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ /* * Set a group using well-known domain parameters */ int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id) { mbedtls_ecp_group_free(grp); mbedtls_ecp_group_init(grp); grp->id = id; switch (id) { #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) case MBEDTLS_ECP_DP_SECP192R1: NIST_MODP(p192); return LOAD_GROUP(secp192r1); #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) case MBEDTLS_ECP_DP_SECP224R1: NIST_MODP(p224); return LOAD_GROUP(secp224r1); #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) case MBEDTLS_ECP_DP_SECP256R1: NIST_MODP(p256); return LOAD_GROUP(secp256r1); #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) case MBEDTLS_ECP_DP_SECP384R1: NIST_MODP(p384); return LOAD_GROUP(secp384r1); #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) case MBEDTLS_ECP_DP_SECP521R1: NIST_MODP(p521); return LOAD_GROUP(secp521r1); #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) case MBEDTLS_ECP_DP_SECP192K1: grp->modp = ecp_mod_p192k1; return LOAD_GROUP_A(secp192k1); #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) case MBEDTLS_ECP_DP_SECP224K1: grp->modp = ecp_mod_p224k1; return LOAD_GROUP_A(secp224k1); #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) case MBEDTLS_ECP_DP_SECP256K1: grp->modp = ecp_mod_p256k1; return LOAD_GROUP_A(secp256k1); #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) case MBEDTLS_ECP_DP_BP256R1: return LOAD_GROUP_A(brainpoolP256r1); #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) case MBEDTLS_ECP_DP_BP384R1: return LOAD_GROUP_A(brainpoolP384r1); #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) case MBEDTLS_ECP_DP_BP512R1: return LOAD_GROUP_A(brainpoolP512r1); #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) case MBEDTLS_ECP_DP_CURVE25519: grp->modp = ecp_mod_p255; return ecp_use_curve25519(grp); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) case MBEDTLS_ECP_DP_CURVE448: grp->modp = ecp_mod_p448; return ecp_use_curve448(grp); #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ default: grp->id = MBEDTLS_ECP_DP_NONE; return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } } #if defined(MBEDTLS_ECP_NIST_OPTIM) /* * Fast reduction modulo the primes used by the NIST curves. * * These functions are critical for speed, but not needed for correct * operations. So, we make the choice to heavily rely on the internals of our * bignum library, which creates a tight coupling between these functions and * our MPI implementation. However, the coupling between the ECP module and * MPI remains loose, since these functions can be deactivated at will. */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) /* * Compared to the way things are presented in FIPS 186-3 D.2, * we proceed in columns, from right (least significant chunk) to left, * adding chunks to N in place, and keeping a carry for the next chunk. * This avoids moving things around in memory, and uselessly adding zeros, * compared to the more straightforward, line-oriented approach. * * For this prime we need to handle data in chunks of 64 bits. * Since this is always a multiple of our basic mbedtls_mpi_uint, we can * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. */ /* Add 64-bit chunks (dst += src) and update carry */ static inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry) { unsigned char i; mbedtls_mpi_uint c = 0; for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) { *dst += c; c = (*dst < c); *dst += *src; c += (*dst < *src); } *carry += c; } /* Add carry to a 64-bit chunk and update carry */ static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry) { unsigned char i; for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) { *dst += *carry; *carry = (*dst < *carry); } } #define WIDTH 8 / sizeof(mbedtls_mpi_uint) #define A(i) N->p + (i) * WIDTH #define ADD(i) add64(p, A(i), &c) #define NEXT p += WIDTH; carry64(p, &c) #define LAST p += WIDTH; *p = c; while (++p < end) *p = 0 /* * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) */ static int ecp_mod_p192(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_uint c = 0; mbedtls_mpi_uint *p, *end; /* Make sure we have enough blocks so that A(5) is legal */ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, 6 * WIDTH)); p = N->p; end = p + N->n; ADD(3); ADD(5); NEXT; // A0 += A3 + A5 ADD(3); ADD(4); ADD(5); NEXT; // A1 += A3 + A4 + A5 ADD(4); ADD(5); LAST; // A2 += A4 + A5 cleanup: return ret; } #undef WIDTH #undef A #undef ADD #undef NEXT #undef LAST #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /* * The reader is advised to first understand ecp_mod_p192() since the same * general structure is used here, but with additional complications: * (1) chunks of 32 bits, and (2) subtractions. */ /* * For these primes, we need to handle data in chunks of 32 bits. * This makes it more complicated if we use 64 bits limbs in MPI, * which prevents us from using a uniform access method as for p192. * * So, we define a mini abstraction layer to access 32 bit chunks, * load them in 'cur' for work, and store them back from 'cur' when done. * * While at it, also define the size of N in terms of 32-bit chunks. */ #define LOAD32 cur = A(i); #if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ #define MAX32 N->n #define A(j) N->p[j] #define STORE32 N->p[i] = cur; #else /* 64-bit */ #define MAX32 N->n * 2 #define A(j) (j) % 2 ? (uint32_t) (N->p[(j)/2] >> 32) : \ (uint32_t) (N->p[(j)/2]) #define STORE32 \ if (i % 2) { \ N->p[i/2] &= 0x00000000FFFFFFFF; \ N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ } else { \ N->p[i/2] &= 0xFFFFFFFF00000000; \ N->p[i/2] |= (mbedtls_mpi_uint) cur; \ } #endif /* sizeof( mbedtls_mpi_uint ) */ /* * Helpers for addition and subtraction of chunks, with signed carry. */ static inline void add32(uint32_t *dst, uint32_t src, signed char *carry) { *dst += src; *carry += (*dst < src); } static inline void sub32(uint32_t *dst, uint32_t src, signed char *carry) { *carry -= (*dst < src); *dst -= src; } #define ADD(j) add32(&cur, A(j), &c); #define SUB(j) sub32(&cur, A(j), &c); /* * Helpers for the main 'loop' */ #define INIT(b) \ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; \ signed char c = 0, cc; \ uint32_t cur; \ size_t i = 0, bits = (b); \ /* N is the size of the product of two b-bit numbers, plus one */ \ /* limb for fix_negative */ \ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, (b) * 2 / biL + 1)); \ LOAD32; #define NEXT \ STORE32; i++; LOAD32; \ cc = c; c = 0; \ if (cc < 0) \ sub32(&cur, -cc, &c); \ else \ add32(&cur, cc, &c); \ #define LAST \ STORE32; i++; \ cur = c > 0 ? c : 0; STORE32; \ cur = 0; while (++i < MAX32) { STORE32; } \ if (c < 0) mbedtls_ecp_fix_negative(N, c, bits); /* * If the result is negative, we get it in the form * c * 2^bits + N, with c negative and N positive shorter than 'bits' */ static void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits) { size_t i; /* Set N := 2^bits - 1 - N. We know that 0 <= N < 2^bits, so * set the absolute value to 0xfff...fff - N. There is no carry * since we're subtracting from all-bits-one. */ for (i = 0; i <= bits / 8 / sizeof(mbedtls_mpi_uint); i++) { N->p[i] = ~(mbedtls_mpi_uint) 0 - N->p[i]; } /* Add 1, taking care of the carry. */ i = 0; do { ++N->p[i]; } while (N->p[i++] == 0 && i <= bits / 8 / sizeof(mbedtls_mpi_uint)); /* Invert the sign. * Now N = N0 - 2^bits where N0 is the initial value of N. */ N->s = -1; /* Add |c| * 2^bits to the absolute value. Since c and N are * negative, this adds c * 2^bits. */ mbedtls_mpi_uint msw = (mbedtls_mpi_uint) -c; #if defined(MBEDTLS_HAVE_INT64) if (bits == 224) { msw <<= 32; } #endif N->p[bits / 8 / sizeof(mbedtls_mpi_uint)] += msw; } #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) /* * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) */ static int ecp_mod_p224(mbedtls_mpi *N) { INIT(224); SUB(7); SUB(11); NEXT; // A0 += -A7 - A11 SUB(8); SUB(12); NEXT; // A1 += -A8 - A12 SUB(9); SUB(13); NEXT; // A2 += -A9 - A13 SUB(10); ADD(7); ADD(11); NEXT; // A3 += -A10 + A7 + A11 SUB(11); ADD(8); ADD(12); NEXT; // A4 += -A11 + A8 + A12 SUB(12); ADD(9); ADD(13); NEXT; // A5 += -A12 + A9 + A13 SUB(13); ADD(10); LAST; // A6 += -A13 + A10 cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) /* * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) */ static int ecp_mod_p256(mbedtls_mpi *N) { INIT(256); ADD(8); ADD(9); SUB(11); SUB(12); SUB(13); SUB(14); NEXT; // A0 ADD(9); ADD(10); SUB(12); SUB(13); SUB(14); SUB(15); NEXT; // A1 ADD(10); ADD(11); SUB(13); SUB(14); SUB(15); NEXT; // A2 ADD(11); ADD(11); ADD(12); ADD(12); ADD(13); SUB(15); SUB(8); SUB(9); NEXT; // A3 ADD(12); ADD(12); ADD(13); ADD(13); ADD(14); SUB(9); SUB(10); NEXT; // A4 ADD(13); ADD(13); ADD(14); ADD(14); ADD(15); SUB(10); SUB(11); NEXT; // A5 ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13); SUB(8); SUB(9); NEXT; // A6 ADD(15); ADD(15); ADD(15); ADD(8); SUB(10); SUB(11); SUB(12); SUB(13); LAST; // A7 cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /* * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) */ static int ecp_mod_p384(mbedtls_mpi *N) { INIT(384); ADD(12); ADD(21); ADD(20); SUB(23); NEXT; // A0 ADD(13); ADD(22); ADD(23); SUB(12); SUB(20); NEXT; // A2 ADD(14); ADD(23); SUB(13); SUB(21); NEXT; // A2 ADD(15); ADD(12); ADD(20); ADD(21); SUB(14); SUB(22); SUB(23); NEXT; // A3 ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22); SUB(15); SUB(23); SUB(23); NEXT; // A4 ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23); SUB(16); NEXT; // A5 ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22); SUB(17); NEXT; // A6 ADD(19); ADD(16); ADD(15); ADD(23); SUB(18); NEXT; // A7 ADD(20); ADD(17); ADD(16); SUB(19); NEXT; // A8 ADD(21); ADD(18); ADD(17); SUB(20); NEXT; // A9 ADD(22); ADD(19); ADD(18); SUB(21); NEXT; // A10 ADD(23); ADD(20); ADD(19); SUB(22); LAST; // A11 cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #undef A #undef LOAD32 #undef STORE32 #undef MAX32 #undef INIT #undef NEXT #undef LAST #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || MBEDTLS_ECP_DP_SECP256R1_ENABLED || MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) /* * Here we have an actual Mersenne prime, so things are more straightforward. * However, chunks are aligned on a 'weird' boundary (521 bits). */ /* Size of p521 in terms of mbedtls_mpi_uint */ #define P521_WIDTH (521 / 8 / sizeof(mbedtls_mpi_uint) + 1) /* Bits to keep in the most significant mbedtls_mpi_uint */ #define P521_MASK 0x01FF /* * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) * Write N as A1 + 2^521 A0, return A0 + A1 */ static int ecp_mod_p521(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_mpi M; mbedtls_mpi_uint Mp[P521_WIDTH + 1]; /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: * we need to hold bits 513 to 1056, which is 34 limbs, that is * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ if (N->n < P521_WIDTH) { return 0; } /* M = A1 */ M.s = 1; M.n = N->n - (P521_WIDTH - 1); if (M.n > P521_WIDTH + 1) { M.n = P521_WIDTH + 1; } M.p = Mp; memcpy(Mp, N->p + P521_WIDTH - 1, M.n * sizeof(mbedtls_mpi_uint)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, 521 % (8 * sizeof(mbedtls_mpi_uint)))); /* N = A0 */ N->p[P521_WIDTH - 1] &= P521_MASK; for (i = P521_WIDTH; i < N->n; i++) { N->p[i] = 0; } /* N = A0 + A1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M)); cleanup: return ret; } #undef P521_WIDTH #undef P521_MASK #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #endif /* MBEDTLS_ECP_NIST_OPTIM */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /* Size of p255 in terms of mbedtls_mpi_uint */ #define P255_WIDTH (255 / 8 / sizeof(mbedtls_mpi_uint) + 1) /* * Fast quasi-reduction modulo p255 = 2^255 - 19 * Write N as A0 + 2^256 A1, return A0 + 38 * A1 */ static int ecp_mod_p255(mbedtls_mpi *N) { mbedtls_mpi_uint Mp[P255_WIDTH]; /* Helper references for top part of N */ mbedtls_mpi_uint * const NT_p = N->p + P255_WIDTH; const size_t NT_n = N->n - P255_WIDTH; if (N->n <= P255_WIDTH) { return 0; } if (NT_n > P255_WIDTH) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Split N as N + 2^256 M */ memcpy(Mp, NT_p, sizeof(mbedtls_mpi_uint) * NT_n); memset(NT_p, 0, sizeof(mbedtls_mpi_uint) * NT_n); /* N = A0 + 38 * A1 */ mbedtls_mpi_core_mla(N->p, P255_WIDTH + 1, Mp, NT_n, 38); return 0; } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* Size of p448 in terms of mbedtls_mpi_uint */ #define P448_WIDTH (448 / 8 / sizeof(mbedtls_mpi_uint)) /* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ #define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y)) #define P224_SIZE (224 / 8) #define P224_WIDTH_MIN (P224_SIZE / sizeof(mbedtls_mpi_uint)) #define P224_WIDTH_MAX DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint)) #define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224) /* * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference * implementation of Curve448, which uses its own special 56-bit limbs rather * than a generic bignum library. We could squeeze some extra speed out on * 32-bit machines by splitting N up into 32-bit limbs and doing the * arithmetic using the limbs directly as we do for the NIST primes above, * but for 64-bit targets it should use half the number of operations if we do * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. */ static int ecp_mod_p448(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_mpi M, Q; mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; if (N->n <= P448_WIDTH) { return 0; } /* M = A1 */ M.s = 1; M.n = N->n - (P448_WIDTH); if (M.n > P448_WIDTH) { /* Shouldn't be called with N larger than 2^896! */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } M.p = Mp; memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + P448_WIDTH, M.n * sizeof(mbedtls_mpi_uint)); /* N = A0 */ for (i = P448_WIDTH; i < N->n; i++) { N->p[i] = 0; } /* N += A1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &M)); /* Q = B1, N += B1 */ Q = M; Q.p = Qp; memcpy(Qp, Mp, sizeof(Qp)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Q, 224)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &Q)); /* M = (B0 + B1) * 2^224, N += M */ if (sizeof(mbedtls_mpi_uint) > 4) { Mp[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS); } for (i = P224_WIDTH_MAX; i < M.n; ++i) { Mp[i] = 0; } MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&M, &M, &Q)); M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&M, 224)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &M)); cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* * Fast quasi-reduction modulo P = 2^s - R, * with R about 33 bits, used by the Koblitz curves. * * Write N as A0 + 2^224 A1, return A0 + R * A1. * Actually do two passes, since R is big. */ #define P_KOBLITZ_MAX (256 / 8 / sizeof(mbedtls_mpi_uint)) // Max limbs in P #define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R static inline int ecp_mod_koblitz(mbedtls_mpi *N, const mbedtls_mpi_uint *Rp, size_t p_limbs, size_t adjust, size_t shift, mbedtls_mpi_uint mask) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_mpi M, R; mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; if (N->n < p_limbs) { return 0; } /* Init R */ R.s = 1; R.p = (mbedtls_mpi_uint *) Rp; /* R.p will not be modified so the cast is safe */ R.n = P_KOBLITZ_R; /* Common setup for M */ M.s = 1; M.p = Mp; /* M = A1 */ M.n = (unsigned short) (N->n - (p_limbs - adjust)); if (M.n > p_limbs + adjust) { M.n = (unsigned short) (p_limbs + adjust); } memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint)); if (shift != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift)); } M.n += R.n; /* Make room for multiplication by R */ /* N = A0 */ if (mask != 0) { N->p[p_limbs - 1] &= mask; } for (i = p_limbs; i < N->n; i++) { N->p[i] = 0; } /* N = A0 + R * A1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&M, &M, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M)); /* Second pass */ /* M = A1 */ M.n = (unsigned short) (N->n - (p_limbs - adjust)); if (M.n > p_limbs + adjust) { M.n = (unsigned short) (p_limbs + adjust); } memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint)); if (shift != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift)); } M.n += R.n; /* Make room for multiplication by R */ /* N = A0 */ if (mask != 0) { N->p[p_limbs - 1] &= mask; } for (i = p_limbs; i < N->n; i++) { N->p[i] = 0; } /* N = A0 + R * A1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&M, &M, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M)); cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || MBEDTLS_ECP_DP_SECP224K1_ENABLED) || MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) /* * Fast quasi-reduction modulo p192k1 = 2^192 - R, * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 */ static int ecp_mod_p192k1(mbedtls_mpi *N) { static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; return ecp_mod_koblitz(N, Rp, 192 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); } #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) /* * Fast quasi-reduction modulo p224k1 = 2^224 - R, * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 */ static int ecp_mod_p224k1(mbedtls_mpi *N) { static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; #if defined(MBEDTLS_HAVE_INT64) return ecp_mod_koblitz(N, Rp, 4, 1, 32, 0xFFFFFFFF); #else return ecp_mod_koblitz(N, Rp, 224 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); #endif } #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* * Fast quasi-reduction modulo p256k1 = 2^256 - R, * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 */ static int ecp_mod_p256k1(mbedtls_mpi *N) { static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; return ecp_mod_koblitz(N, Rp, 256 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); } #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_TEST_HOOKS) MBEDTLS_STATIC_TESTABLE mbedtls_ecp_variant mbedtls_ecp_get_variant(void) { return MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT; } #endif /* MBEDTLS_TEST_HOOKS */ #endif /* !MBEDTLS_ECP_ALT */ #endif /* MBEDTLS_ECP_LIGHT */ #endif /* MBEDTLS_ECP_WITH_MPI_UINT */ webfakes/src/mbedtls/library/psa_util_internal.h0000644000176200001440000000705714740737024021634 0ustar liggesusers/** * \file psa_util_internal.h * * \brief Internal utility functions for use of PSA Crypto. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PSA_UTIL_INTERNAL_H #define MBEDTLS_PSA_UTIL_INTERNAL_H /* Include the public header so that users only need one include. */ #include "mbedtls/psa_util.h" #include "psa/crypto.h" #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) /************************************************************************* * FFDH ************************************************************************/ #define MBEDTLS_PSA_MAX_FFDH_PUBKEY_LENGTH \ PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) /************************************************************************* * ECC ************************************************************************/ #define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH \ PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) #define MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH \ PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) /************************************************************************* * Error translation ************************************************************************/ typedef struct { /* Error codes used by PSA crypto are in -255..-128, fitting in 16 bits. */ int16_t psa_status; /* Error codes used by Mbed TLS are in one of the ranges * -127..-1 (low-level) or -32767..-4096 (high-level with a low-level * code optionally added), fitting in 16 bits. */ int16_t mbedtls_error; } mbedtls_error_pair_t; #if defined(MBEDTLS_MD_LIGHT) extern const mbedtls_error_pair_t psa_to_md_errors[4]; #endif #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) extern const mbedtls_error_pair_t psa_to_cipher_errors[4]; #endif #if defined(MBEDTLS_LMS_C) extern const mbedtls_error_pair_t psa_to_lms_errors[3]; #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) extern const mbedtls_error_pair_t psa_to_ssl_errors[7]; #endif #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) extern const mbedtls_error_pair_t psa_to_pk_rsa_errors[8]; #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) extern const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[7]; #endif /* Generic fallback function for error translation, * when the received state was not module-specific. */ int psa_generic_status_to_mbedtls(psa_status_t status); /* This function iterates over provided local error translations, * and if no match was found - calls the fallback error translation function. */ int psa_status_to_mbedtls(psa_status_t status, const mbedtls_error_pair_t *local_translations, size_t local_errors_num, int (*fallback_f)(psa_status_t)); /* The second out of three-stage error handling functions of the pk module, * acts as a fallback after RSA / ECDSA error translation, and if no match * is found, it itself calls psa_generic_status_to_mbedtls. */ int psa_pk_status_to_mbedtls(psa_status_t status); /* Utility macro to shorten the defines of error translator in modules. */ #define PSA_TO_MBEDTLS_ERR_LIST(status, error_list, fallback_f) \ psa_status_to_mbedtls(status, error_list, \ sizeof(error_list)/sizeof(error_list[0]), \ fallback_f) #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ #endif /* MBEDTLS_PSA_UTIL_INTERNAL_H */ webfakes/src/mbedtls/library/rsa_alt_helpers.c0000644000176200001440000003247214740737024021261 0ustar liggesusers/* * Helper functions for the RSA module * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * */ #include "common.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #include "mbedtls/bignum.h" #include "rsa_alt_helpers.h" /* * Compute RSA prime factors from public and private exponents * * Summary of algorithm: * Setting F := lcm(P-1,Q-1), the idea is as follows: * * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime * factors of N. * * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same * construction still applies since (-)^K is the identity on the set of * roots of 1 in Z/NZ. * * The public and private key primitives (-)^E and (-)^D are mutually inverse * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. * Splitting L = 2^t * K with K odd, we have * * DE - 1 = FL = (F/2) * (2^(t+1)) * K, * * so (F / 2) * K is among the numbers * * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord * * where ord is the order of 2 in (DE - 1). * We can therefore iterate through these numbers apply the construction * of (a) and (b) above to attempt to factor N. * */ int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N, mbedtls_mpi const *E, mbedtls_mpi const *D, mbedtls_mpi *P, mbedtls_mpi *Q) { int ret = 0; uint16_t attempt; /* Number of current attempt */ uint16_t iter; /* Number of squares computed in the current attempt */ uint16_t order; /* Order of 2 in DE - 1 */ mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ mbedtls_mpi K; /* Temporary holding the current candidate */ const unsigned char primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251 }; const size_t num_primes = sizeof(primes) / sizeof(*primes); if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_cmp_int(N, 0) <= 0 || mbedtls_mpi_cmp_int(D, 1) <= 0 || mbedtls_mpi_cmp_mpi(D, N) >= 0 || mbedtls_mpi_cmp_int(E, 1) <= 0 || mbedtls_mpi_cmp_mpi(E, N) >= 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* * Initializations and temporary changes */ mbedtls_mpi_init(&K); mbedtls_mpi_init(&T); /* T := DE - 1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D, E)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1)); if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } /* After this operation, T holds the largest odd divisor of DE - 1. */ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order)); /* * Actual work */ /* Skip trying 2 if N == 1 mod 8 */ attempt = 0; if (N->p[0] % 8 == 1) { attempt = 1; } for (; attempt < num_primes; ++attempt) { MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt])); /* Check if gcd(K,N) = 1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N)); if (mbedtls_mpi_cmp_int(P, 1) != 0) { continue; } /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... * and check whether they have nontrivial GCD with N. */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N, Q /* temporarily use Q for storing Montgomery * multiplication helper values */)); for (iter = 1; iter <= order; ++iter) { /* If we reach 1 prematurely, there's no point * in continuing to square K */ if (mbedtls_mpi_cmp_int(&K, 1) == 0) { break; } MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N)); if (mbedtls_mpi_cmp_int(P, 1) == 1 && mbedtls_mpi_cmp_mpi(P, N) == -1) { /* * Have found a nontrivial divisor P of N. * Set Q := N / P. */ MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P)); goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N)); } /* * If we get here, then either we prematurely aborted the loop because * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must * be 1 if D,E,N were consistent. * Check if that's the case and abort if not, to avoid very long, * yet eventually failing, computations if N,D,E were not sane. */ if (mbedtls_mpi_cmp_int(&K, 1) != 0) { break; } } ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; cleanup: mbedtls_mpi_free(&K); mbedtls_mpi_free(&T); return ret; } /* * Given P, Q and the public exponent E, deduce D. * This is essentially a modular inversion. */ int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P, mbedtls_mpi const *Q, mbedtls_mpi const *E, mbedtls_mpi *D) { int ret = 0; mbedtls_mpi K, L; if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_cmp_int(P, 1) <= 0 || mbedtls_mpi_cmp_int(Q, 1) <= 0 || mbedtls_mpi_cmp_int(E, 0) == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_init(&K); mbedtls_mpi_init(&L); /* Temporarily put K := P-1 and L := Q-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1)); /* Temporarily put D := gcd(P-1, Q-1) */ MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L)); /* K := LCM(P-1, Q-1) */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L)); MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D)); /* Compute modular inverse of E in LCM(P-1, Q-1) */ MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K)); cleanup: mbedtls_mpi_free(&K); mbedtls_mpi_free(&L); return ret; } int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP) { int ret = 0; mbedtls_mpi K; mbedtls_mpi_init(&K); /* DP = D mod P-1 */ if (DP != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K)); } /* DQ = D mod Q-1 */ if (DQ != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K)); } /* QP = Q^{-1} mod P */ if (QP != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P)); } cleanup: mbedtls_mpi_free(&K); return ret; } /* * Check that core RSA parameters are sane. */ int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = 0; mbedtls_mpi K, L; mbedtls_mpi_init(&K); mbedtls_mpi_init(&L); /* * Step 1: If PRNG provided, check that P and Q are prime */ #if defined(MBEDTLS_GENPRIME) /* * When generating keys, the strongest security we support aims for an error * rate of at most 2^-100 and we are aiming for the same certainty here as * well. */ if (f_rng != NULL && P != NULL && (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } if (f_rng != NULL && Q != NULL && (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } #else ((void) f_rng); ((void) p_rng); #endif /* MBEDTLS_GENPRIME */ /* * Step 2: Check that 1 < N = P * Q */ if (P != NULL && Q != NULL && N != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q)); if (mbedtls_mpi_cmp_int(N, 1) <= 0 || mbedtls_mpi_cmp_mpi(&K, N) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } /* * Step 3: Check and 1 < D, E < N if present. */ if (N != NULL && D != NULL && E != NULL) { if (mbedtls_mpi_cmp_int(D, 1) <= 0 || mbedtls_mpi_cmp_int(E, 1) <= 0 || mbedtls_mpi_cmp_mpi(D, N) >= 0 || mbedtls_mpi_cmp_mpi(E, N) >= 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } /* * Step 4: Check that D, E are inverse modulo P-1 and Q-1 */ if (P != NULL && Q != NULL && D != NULL && E != NULL) { if (mbedtls_mpi_cmp_int(P, 1) <= 0 || mbedtls_mpi_cmp_int(Q, 1) <= 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } /* Compute DE-1 mod P-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L)); if (mbedtls_mpi_cmp_int(&K, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } /* Compute DE-1 mod Q-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L)); if (mbedtls_mpi_cmp_int(&K, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } cleanup: mbedtls_mpi_free(&K); mbedtls_mpi_free(&L); /* Wrap MPI error codes by RSA check failure error code */ if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) { ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } return ret; } /* * Check that RSA CRT parameters are in accordance with core parameters. */ int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *DP, const mbedtls_mpi *DQ, const mbedtls_mpi *QP) { int ret = 0; mbedtls_mpi K, L; mbedtls_mpi_init(&K); mbedtls_mpi_init(&L); /* Check that DP - D == 0 mod P - 1 */ if (DP != NULL) { if (P == NULL) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); if (mbedtls_mpi_cmp_int(&L, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } /* Check that DQ - D == 0 mod Q - 1 */ if (DQ != NULL) { if (Q == NULL) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); if (mbedtls_mpi_cmp_int(&L, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } /* Check that QP * Q - 1 == 0 mod P */ if (QP != NULL) { if (P == NULL || Q == NULL) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P)); if (mbedtls_mpi_cmp_int(&K, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } cleanup: /* Wrap MPI error codes by RSA check failure error code */ if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) { ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } mbedtls_mpi_free(&K); mbedtls_mpi_free(&L); return ret; } #endif /* MBEDTLS_RSA_C */ webfakes/src/mbedtls/library/md_wrap.h0000644000176200001440000000160014740737024017535 0ustar liggesusers/** * \file md_wrap.h * * \brief Message digest wrappers. * * \warning This in an internal header. Do not include directly. * * \author Adriaan de Jong */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD_WRAP_H #define MBEDTLS_MD_WRAP_H #include "mbedtls/build_info.h" #include "mbedtls/md.h" #ifdef __cplusplus extern "C" { #endif /** * Message digest information. * Allows message digest functions to be called in a generic way. */ struct mbedtls_md_info_t { /** Digest identifier */ mbedtls_md_type_t type; /** Output length of the digest function in bytes */ unsigned char size; #if defined(MBEDTLS_MD_C) /** Block length of the digest function in bytes */ unsigned char block_size; #endif }; #ifdef __cplusplus } #endif #endif /* MBEDTLS_MD_WRAP_H */ webfakes/src/mbedtls/library/psa_crypto_ecp.c0000644000176200001440000004724314740737024021126 0ustar liggesusers/* * PSA ECP layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa_crypto_core.h" #include "psa_crypto_ecp.h" #include "psa_crypto_random_impl.h" #include "mbedtls/psa_util.h" #include #include #include "mbedtls/platform.h" #include #include #include #include #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) /* Helper function to verify if the provided EC's family and key bit size are valid. * * Note: "bits" parameter is used both as input and output and it might be updated * in case provided input value is not multiple of 8 ("sloppy" bits). */ static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits) { switch (family) { case PSA_ECC_FAMILY_SECP_R1: switch (*bits) { case 192: case 224: case 256: case 384: case 521: return PSA_SUCCESS; case 528: *bits = 521; return PSA_SUCCESS; } break; case PSA_ECC_FAMILY_BRAINPOOL_P_R1: switch (*bits) { case 256: case 384: case 512: return PSA_SUCCESS; } break; case PSA_ECC_FAMILY_MONTGOMERY: switch (*bits) { case 448: case 255: return PSA_SUCCESS; case 256: *bits = 255; return PSA_SUCCESS; } break; case PSA_ECC_FAMILY_SECP_K1: switch (*bits) { case 192: /* secp224k1 is not and will not be supported in PSA (#3541). */ case 256: return PSA_SUCCESS; } break; } return PSA_ERROR_INVALID_ARGUMENT; } psa_status_t mbedtls_psa_ecp_load_representation( psa_key_type_t type, size_t curve_bits, const uint8_t *data, size_t data_length, mbedtls_ecp_keypair **p_ecp) { mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; psa_status_t status; mbedtls_ecp_keypair *ecp = NULL; size_t curve_bytes = data_length; int explicit_bits = (curve_bits != 0); if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) && PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) { /* A Weierstrass public key is represented as: * - The byte 0x04; * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. * So its data length is 2m+1 where m is the curve size in bits. */ if ((data_length & 1) == 0) { return PSA_ERROR_INVALID_ARGUMENT; } curve_bytes = data_length / 2; /* Montgomery public keys are represented in compressed format, meaning * their curve_bytes is equal to the amount of input. */ /* Private keys are represented in uncompressed private random integer * format, meaning their curve_bytes is equal to the amount of input. */ } if (explicit_bits) { /* With an explicit bit-size, the data must have the matching length. */ if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) { return PSA_ERROR_INVALID_ARGUMENT; } } else { /* We need to infer the bit-size from the data. Since the only * information we have is the length in bytes, the value of curve_bits * at this stage is rounded up to the nearest multiple of 8. */ curve_bits = PSA_BYTES_TO_BITS(curve_bytes); } /* Allocate and initialize a key representation. */ ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); if (ecp == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } mbedtls_ecp_keypair_init(ecp); status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits); if (status != PSA_SUCCESS) { goto exit; } /* Load the group. */ grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type), curve_bits); if (grp_id == MBEDTLS_ECP_DP_NONE) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = mbedtls_to_psa_error( mbedtls_ecp_group_load(&ecp->grp, grp_id)); if (status != PSA_SUCCESS) { goto exit; } /* Load the key material. */ if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { /* Load the public value. */ status = mbedtls_to_psa_error( mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q, data, data_length)); if (status != PSA_SUCCESS) { goto exit; } /* Check that the point is on the curve. */ status = mbedtls_to_psa_error( mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q)); if (status != PSA_SUCCESS) { goto exit; } } else { /* Load and validate the secret value. */ status = mbedtls_to_psa_error( mbedtls_ecp_read_key(ecp->grp.id, ecp, data, data_length)); if (status != PSA_SUCCESS) { goto exit; } } *p_ecp = ecp; exit: if (status != PSA_SUCCESS) { mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); } return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) psa_status_t mbedtls_psa_ecp_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits) { psa_status_t status; mbedtls_ecp_keypair *ecp = NULL; /* Parse input */ status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, data, data_length, &ecp); if (status != PSA_SUCCESS) { goto exit; } if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) == PSA_ECC_FAMILY_MONTGOMERY) { *bits = ecp->grp.nbits + 1; } else { *bits = ecp->grp.nbits; } /* Re-export the data to PSA export format. There is currently no support * for other input formats then the export format, so this is a 1-1 * copy operation. */ status = mbedtls_psa_ecp_export_key(attributes->type, ecp, key_buffer, key_buffer_size, key_buffer_length); exit: /* Always free the PK object (will also free contained ECP context) */ mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return status; } psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type, mbedtls_ecp_keypair *ecp, uint8_t *data, size_t data_size, size_t *data_length) { psa_status_t status; if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { /* Check whether the public part is loaded */ if (mbedtls_ecp_is_zero(&ecp->Q)) { /* Calculate the public key */ status = mbedtls_to_psa_error( mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); if (status != PSA_SUCCESS) { return status; } } status = mbedtls_to_psa_error( mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, data_length, data, data_size)); if (status != PSA_SUCCESS) { memset(data, 0, data_size); } return status; } else { status = mbedtls_to_psa_error( mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size)); return status; } } psa_status_t mbedtls_psa_ecp_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ecp = NULL; status = mbedtls_psa_ecp_load_representation( attributes->type, attributes->bits, key_buffer, key_buffer_size, &ecp); if (status != PSA_SUCCESS) { return status; } status = mbedtls_psa_ecp_export_key( PSA_KEY_TYPE_ECC_PUBLIC_KEY( PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)), ecp, data, data_size, data_length); mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) psa_status_t mbedtls_psa_ecp_generate_key( const psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->type); mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_from_psa(curve, attributes->bits); const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_info_from_grp_id(grp_id); mbedtls_ecp_keypair ecp; if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) { return PSA_ERROR_NOT_SUPPORTED; } mbedtls_ecp_keypair_init(&ecp); ret = mbedtls_ecp_gen_key(grp_id, &ecp, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); if (ret != 0) { mbedtls_ecp_keypair_free(&ecp); return mbedtls_to_psa_error(ret); } status = mbedtls_to_psa_error( mbedtls_ecp_write_key_ext(&ecp, key_buffer_length, key_buffer, key_buffer_size)); mbedtls_ecp_keypair_free(&ecp); return status; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ /****************************************************************/ /* ECDSA sign/verify */ /****************************************************************/ #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) psa_status_t mbedtls_psa_ecdsa_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ecp = NULL; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t curve_bytes; mbedtls_mpi r, s; status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, key_buffer, key_buffer_size, &ecp); if (status != PSA_SUCCESS) { return status; } curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); if (signature_size < 2 * curve_bytes) { ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; goto cleanup; } if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext( &ecp->grp, &r, &s, &ecp->d, hash, hash_length, md_alg, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); #else ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; goto cleanup; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ } else { (void) alg; MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d, hash, hash_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); } MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r, signature, curve_bytes)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s, signature + curve_bytes, curve_bytes)); cleanup: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); if (ret == 0) { *signature_length = 2 * curve_bytes; } mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp) { int ret = 0; /* Check whether the public part is loaded. If not, load it. */ if (mbedtls_ecp_is_zero(&ecp->Q)) { ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); } return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_ecdsa_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ecp = NULL; size_t curve_bytes; mbedtls_mpi r, s; (void) alg; status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, key_buffer, key_buffer_size, &ecp); if (status != PSA_SUCCESS) { return status; } curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); if (signature_length != 2 * curve_bytes) { status = PSA_ERROR_INVALID_SIGNATURE; goto cleanup; } status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r, signature, curve_bytes)); if (status != PSA_SUCCESS) { goto cleanup; } status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s, signature + curve_bytes, curve_bytes)); if (status != PSA_SUCCESS) { goto cleanup; } status = mbedtls_psa_ecp_load_public_part(ecp); if (status != PSA_SUCCESS) { goto cleanup; } status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash, hash_length, &ecp->Q, &r, &s)); cleanup: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ /****************************************************************/ /* ECDH Key Agreement */ /****************************************************************/ #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) psa_status_t mbedtls_psa_key_agreement_ecdh( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length) { psa_status_t status; if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) || !PSA_ALG_IS_ECDH(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } mbedtls_ecp_keypair *ecp = NULL; status = mbedtls_psa_ecp_load_representation( attributes->type, attributes->bits, key_buffer, key_buffer_size, &ecp); if (status != PSA_SUCCESS) { return status; } mbedtls_ecp_keypair *their_key = NULL; mbedtls_ecdh_context ecdh; size_t bits = 0; psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits); mbedtls_ecdh_init(&ecdh); status = mbedtls_psa_ecp_load_representation( PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), bits, peer_key, peer_key_length, &their_key); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_to_psa_error( mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS)); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_to_psa_error( mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS)); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_to_psa_error( mbedtls_ecdh_calc_secret(&ecdh, shared_secret_length, shared_secret, shared_secret_size, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); if (status != PSA_SUCCESS) { goto exit; } if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) { status = PSA_ERROR_CORRUPTION_DETECTED; } exit: if (status != PSA_SUCCESS) { mbedtls_platform_zeroize(shared_secret, shared_secret_size); } mbedtls_ecdh_free(&ecdh); mbedtls_ecp_keypair_free(their_key); mbedtls_free(their_key); mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/psa_crypto.c0000644000176200001440000115561614740737024020304 0ustar liggesusers/* * PSA crypto layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "psa_crypto_core_common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) #include "check_crypto_config.h" #endif #include "psa/crypto.h" #include "psa/crypto_values.h" #include "psa_crypto_cipher.h" #include "psa_crypto_core.h" #include "psa_crypto_invasive.h" #include "psa_crypto_driver_wrappers.h" #include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_ecp.h" #include "psa_crypto_ffdh.h" #include "psa_crypto_hash.h" #include "psa_crypto_mac.h" #include "psa_crypto_rsa.h" #include "psa_crypto_ecp.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #include "psa_crypto_se.h" #endif #include "psa_crypto_slot_management.h" /* Include internal declarations that are useful for implementing persistently * stored keys. */ #include "psa_crypto_storage.h" #include "psa_crypto_random_impl.h" #include #include #include "mbedtls/platform.h" #include "mbedtls/aes.h" #include "mbedtls/asn1.h" #include "mbedtls/asn1write.h" #include "mbedtls/bignum.h" #include "mbedtls/camellia.h" #include "mbedtls/chacha20.h" #include "mbedtls/chachapoly.h" #include "mbedtls/cipher.h" #include "mbedtls/ccm.h" #include "mbedtls/cmac.h" #include "mbedtls/constant_time.h" #include "mbedtls/des.h" #include "mbedtls/ecdh.h" #include "mbedtls/ecp.h" #include "mbedtls/entropy.h" #include "mbedtls/error.h" #include "mbedtls/gcm.h" #include "mbedtls/md5.h" #include "mbedtls/pk.h" #include "pk_wrap.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/ripemd160.h" #include "mbedtls/rsa.h" #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" #include "mbedtls/psa_util.h" #include "mbedtls/threading.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) #define BUILTIN_ALG_ANY_HKDF 1 #endif /****************************************************************/ /* Global data, support functions and library management */ /****************************************************************/ static int key_type_is_raw_bytes(psa_key_type_t type) { return PSA_KEY_TYPE_IS_UNSTRUCTURED(type); } /* Values for psa_global_data_t::rng_state */ #define RNG_NOT_INITIALIZED 0 #define RNG_INITIALIZED 1 #define RNG_SEEDED 2 /* IDs for PSA crypto subsystems. Starts at 1 to catch potential uninitialized * variables as arguments. */ typedef enum { PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 1, PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS, PSA_CRYPTO_SUBSYSTEM_RNG, PSA_CRYPTO_SUBSYSTEM_TRANSACTION, } mbedtls_psa_crypto_subsystem; /* Initialization flags for global_data::initialized */ #define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED 0x01 #define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED 0x02 #define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED 0x04 #define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED ( \ PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \ PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \ PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) typedef struct { uint8_t initialized; uint8_t rng_state; mbedtls_psa_random_context_t rng; } psa_global_data_t; static psa_global_data_t global_data; static uint8_t psa_get_initialized(void) { uint8_t initialized; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ initialized = global_data.rng_state == RNG_SEEDED; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ initialized = (initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ return initialized; } static uint8_t psa_get_drivers_initialized(void) { uint8_t initialized; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ return initialized; } #define GUARD_MODULE_INITIALIZED \ if (psa_get_initialized() == 0) \ return PSA_ERROR_BAD_STATE; #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) /* Declare a local copy of an input buffer and a variable that will be used * to store a pointer to the start of the buffer. * * Note: This macro must be called before any operations which may jump to * the exit label, so that the local input copy object is safe to be freed. * * Assumptions: * - input is the name of a pointer to the buffer to be copied * - The name LOCAL_INPUT_COPY_OF_input is unused in the current scope * - input_copy_name is a name that is unused in the current scope */ #define LOCAL_INPUT_DECLARE(input, input_copy_name) \ psa_crypto_local_input_t LOCAL_INPUT_COPY_OF_##input = PSA_CRYPTO_LOCAL_INPUT_INIT; \ const uint8_t *input_copy_name = NULL; /* Allocate a copy of the buffer input and set the pointer input_copy to * point to the start of the copy. * * Assumptions: * - psa_status_t status exists * - An exit label is declared * - input is the name of a pointer to the buffer to be copied * - LOCAL_INPUT_DECLARE(input, input_copy) has previously been called */ #define LOCAL_INPUT_ALLOC(input, length, input_copy) \ status = psa_crypto_local_input_alloc(input, length, \ &LOCAL_INPUT_COPY_OF_##input); \ if (status != PSA_SUCCESS) { \ goto exit; \ } \ input_copy = LOCAL_INPUT_COPY_OF_##input.buffer; /* Free the local input copy allocated previously by LOCAL_INPUT_ALLOC() * * Assumptions: * - input_copy is the name of the input copy pointer set by LOCAL_INPUT_ALLOC() * - input is the name of the original buffer that was copied */ #define LOCAL_INPUT_FREE(input, input_copy) \ input_copy = NULL; \ psa_crypto_local_input_free(&LOCAL_INPUT_COPY_OF_##input); /* Declare a local copy of an output buffer and a variable that will be used * to store a pointer to the start of the buffer. * * Note: This macro must be called before any operations which may jump to * the exit label, so that the local output copy object is safe to be freed. * * Assumptions: * - output is the name of a pointer to the buffer to be copied * - The name LOCAL_OUTPUT_COPY_OF_output is unused in the current scope * - output_copy_name is a name that is unused in the current scope */ #define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ psa_crypto_local_output_t LOCAL_OUTPUT_COPY_OF_##output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; \ uint8_t *output_copy_name = NULL; /* Allocate a copy of the buffer output and set the pointer output_copy to * point to the start of the copy. * * Assumptions: * - psa_status_t status exists * - An exit label is declared * - output is the name of a pointer to the buffer to be copied * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called */ #define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ status = psa_crypto_local_output_alloc(output, length, \ &LOCAL_OUTPUT_COPY_OF_##output); \ if (status != PSA_SUCCESS) { \ goto exit; \ } \ output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer; /* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC() * after first copying back its contents to the original buffer. * * Assumptions: * - psa_status_t status exists * - output_copy is the name of the output copy pointer set by LOCAL_OUTPUT_ALLOC() * - output is the name of the original buffer that was copied */ #define LOCAL_OUTPUT_FREE(output, output_copy) \ output_copy = NULL; \ do { \ psa_status_t local_output_status; \ local_output_status = psa_crypto_local_output_free(&LOCAL_OUTPUT_COPY_OF_##output); \ if (local_output_status != PSA_SUCCESS) { \ /* Since this error case is an internal error, it's more serious than \ * any existing error code and so it's fine to overwrite the existing \ * status. */ \ status = local_output_status; \ } \ } while (0) #else /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ #define LOCAL_INPUT_DECLARE(input, input_copy_name) \ const uint8_t *input_copy_name = NULL; #define LOCAL_INPUT_ALLOC(input, length, input_copy) \ input_copy = input; #define LOCAL_INPUT_FREE(input, input_copy) \ input_copy = NULL; #define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ uint8_t *output_copy_name = NULL; #define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ output_copy = output; #define LOCAL_OUTPUT_FREE(output, output_copy) \ output_copy = NULL; #endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ int psa_can_do_hash(psa_algorithm_t hash_alg) { (void) hash_alg; return psa_get_drivers_initialized(); } int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg) { (void) key_type; (void) cipher_alg; return psa_get_drivers_initialized(); } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) static int psa_is_dh_key_size_valid(size_t bits) { switch (bits) { #if defined(PSA_WANT_DH_RFC7919_2048) case 2048: return 1; #endif /* PSA_WANT_DH_RFC7919_2048 */ #if defined(PSA_WANT_DH_RFC7919_3072) case 3072: return 1; #endif /* PSA_WANT_DH_RFC7919_3072 */ #if defined(PSA_WANT_DH_RFC7919_4096) case 4096: return 1; #endif /* PSA_WANT_DH_RFC7919_4096 */ #if defined(PSA_WANT_DH_RFC7919_6144) case 6144: return 1; #endif /* PSA_WANT_DH_RFC7919_6144 */ #if defined(PSA_WANT_DH_RFC7919_8192) case 8192: return 1; #endif /* PSA_WANT_DH_RFC7919_8192 */ default: return 0; } } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT || MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */ psa_status_t mbedtls_to_psa_error(int ret) { /* Mbed TLS error codes can combine a high-level error code and a * low-level error code. The low-level error usually reflects the * root cause better, so dispatch on that preferably. */ int low_level_ret = -(-ret & 0x007f); switch (low_level_ret != 0 ? low_level_ret : ret) { case 0: return PSA_SUCCESS; #if defined(MBEDTLS_AES_C) case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH: case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_AES_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; #endif #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_ASN1_WRITE_C) case MBEDTLS_ERR_ASN1_OUT_OF_DATA: case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG: case MBEDTLS_ERR_ASN1_INVALID_LENGTH: case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH: case MBEDTLS_ERR_ASN1_INVALID_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_ASN1_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA: case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH: return PSA_ERROR_NOT_SUPPORTED; #endif #if defined(MBEDTLS_CCM_C) case MBEDTLS_ERR_CCM_BAD_INPUT: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_CCM_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; #endif #if defined(MBEDTLS_CHACHA20_C) case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; #endif #if defined(MBEDTLS_CHACHAPOLY_C) case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE: return PSA_ERROR_BAD_STATE; case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; #endif #if defined(MBEDTLS_CIPHER_C) case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_CIPHER_INVALID_PADDING: return PSA_ERROR_INVALID_PADDING; case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_CIPHER_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT: return PSA_ERROR_CORRUPTION_DETECTED; #endif #if !(defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) || \ defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)) /* Only check CTR_DRBG error codes if underlying mbedtls_xxx * functions are passed a CTR_DRBG instance. */ case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG: case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR: return PSA_ERROR_INSUFFICIENT_ENTROPY; #endif #if defined(MBEDTLS_DES_C) case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH: return PSA_ERROR_NOT_SUPPORTED; #endif case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED: case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE: case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; #if defined(MBEDTLS_GCM_C) case MBEDTLS_ERR_GCM_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_GCM_BAD_INPUT: return PSA_ERROR_INVALID_ARGUMENT; #endif #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \ defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) /* Only check HMAC_DRBG error codes if underlying mbedtls_xxx * functions are passed a HMAC_DRBG instance. */ case MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; case MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG: case MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR: return PSA_ERROR_INSUFFICIENT_ENTROPY; #endif #if defined(MBEDTLS_MD_LIGHT) case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_MD_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MD_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; #if defined(MBEDTLS_FS_IO) case MBEDTLS_ERR_MD_FILE_IO_ERROR: return PSA_ERROR_STORAGE_FAILURE; #endif #endif #if defined(MBEDTLS_BIGNUM_C) #if defined(MBEDTLS_FS_IO) case MBEDTLS_ERR_MPI_FILE_IO_ERROR: return PSA_ERROR_STORAGE_FAILURE; #endif case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_INVALID_CHARACTER: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_MPI_NEGATIVE_VALUE: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; #endif #if defined(MBEDTLS_PK_C) case MBEDTLS_ERR_PK_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_PK_TYPE_MISMATCH: case MBEDTLS_ERR_PK_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || defined(MBEDTLS_FS_IO) || \ defined(MBEDTLS_PSA_ITS_FILE_C) case MBEDTLS_ERR_PK_FILE_IO_ERROR: return PSA_ERROR_STORAGE_FAILURE; #endif case MBEDTLS_ERR_PK_KEY_INVALID_VERSION: case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_PK_PASSWORD_REQUIRED: case MBEDTLS_ERR_PK_PASSWORD_MISMATCH: return PSA_ERROR_NOT_PERMITTED; case MBEDTLS_ERR_PK_INVALID_PUBKEY: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_PK_INVALID_ALG: case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE: case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_PK_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; #endif case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED: return PSA_ERROR_HARDWARE_FAILURE; case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED: return PSA_ERROR_NOT_SUPPORTED; #if defined(MBEDTLS_RSA_C) case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_RSA_INVALID_PADDING: return PSA_ERROR_INVALID_PADDING; case MBEDTLS_ERR_RSA_KEY_GEN_FAILED: return PSA_ERROR_HARDWARE_FAILURE; case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_RSA_PUBLIC_FAILED: case MBEDTLS_ERR_RSA_PRIVATE_FAILED: return PSA_ERROR_CORRUPTION_DETECTED; case MBEDTLS_ERR_RSA_VERIFY_FAILED: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_RSA_RNG_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; #endif #if defined(MBEDTLS_ECP_LIGHT) case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: case MBEDTLS_ERR_ECP_INVALID_KEY: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH: case MBEDTLS_ERR_ECP_VERIFY_FAILED: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_ECP_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_ECP_RANDOM_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; #if defined(MBEDTLS_ECP_RESTARTABLE) case MBEDTLS_ERR_ECP_IN_PROGRESS: return PSA_OPERATION_INCOMPLETE; #endif #endif case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: return PSA_ERROR_CORRUPTION_DETECTED; default: return PSA_ERROR_GENERIC_ERROR; } } /** * \brief For output buffers which contain "tags" * (outputs that may be checked for validity like * hashes, MACs and signatures), fill the unused * part of the output buffer (the whole buffer on * error, the trailing part on success) with * something that isn't a valid tag (barring an * attack on the tag and deliberately-crafted * input), in case the caller doesn't check the * return status properly. * * \param output_buffer Pointer to buffer to wipe. May not be NULL * unless \p output_buffer_size is zero. * \param status Status of function called to generate * output_buffer originally * \param output_buffer_size Size of output buffer. If zero, \p output_buffer * could be NULL. * \param output_buffer_length Length of data written to output_buffer, must be * less than \p output_buffer_size */ static void psa_wipe_tag_output_buffer(uint8_t *output_buffer, psa_status_t status, size_t output_buffer_size, size_t output_buffer_length) { size_t offset = 0; if (output_buffer_size == 0) { /* If output_buffer_size is 0 then we have nothing to do. We must not call memset because output_buffer may be NULL in this case */ return; } if (status == PSA_SUCCESS) { offset = output_buffer_length; } memset(output_buffer + offset, '!', output_buffer_size - offset); } psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type, size_t bits) { /* Check that the bit size is acceptable for the key type */ switch (type) { case PSA_KEY_TYPE_RAW_DATA: case PSA_KEY_TYPE_HMAC: case PSA_KEY_TYPE_DERIVE: case PSA_KEY_TYPE_PASSWORD: case PSA_KEY_TYPE_PASSWORD_HASH: break; #if defined(PSA_WANT_KEY_TYPE_AES) case PSA_KEY_TYPE_AES: if (bits != 128 && bits != 192 && bits != 256) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif #if defined(PSA_WANT_KEY_TYPE_ARIA) case PSA_KEY_TYPE_ARIA: if (bits != 128 && bits != 192 && bits != 256) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif #if defined(PSA_WANT_KEY_TYPE_CAMELLIA) case PSA_KEY_TYPE_CAMELLIA: if (bits != 128 && bits != 192 && bits != 256) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif #if defined(PSA_WANT_KEY_TYPE_DES) case PSA_KEY_TYPE_DES: if (bits != 64 && bits != 128 && bits != 192) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif #if defined(PSA_WANT_KEY_TYPE_CHACHA20) case PSA_KEY_TYPE_CHACHA20: if (bits != 256) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif default: return PSA_ERROR_NOT_SUPPORTED; } if (bits % 8 != 0) { return PSA_ERROR_INVALID_ARGUMENT; } return PSA_SUCCESS; } /** Check whether a given key type is valid for use with a given MAC algorithm * * Upon successful return of this function, the behavior of #PSA_MAC_LENGTH * when called with the validated \p algorithm and \p key_type is well-defined. * * \param[in] algorithm The specific MAC algorithm (can be wildcard). * \param[in] key_type The key type of the key to be used with the * \p algorithm. * * \retval #PSA_SUCCESS * The \p key_type is valid for use with the \p algorithm * \retval #PSA_ERROR_INVALID_ARGUMENT * The \p key_type is not valid for use with the \p algorithm */ MBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do( psa_algorithm_t algorithm, psa_key_type_t key_type) { if (PSA_ALG_IS_HMAC(algorithm)) { if (key_type == PSA_KEY_TYPE_HMAC) { return PSA_SUCCESS; } } if (PSA_ALG_IS_BLOCK_CIPHER_MAC(algorithm)) { /* Check that we're calling PSA_BLOCK_CIPHER_BLOCK_LENGTH with a cipher * key. */ if ((key_type & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) { /* PSA_BLOCK_CIPHER_BLOCK_LENGTH returns 1 for stream ciphers and * the block length (larger than 1) for block ciphers. */ if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1) { return PSA_SUCCESS; } } } return PSA_ERROR_INVALID_ARGUMENT; } psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot, size_t buffer_length) { if (slot->key.data != NULL) { return PSA_ERROR_ALREADY_EXISTS; } slot->key.data = mbedtls_calloc(1, buffer_length); if (slot->key.data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } slot->key.bytes = buffer_length; return PSA_SUCCESS; } psa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot, const uint8_t *data, size_t data_length) { psa_status_t status = psa_allocate_buffer_to_slot(slot, data_length); if (status != PSA_SUCCESS) { return status; } memcpy(slot->key.data, data, data_length); return PSA_SUCCESS; } psa_status_t psa_import_key_into_slot( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t type = attributes->type; /* zero-length keys are never supported. */ if (data_length == 0) { return PSA_ERROR_NOT_SUPPORTED; } if (key_type_is_raw_bytes(type)) { *bits = PSA_BYTES_TO_BITS(data_length); status = psa_validate_unstructured_key_bit_size(attributes->type, *bits); if (status != PSA_SUCCESS) { return status; } /* Copy the key material. */ memcpy(key_buffer, data, data_length); *key_buffer_length = data_length; (void) key_buffer_size; return PSA_SUCCESS; } else if (PSA_KEY_TYPE_IS_ASYMMETRIC(type)) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) if (PSA_KEY_TYPE_IS_DH(type)) { if (psa_is_dh_key_size_valid(PSA_BYTES_TO_BITS(data_length)) == 0) { return PSA_ERROR_NOT_SUPPORTED; } return mbedtls_psa_ffdh_import_key(attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) if (PSA_KEY_TYPE_IS_ECC(type)) { return mbedtls_psa_ecp_import_key(attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ #if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) if (PSA_KEY_TYPE_IS_RSA(type)) { return mbedtls_psa_rsa_import_key(attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits); } #endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ } return PSA_ERROR_NOT_SUPPORTED; } /** Calculate the intersection of two algorithm usage policies. * * Return 0 (which allows no operation) on incompatibility. */ static psa_algorithm_t psa_key_policy_algorithm_intersection( psa_key_type_t key_type, psa_algorithm_t alg1, psa_algorithm_t alg2) { /* Common case: both sides actually specify the same policy. */ if (alg1 == alg2) { return alg1; } /* If the policies are from the same hash-and-sign family, check * if one is a wildcard. If so the other has the specific algorithm. */ if (PSA_ALG_IS_SIGN_HASH(alg1) && PSA_ALG_IS_SIGN_HASH(alg2) && (alg1 & ~PSA_ALG_HASH_MASK) == (alg2 & ~PSA_ALG_HASH_MASK)) { if (PSA_ALG_SIGN_GET_HASH(alg1) == PSA_ALG_ANY_HASH) { return alg2; } if (PSA_ALG_SIGN_GET_HASH(alg2) == PSA_ALG_ANY_HASH) { return alg1; } } /* If the policies are from the same AEAD family, check whether * one of them is a minimum-tag-length wildcard. Calculate the most * restrictive tag length. */ if (PSA_ALG_IS_AEAD(alg1) && PSA_ALG_IS_AEAD(alg2) && (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg1, 0) == PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg2, 0))) { size_t alg1_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg1); size_t alg2_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg2); size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len; /* If both are wildcards, return most restrictive wildcard */ if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) && ((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) { return PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( alg1, restricted_len); } /* If only one is a wildcard, return specific algorithm if compatible. */ if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) && (alg1_len <= alg2_len)) { return alg2; } if (((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) && (alg2_len <= alg1_len)) { return alg1; } } /* If the policies are from the same MAC family, check whether one * of them is a minimum-MAC-length policy. Calculate the most * restrictive tag length. */ if (PSA_ALG_IS_MAC(alg1) && PSA_ALG_IS_MAC(alg2) && (PSA_ALG_FULL_LENGTH_MAC(alg1) == PSA_ALG_FULL_LENGTH_MAC(alg2))) { /* Validate the combination of key type and algorithm. Since the base * algorithm of alg1 and alg2 are the same, we only need this once. */ if (PSA_SUCCESS != psa_mac_key_can_do(alg1, key_type)) { return 0; } /* Get the (exact or at-least) output lengths for both sides of the * requested intersection. None of the currently supported algorithms * have an output length dependent on the actual key size, so setting it * to a bogus value of 0 is currently OK. * * Note that for at-least-this-length wildcard algorithms, the output * length is set to the shortest allowed length, which allows us to * calculate the most restrictive tag length for the intersection. */ size_t alg1_len = PSA_MAC_LENGTH(key_type, 0, alg1); size_t alg2_len = PSA_MAC_LENGTH(key_type, 0, alg2); size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len; /* If both are wildcards, return most restrictive wildcard */ if (((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) && ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0)) { return PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg1, restricted_len); } /* If only one is an at-least-this-length policy, the intersection would * be the other (fixed-length) policy as long as said fixed length is * equal to or larger than the shortest allowed length. */ if ((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { return (alg1_len <= alg2_len) ? alg2 : 0; } if ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { return (alg2_len <= alg1_len) ? alg1 : 0; } /* If none of them are wildcards, check whether they define the same tag * length. This is still possible here when one is default-length and * the other specific-length. Ensure to always return the * specific-length version for the intersection. */ if (alg1_len == alg2_len) { return PSA_ALG_TRUNCATED_MAC(alg1, alg1_len); } } /* If the policies are incompatible, allow nothing. */ return 0; } static int psa_key_algorithm_permits(psa_key_type_t key_type, psa_algorithm_t policy_alg, psa_algorithm_t requested_alg) { /* Common case: the policy only allows requested_alg. */ if (requested_alg == policy_alg) { return 1; } /* If policy_alg is a hash-and-sign with a wildcard for the hash, * and requested_alg is the same hash-and-sign family with any hash, * then requested_alg is compliant with policy_alg. */ if (PSA_ALG_IS_SIGN_HASH(requested_alg) && PSA_ALG_SIGN_GET_HASH(policy_alg) == PSA_ALG_ANY_HASH) { return (policy_alg & ~PSA_ALG_HASH_MASK) == (requested_alg & ~PSA_ALG_HASH_MASK); } /* If policy_alg is a wildcard AEAD algorithm of the same base as * the requested algorithm, check the requested tag length to be * equal-length or longer than the wildcard-specified length. */ if (PSA_ALG_IS_AEAD(policy_alg) && PSA_ALG_IS_AEAD(requested_alg) && (PSA_ALG_AEAD_WITH_SHORTENED_TAG(policy_alg, 0) == PSA_ALG_AEAD_WITH_SHORTENED_TAG(requested_alg, 0)) && ((policy_alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) { return PSA_ALG_AEAD_GET_TAG_LENGTH(policy_alg) <= PSA_ALG_AEAD_GET_TAG_LENGTH(requested_alg); } /* If policy_alg is a MAC algorithm of the same base as the requested * algorithm, check whether their MAC lengths are compatible. */ if (PSA_ALG_IS_MAC(policy_alg) && PSA_ALG_IS_MAC(requested_alg) && (PSA_ALG_FULL_LENGTH_MAC(policy_alg) == PSA_ALG_FULL_LENGTH_MAC(requested_alg))) { /* Validate the combination of key type and algorithm. Since the policy * and requested algorithms are the same, we only need this once. */ if (PSA_SUCCESS != psa_mac_key_can_do(policy_alg, key_type)) { return 0; } /* Get both the requested output length for the algorithm which is to be * verified, and the default output length for the base algorithm. * Note that none of the currently supported algorithms have an output * length dependent on actual key size, so setting it to a bogus value * of 0 is currently OK. */ size_t requested_output_length = PSA_MAC_LENGTH( key_type, 0, requested_alg); size_t default_output_length = PSA_MAC_LENGTH( key_type, 0, PSA_ALG_FULL_LENGTH_MAC(requested_alg)); /* If the policy is default-length, only allow an algorithm with * a declared exact-length matching the default. */ if (PSA_MAC_TRUNCATED_LENGTH(policy_alg) == 0) { return requested_output_length == default_output_length; } /* If the requested algorithm is default-length, allow it if the policy * length exactly matches the default length. */ if (PSA_MAC_TRUNCATED_LENGTH(requested_alg) == 0 && PSA_MAC_TRUNCATED_LENGTH(policy_alg) == default_output_length) { return 1; } /* If policy_alg is an at-least-this-length wildcard MAC algorithm, * check for the requested MAC length to be equal to or longer than the * minimum allowed length. */ if ((policy_alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { return PSA_MAC_TRUNCATED_LENGTH(policy_alg) <= requested_output_length; } } /* If policy_alg is a generic key agreement operation, then using it for * a key derivation with that key agreement should also be allowed. This * behaviour is expected to be defined in a future specification version. */ if (PSA_ALG_IS_RAW_KEY_AGREEMENT(policy_alg) && PSA_ALG_IS_KEY_AGREEMENT(requested_alg)) { return PSA_ALG_KEY_AGREEMENT_GET_BASE(requested_alg) == policy_alg; } /* If it isn't explicitly permitted, it's forbidden. */ return 0; } /** Test whether a policy permits an algorithm. * * The caller must test usage flags separately. * * \note This function requires providing the key type for which the policy is * being validated, since some algorithm policy definitions (e.g. MAC) * have different properties depending on what kind of cipher it is * combined with. * * \retval PSA_SUCCESS When \p alg is a specific algorithm * allowed by the \p policy. * \retval PSA_ERROR_INVALID_ARGUMENT When \p alg is not a specific algorithm * \retval PSA_ERROR_NOT_PERMITTED When \p alg is a specific algorithm, but * the \p policy does not allow it. */ static psa_status_t psa_key_policy_permits(const psa_key_policy_t *policy, psa_key_type_t key_type, psa_algorithm_t alg) { /* '0' is not a valid algorithm */ if (alg == 0) { return PSA_ERROR_INVALID_ARGUMENT; } /* A requested algorithm cannot be a wildcard. */ if (PSA_ALG_IS_WILDCARD(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } if (psa_key_algorithm_permits(key_type, policy->alg, alg) || psa_key_algorithm_permits(key_type, policy->alg2, alg)) { return PSA_SUCCESS; } else { return PSA_ERROR_NOT_PERMITTED; } } /** Restrict a key policy based on a constraint. * * \note This function requires providing the key type for which the policy is * being restricted, since some algorithm policy definitions (e.g. MAC) * have different properties depending on what kind of cipher it is * combined with. * * \param[in] key_type The key type for which to restrict the policy * \param[in,out] policy The policy to restrict. * \param[in] constraint The policy constraint to apply. * * \retval #PSA_SUCCESS * \c *policy contains the intersection of the original value of * \c *policy and \c *constraint. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c key_type, \c *policy and \c *constraint are incompatible. * \c *policy is unchanged. */ static psa_status_t psa_restrict_key_policy( psa_key_type_t key_type, psa_key_policy_t *policy, const psa_key_policy_t *constraint) { psa_algorithm_t intersection_alg = psa_key_policy_algorithm_intersection(key_type, policy->alg, constraint->alg); psa_algorithm_t intersection_alg2 = psa_key_policy_algorithm_intersection(key_type, policy->alg2, constraint->alg2); if (intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0) { return PSA_ERROR_INVALID_ARGUMENT; } if (intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0) { return PSA_ERROR_INVALID_ARGUMENT; } policy->usage &= constraint->usage; policy->alg = intersection_alg; policy->alg2 = intersection_alg2; return PSA_SUCCESS; } /** Get the description of a key given its identifier and policy constraints * and lock it. * * The key must have allow all the usage flags set in \p usage. If \p alg is * nonzero, the key must allow operations with this algorithm. If \p alg is * zero, the algorithm is not checked. * * In case of a persistent key, the function loads the description of the key * into a key slot if not already done. * * On success, the returned key slot has been registered for reading. * It is the responsibility of the caller to then unregister * once they have finished reading the contents of the slot. * The caller unregisters by calling psa_unregister_read() or * psa_unregister_read_under_mutex(). psa_unregister_read() must be called * if and only if the caller already holds the global key slot mutex * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates * the unregister with mutex lock and unlock operations. */ static psa_status_t psa_get_and_lock_key_slot_with_policy( mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot, psa_key_usage_t usage, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; status = psa_get_and_lock_key_slot(key, p_slot); if (status != PSA_SUCCESS) { return status; } slot = *p_slot; /* Enforce that usage policy for the key slot contains all the flags * required by the usage parameter. There is one exception: public * keys can always be exported, so we treat public key objects as * if they had the export flag. */ if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) { usage &= ~PSA_KEY_USAGE_EXPORT; } if ((slot->attr.policy.usage & usage) != usage) { status = PSA_ERROR_NOT_PERMITTED; goto error; } /* Enforce that the usage policy permits the requested algorithm. */ if (alg != 0) { status = psa_key_policy_permits(&slot->attr.policy, slot->attr.type, alg); if (status != PSA_SUCCESS) { goto error; } } return PSA_SUCCESS; error: *p_slot = NULL; psa_unregister_read_under_mutex(slot); return status; } /** Get a key slot containing a transparent key and lock it. * * A transparent key is a key for which the key material is directly * available, as opposed to a key in a secure element and/or to be used * by a secure element. * * This is a temporary function that may be used instead of * psa_get_and_lock_key_slot_with_policy() when there is no opaque key support * for a cryptographic operation. * * On success, the returned key slot has been registered for reading. * It is the responsibility of the caller to then unregister * once they have finished reading the contents of the slot. * The caller unregisters by calling psa_unregister_read() or * psa_unregister_read_under_mutex(). psa_unregister_read() must be called * if and only if the caller already holds the global key slot mutex * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates * psa_unregister_read() with mutex lock and unlock operations. */ static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot, psa_key_usage_t usage, psa_algorithm_t alg) { psa_status_t status = psa_get_and_lock_key_slot_with_policy(key, p_slot, usage, alg); if (status != PSA_SUCCESS) { return status; } if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) { psa_unregister_read_under_mutex(*p_slot); *p_slot = NULL; return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot) { if (slot->key.data != NULL) { mbedtls_zeroize_and_free(slot->key.data, slot->key.bytes); } slot->key.data = NULL; slot->key.bytes = 0; return PSA_SUCCESS; } /** Completely wipe a slot in memory, including its policy. * Persistent storage is not affected. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) { psa_status_t status = psa_remove_key_data_from_memory(slot); /* * As the return error code may not be handled in case of multiple errors, * do our best to report an unexpected amount of registered readers or * an unexpected state. * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that the slot is valid for * wiping. * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the * function is called as part of the execution of a test suite, the * execution of the test suite is stopped in error if the assertion fails. */ switch (slot->state) { case PSA_SLOT_FULL: /* In this state psa_wipe_key_slot() must only be called if the * caller is the last reader. */ case PSA_SLOT_PENDING_DELETION: /* In this state psa_wipe_key_slot() must only be called if the * caller is the last reader. */ if (slot->var.occupied.registered_readers != 1) { MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 1); status = PSA_ERROR_CORRUPTION_DETECTED; } break; case PSA_SLOT_FILLING: /* In this state registered_readers must be 0. */ if (slot->var.occupied.registered_readers != 0) { MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 0); status = PSA_ERROR_CORRUPTION_DETECTED; } break; case PSA_SLOT_EMPTY: /* The slot is already empty, it cannot be wiped. */ MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->state != PSA_SLOT_EMPTY); status = PSA_ERROR_CORRUPTION_DETECTED; break; default: /* The slot's state is invalid. */ status = PSA_ERROR_CORRUPTION_DETECTED; } #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) size_t slice_index = slot->slice_index; #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ /* Multipart operations may still be using the key. This is safe * because all multipart operation objects are independent from * the key slot: if they need to access the key after the setup * phase, they have a copy of the key. Note that this means that * key material can linger until all operations are completed. */ /* At this point, key material and other type-specific content has * been wiped. Clear remaining metadata. We can call memset and not * zeroize because the metadata is not particularly sensitive. * This memset also sets the slot's state to PSA_SLOT_EMPTY. */ memset(slot, 0, sizeof(*slot)); #if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) /* If the slot is already corrupted, something went deeply wrong, * like a thread still using the slot or a stray pointer leading * to the slot's memory being used for another object. Let the slot * leak rather than make the corruption worse. */ if (status == PSA_SUCCESS) { status = psa_free_key_slot(slice_index, slot); } #endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */ return status; } psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) { psa_key_slot_t *slot; psa_status_t status; /* status of the last operation */ psa_status_t overall_status = PSA_SUCCESS; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) psa_se_drv_table_entry_t *driver; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ if (mbedtls_svc_key_id_is_null(key)) { return PSA_SUCCESS; } /* * Get the description of the key in a key slot, and register to read it. * In the case of a persistent key, this will load the key description * from persistent memory if not done yet. * We cannot avoid this loading as without it we don't know if * the key is operated by an SE or not and this information is needed by * the current implementation. */ status = psa_get_and_lock_key_slot(key, &slot); if (status != PSA_SUCCESS) { return status; } #if defined(MBEDTLS_THREADING_C) /* We cannot unlock between setting the state to PENDING_DELETION * and destroying the key in storage, as otherwise another thread * could load the key into a new slot and the key will not be * fully destroyed. */ PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); if (slot->state == PSA_SLOT_PENDING_DELETION) { /* Another thread has destroyed the key between us locking the slot * and us gaining the mutex. Unregister from the slot, * and report that the key does not exist. */ status = psa_unregister_read(slot); PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); return (status == PSA_SUCCESS) ? PSA_ERROR_INVALID_HANDLE : status; } #endif /* Set the key slot containing the key description's state to * PENDING_DELETION. This stops new operations from registering * to read the slot. Current readers can safely continue to access * the key within the slot; the last registered reader will * automatically wipe the slot when they call psa_unregister_read(). * If the key is persistent, we can now delete the copy of the key * from memory. If the key is opaque, we require the driver to * deal with the deletion. */ overall_status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL, PSA_SLOT_PENDING_DELETION); if (overall_status != PSA_SUCCESS) { goto exit; } if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) { /* Refuse the destruction of a read-only key (which may or may not work * if we attempt it, depending on whether the key is merely read-only * by policy or actually physically read-only). * Just do the best we can, which is to wipe the copy in memory * (done in this function's cleanup code). */ overall_status = PSA_ERROR_NOT_PERMITTED; goto exit; } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) driver = psa_get_se_driver_entry(slot->attr.lifetime); if (driver != NULL) { /* For a key in a secure element, we need to do three things: * remove the key file in internal storage, destroy the * key inside the secure element, and update the driver's * persistent data. Start a transaction that will encompass these * three actions. */ psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_DESTROY_KEY); psa_crypto_transaction.key.lifetime = slot->attr.lifetime; psa_crypto_transaction.key.slot = psa_key_slot_get_slot_number(slot); psa_crypto_transaction.key.id = slot->attr.id; status = psa_crypto_save_transaction(); if (status != PSA_SUCCESS) { (void) psa_crypto_stop_transaction(); /* We should still try to destroy the key in the secure * element and the key metadata in storage. This is especially * important if the error is that the storage is full. * But how to do it exactly without risking an inconsistent * state after a reset? * https://github.com/ARMmbed/mbed-crypto/issues/215 */ overall_status = status; goto exit; } status = psa_destroy_se_key(driver, psa_key_slot_get_slot_number(slot)); if (overall_status == PSA_SUCCESS) { overall_status = status; } } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { /* Destroy the copy of the persistent key from storage. * The slot will still hold a copy of the key until the last reader * unregisters. */ status = psa_destroy_persistent_key(slot->attr.id); if (overall_status == PSA_SUCCESS) { overall_status = status; } } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if (driver != NULL) { status = psa_save_se_persistent_data(driver); if (overall_status == PSA_SUCCESS) { overall_status = status; } status = psa_crypto_stop_transaction(); if (overall_status == PSA_SUCCESS) { overall_status = status; } } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ exit: /* Unregister from reading the slot. If we are the last active reader * then this will wipe the slot. */ status = psa_unregister_read(slot); /* Prioritize CORRUPTION_DETECTED from unregistering over * a storage error. */ if (status != PSA_SUCCESS) { overall_status = status; } #if defined(MBEDTLS_THREADING_C) /* Don't overwrite existing errors if the unlock fails. */ status = overall_status; PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return overall_status; } /** Retrieve all the publicly-accessible attributes of a key. */ psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, psa_key_attributes_t *attributes) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; psa_reset_key_attributes(attributes); status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0); if (status != PSA_SUCCESS) { return status; } *attributes = slot->attr; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if (psa_get_se_driver_entry(slot->attr.lifetime) != NULL) { psa_set_key_slot_number(attributes, psa_key_slot_get_slot_number(slot)); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ return psa_unregister_read_under_mutex(slot); } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) psa_status_t psa_get_key_slot_number( const psa_key_attributes_t *attributes, psa_key_slot_number_t *slot_number) { if (attributes->has_slot_number) { *slot_number = attributes->slot_number; return PSA_SUCCESS; } else { return PSA_ERROR_INVALID_ARGUMENT; } } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ static psa_status_t psa_export_key_buffer_internal(const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { if (key_buffer_size > data_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(data, key_buffer, key_buffer_size); memset(data + key_buffer_size, 0, data_size - key_buffer_size); *data_length = key_buffer_size; return PSA_SUCCESS; } psa_status_t psa_export_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { psa_key_type_t type = attributes->type; if (key_type_is_raw_bytes(type) || PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) || PSA_KEY_TYPE_IS_DH(type)) { return psa_export_key_buffer_internal( key_buffer, key_buffer_size, data, data_size, data_length); } else { /* This shouldn't happen in the reference implementation, but it is valid for a special-purpose implementation to omit support for exporting certain key types. */ return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t psa_export_key(mbedtls_svc_key_id_t key, uint8_t *data_external, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_OUTPUT_DECLARE(data_external, data); /* Reject a zero-length output buffer now, since this can never be a * valid key representation. This way we know that data must be a valid * pointer and we can do things like memset(data, ..., data_size). */ if (data_size == 0) { return PSA_ERROR_BUFFER_TOO_SMALL; } /* Set the key to empty now, so that even when there are errors, we always * set data_length to a value between 0 and data_size. On error, setting * the key to empty is a good choice because an empty key representation is * unlikely to be accepted anywhere. */ *data_length = 0; /* Export requires the EXPORT flag. There is an exception for public keys, * which don't require any flag, but * psa_get_and_lock_key_slot_with_policy() takes care of this. */ status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_EXPORT, 0); if (status != PSA_SUCCESS) { return status; } LOCAL_OUTPUT_ALLOC(data_external, data_size, data); status = psa_driver_wrapper_export_key(&slot->attr, slot->key.data, slot->key.bytes, data, data_size, data_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_OUTPUT_FREE(data_external, data); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_export_public_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { psa_key_type_t type = attributes->type; if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) && (PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) || PSA_KEY_TYPE_IS_DH(type))) { /* Exporting public -> public */ return psa_export_key_buffer_internal( key_buffer, key_buffer_size, data, data_size, data_length); } else if (PSA_KEY_TYPE_IS_RSA(type)) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) return mbedtls_psa_rsa_export_public_key(attributes, key_buffer, key_buffer_size, data, data_size, data_length); #else /* We don't know how to convert a private RSA key to public. */ return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ } else if (PSA_KEY_TYPE_IS_ECC(type)) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) return mbedtls_psa_ecp_export_public_key(attributes, key_buffer, key_buffer_size, data, data_size, data_length); #else /* We don't know how to convert a private ECC key to public */ return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ } else if (PSA_KEY_TYPE_IS_DH(type)) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) return mbedtls_psa_ffdh_export_public_key(attributes, key_buffer, key_buffer_size, data, data_size, data_length); #else return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */ } else { (void) key_buffer; (void) key_buffer_size; (void) data; (void) data_size; (void) data_length; return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, uint8_t *data_external, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_OUTPUT_DECLARE(data_external, data); /* Reject a zero-length output buffer now, since this can never be a * valid key representation. This way we know that data must be a valid * pointer and we can do things like memset(data, ..., data_size). */ if (data_size == 0) { return PSA_ERROR_BUFFER_TOO_SMALL; } /* Set the key to empty now, so that even when there are errors, we always * set data_length to a value between 0 and data_size. On error, setting * the key to empty is a good choice because an empty key representation is * unlikely to be accepted anywhere. */ *data_length = 0; /* Exporting a public key doesn't require a usage flag. */ status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0); if (status != PSA_SUCCESS) { return status; } LOCAL_OUTPUT_ALLOC(data_external, data_size, data); if (!PSA_KEY_TYPE_IS_ASYMMETRIC(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_driver_wrapper_export_public_key( &slot->attr, slot->key.data, slot->key.bytes, data, data_size, data_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_OUTPUT_FREE(data_external, data); return (status == PSA_SUCCESS) ? unlock_status : status; } /** Validate that a key policy is internally well-formed. * * This function only rejects invalid policies. It does not validate the * consistency of the policy with respect to other attributes of the key * such as the key type. */ static psa_status_t psa_validate_key_policy(const psa_key_policy_t *policy) { if ((policy->usage & ~(PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_DERIVATION | PSA_KEY_USAGE_DERIVE)) != 0) { return PSA_ERROR_INVALID_ARGUMENT; } return PSA_SUCCESS; } /** Validate the internal consistency of key attributes. * * This function only rejects invalid attribute values. If does not * validate the consistency of the attributes with any key data that may * be involved in the creation of the key. * * Call this function early in the key creation process. * * \param[in] attributes Key attributes for the new key. * \param[out] p_drv On any return, the driver for the key, if any. * NULL for a transparent key. * */ static psa_status_t psa_validate_key_attributes( const psa_key_attributes_t *attributes, psa_se_drv_table_entry_t **p_drv) { psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; psa_key_lifetime_t lifetime = psa_get_key_lifetime(attributes); mbedtls_svc_key_id_t key = psa_get_key_id(attributes); status = psa_validate_key_location(lifetime, p_drv); if (status != PSA_SUCCESS) { return status; } status = psa_validate_key_persistence(lifetime); if (status != PSA_SUCCESS) { return status; } if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { if (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key) != 0) { return PSA_ERROR_INVALID_ARGUMENT; } } else { if (!psa_is_valid_key_id(psa_get_key_id(attributes), 0)) { return PSA_ERROR_INVALID_ARGUMENT; } } status = psa_validate_key_policy(&attributes->policy); if (status != PSA_SUCCESS) { return status; } /* Refuse to create overly large keys. * Note that this doesn't trigger on import if the attributes don't * explicitly specify a size (so psa_get_key_bits returns 0), so * psa_import_key() needs its own checks. */ if (psa_get_key_bits(attributes) > PSA_MAX_KEY_BITS) { return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } /** Prepare a key slot to receive key material. * * This function allocates a key slot and sets its metadata. * * If this function fails, call psa_fail_key_creation(). * * This function is intended to be used as follows: * -# Call psa_start_key_creation() to allocate a key slot, prepare * it with the specified attributes, and in case of a volatile key assign it * a volatile key identifier. * -# Populate the slot with the key material. * -# Call psa_finish_key_creation() to finalize the creation of the slot. * In case of failure at any step, stop the sequence and call * psa_fail_key_creation(). * * On success, the key slot's state is PSA_SLOT_FILLING. * It is the responsibility of the caller to change the slot's state to * PSA_SLOT_EMPTY/FULL once key creation has finished. * * \param method An identification of the calling function. * \param[in] attributes Key attributes for the new key. * \param[out] p_slot On success, a pointer to the prepared slot. * \param[out] p_drv On any return, the driver for the key, if any. * NULL for a transparent key. * * \retval #PSA_SUCCESS * The key slot is ready to receive key material. * \return If this function fails, the key slot is an invalid state. * You must call psa_fail_key_creation() to wipe and free the slot. */ static psa_status_t psa_start_key_creation( psa_key_creation_method_t method, const psa_key_attributes_t *attributes, psa_key_slot_t **p_slot, psa_se_drv_table_entry_t **p_drv) { psa_status_t status; (void) method; *p_drv = NULL; status = psa_validate_key_attributes(attributes, p_drv); if (status != PSA_SUCCESS) { return status; } int key_is_volatile = PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime); psa_key_id_t volatile_key_id; #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif status = psa_reserve_free_key_slot( key_is_volatile ? &volatile_key_id : NULL, p_slot); #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif if (status != PSA_SUCCESS) { return status; } psa_key_slot_t *slot = *p_slot; /* We're storing the declared bit-size of the key. It's up to each * creation mechanism to verify that this information is correct. * It's automatically correct for mechanisms that use the bit-size as * an input (generate, device) but not for those where the bit-size * is optional (import, copy). In case of a volatile key, assign it the * volatile key identifier associated to the slot returned to contain its * definition. */ slot->attr = *attributes; if (key_is_volatile) { #if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) slot->attr.id = volatile_key_id; #else slot->attr.id.key_id = volatile_key_id; #endif } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things * when creating or registering a persistent key: * create the key file in internal storage, create the * key inside the secure element, and update the driver's * persistent data. This is done by starting a transaction that will * encompass these three actions. * For registering a volatile key, we just need to find an appropriate * slot number inside the SE. Since the key is designated volatile, creating * a transaction is not required. */ /* The first thing to do is to find a slot number for the new key. * We save the slot number in persistent storage as part of the * transaction data. It will be needed to recover if the power * fails during the key creation process, to clean up on the secure * element side after restarting. Obtaining a slot number from the * secure element driver updates its persistent state, but we do not yet * save the driver's persistent state, so that if the power fails, * we can roll back to a state where the key doesn't exist. */ if (*p_drv != NULL) { psa_key_slot_number_t slot_number; status = psa_find_se_slot_for_key(attributes, method, *p_drv, &slot_number); if (status != PSA_SUCCESS) { return status; } if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) { psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_CREATE_KEY); psa_crypto_transaction.key.lifetime = slot->attr.lifetime; psa_crypto_transaction.key.slot = slot_number; psa_crypto_transaction.key.id = slot->attr.id; status = psa_crypto_save_transaction(); if (status != PSA_SUCCESS) { (void) psa_crypto_stop_transaction(); return status; } } status = psa_copy_key_material_into_slot( slot, (uint8_t *) (&slot_number), sizeof(slot_number)); if (status != PSA_SUCCESS) { return status; } } if (*p_drv == NULL && method == PSA_KEY_CREATION_REGISTER) { /* Key registration only makes sense with a secure element. */ return PSA_ERROR_INVALID_ARGUMENT; } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ return PSA_SUCCESS; } /** Finalize the creation of a key once its key material has been set. * * This entails writing the key to persistent storage. * * If this function fails, call psa_fail_key_creation(). * See the documentation of psa_start_key_creation() for the intended use * of this function. * * If the finalization succeeds, the function sets the key slot's state to * PSA_SLOT_FULL, and the key slot can no longer be accessed as part of the * key creation process. * * \param[in,out] slot Pointer to the slot with key material. * \param[in] driver The secure element driver for the key, * or NULL for a transparent key. * \param[out] key On success, identifier of the key. Note that the * key identifier is also stored in the key slot. * * \retval #PSA_SUCCESS * The key was successfully created. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * * \return If this function fails, the key slot is an invalid state. * You must call psa_fail_key_creation() to wipe and free the slot. */ static psa_status_t psa_finish_key_creation( psa_key_slot_t *slot, psa_se_drv_table_entry_t *driver, mbedtls_svc_key_id_t *key) { psa_status_t status = PSA_SUCCESS; (void) slot; (void) driver; #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if (driver != NULL) { psa_se_key_data_storage_t data; psa_key_slot_number_t slot_number = psa_key_slot_get_slot_number(slot); MBEDTLS_STATIC_ASSERT(sizeof(slot_number) == sizeof(data.slot_number), "Slot number size does not match psa_se_key_data_storage_t"); memcpy(&data.slot_number, &slot_number, sizeof(slot_number)); status = psa_save_persistent_key(&slot->attr, (uint8_t *) &data, sizeof(data)); } else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ { /* Key material is saved in export representation in the slot, so * just pass the slot buffer for storage. */ status = psa_save_persistent_key(&slot->attr, slot->key.data, slot->key.bytes); } } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Finish the transaction for a key creation. This does not * happen when registering an existing key. Detect this case * by checking whether a transaction is in progress (actual * creation of a persistent key in a secure element requires a transaction, * but registration or volatile key creation doesn't use one). */ if (driver != NULL && psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY) { status = psa_save_se_persistent_data(driver); if (status != PSA_SUCCESS) { psa_destroy_persistent_key(slot->attr.id); #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } status = psa_crypto_stop_transaction(); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ if (status == PSA_SUCCESS) { *key = slot->attr.id; status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, PSA_SLOT_FULL); if (status != PSA_SUCCESS) { *key = MBEDTLS_SVC_KEY_ID_INIT; } } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } /** Abort the creation of a key. * * You may call this function after calling psa_start_key_creation(), * or after psa_finish_key_creation() fails. In other circumstances, this * function may not clean up persistent storage. * See the documentation of psa_start_key_creation() for the intended use * of this function. Sets the slot's state to PSA_SLOT_EMPTY. * * \param[in,out] slot Pointer to the slot with key material. * \param[in] driver The secure element driver for the key, * or NULL for a transparent key. */ static void psa_fail_key_creation(psa_key_slot_t *slot, psa_se_drv_table_entry_t *driver) { (void) driver; if (slot == NULL) { return; } #if defined(MBEDTLS_THREADING_C) /* If the lock operation fails we still wipe the slot. * Operations will no longer work after a failed lock, * but we still need to wipe the slot of confidential data. */ mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex); #endif #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* TODO: If the key has already been created in the secure * element, and the failure happened later (when saving metadata * to internal storage), we need to destroy the key in the secure * element. * https://github.com/ARMmbed/mbed-crypto/issues/217 */ /* Abort the ongoing transaction if any (there may not be one if * the creation process failed before starting one, or if the * key creation is a registration of a key in a secure element). * Earlier functions must already have done what it takes to undo any * partial creation. All that's left is to update the transaction data * itself. */ (void) psa_crypto_stop_transaction(); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_wipe_key_slot(slot); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex); #endif } /** Validate optional attributes during key creation. * * Some key attributes are optional during key creation. If they are * specified in the attributes structure, check that they are consistent * with the data in the slot. * * This function should be called near the end of key creation, after * the slot in memory is fully populated but before saving persistent data. */ static psa_status_t psa_validate_optional_attributes( const psa_key_slot_t *slot, const psa_key_attributes_t *attributes) { if (attributes->type != 0) { if (attributes->type != slot->attr.type) { return PSA_ERROR_INVALID_ARGUMENT; } } if (attributes->bits != 0) { if (attributes->bits != slot->attr.bits) { return PSA_ERROR_INVALID_ARGUMENT; } } return PSA_SUCCESS; } psa_status_t psa_import_key(const psa_key_attributes_t *attributes, const uint8_t *data_external, size_t data_length, mbedtls_svc_key_id_t *key) { psa_status_t status; LOCAL_INPUT_DECLARE(data_external, data); psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; size_t bits; size_t storage_size = data_length; *key = MBEDTLS_SVC_KEY_ID_INIT; /* Reject zero-length symmetric keys (including raw data key objects). * This also rejects any key which might be encoded as an empty string, * which is never valid. */ if (data_length == 0) { return PSA_ERROR_INVALID_ARGUMENT; } /* Ensure that the bytes-to-bits conversion cannot overflow. */ if (data_length > SIZE_MAX / 8) { return PSA_ERROR_NOT_SUPPORTED; } LOCAL_INPUT_ALLOC(data_external, data_length, data); status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes, &slot, &driver); if (status != PSA_SUCCESS) { goto exit; } /* In the case of a transparent key or an opaque key stored in local * storage ( thus not in the case of importing a key in a secure element * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a * buffer to hold the imported key material. */ if (slot->key.data == NULL) { if (psa_key_lifetime_is_external(attributes->lifetime)) { status = psa_driver_wrapper_get_key_buffer_size_from_key_data( attributes, data, data_length, &storage_size); if (status != PSA_SUCCESS) { goto exit; } } status = psa_allocate_buffer_to_slot(slot, storage_size); if (status != PSA_SUCCESS) { goto exit; } } bits = slot->attr.bits; status = psa_driver_wrapper_import_key(attributes, data, data_length, slot->key.data, slot->key.bytes, &slot->key.bytes, &bits); if (status != PSA_SUCCESS) { goto exit; } if (slot->attr.bits == 0) { slot->attr.bits = (psa_key_bits_t) bits; } else if (bits != slot->attr.bits) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } /* Enforce a size limit, and in particular ensure that the bit * size fits in its representation type.*/ if (bits > PSA_MAX_KEY_BITS) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = psa_validate_optional_attributes(slot, attributes); if (status != PSA_SUCCESS) { goto exit; } status = psa_finish_key_creation(slot, driver, key); exit: LOCAL_INPUT_FREE(data_external, data); if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } return status; } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) psa_status_t mbedtls_psa_register_se_key( const psa_key_attributes_t *attributes) { psa_status_t status; psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; /* Leaving attributes unspecified is not currently supported. * It could make sense to query the key type and size from the * secure element, but not all secure elements support this * and the driver HAL doesn't currently support it. */ if (psa_get_key_type(attributes) == PSA_KEY_TYPE_NONE) { return PSA_ERROR_NOT_SUPPORTED; } if (psa_get_key_bits(attributes) == 0) { return PSA_ERROR_NOT_SUPPORTED; } /* Not usable with volatile keys, even with an appropriate location, * due to the API design. * https://github.com/Mbed-TLS/mbedtls/issues/9253 */ if (PSA_KEY_LIFETIME_IS_VOLATILE(psa_get_key_lifetime(attributes))) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_start_key_creation(PSA_KEY_CREATION_REGISTER, attributes, &slot, &driver); if (status != PSA_SUCCESS) { goto exit; } status = psa_finish_key_creation(slot, driver, &key); exit: if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } /* Registration doesn't keep the key in RAM. */ psa_close_key(key); return status; } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, const psa_key_attributes_t *specified_attributes, mbedtls_svc_key_id_t *target_key) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *source_slot = NULL; psa_key_slot_t *target_slot = NULL; psa_key_attributes_t actual_attributes = *specified_attributes; psa_se_drv_table_entry_t *driver = NULL; size_t storage_size = 0; *target_key = MBEDTLS_SVC_KEY_ID_INIT; status = psa_get_and_lock_key_slot_with_policy( source_key, &source_slot, PSA_KEY_USAGE_COPY, 0); if (status != PSA_SUCCESS) { goto exit; } status = psa_validate_optional_attributes(source_slot, specified_attributes); if (status != PSA_SUCCESS) { goto exit; } /* The target key type and number of bits have been validated by * psa_validate_optional_attributes() to be either equal to zero or * equal to the ones of the source key. So it is safe to inherit * them from the source key now." * */ actual_attributes.bits = source_slot->attr.bits; actual_attributes.type = source_slot->attr.type; status = psa_restrict_key_policy(source_slot->attr.type, &actual_attributes.policy, &source_slot->attr.policy); if (status != PSA_SUCCESS) { goto exit; } status = psa_start_key_creation(PSA_KEY_CREATION_COPY, &actual_attributes, &target_slot, &driver); if (status != PSA_SUCCESS) { goto exit; } if (PSA_KEY_LIFETIME_GET_LOCATION(target_slot->attr.lifetime) != PSA_KEY_LIFETIME_GET_LOCATION(source_slot->attr.lifetime)) { /* * If the source and target keys are stored in different locations, * the source key would need to be exported as plaintext and re-imported * in the other location. This has security implications which have not * been fully mapped. For now, this can be achieved through * appropriate API invocations from the application, if needed. * */ status = PSA_ERROR_NOT_SUPPORTED; goto exit; } /* * When the source and target keys are within the same location, * - For transparent keys it is a blind copy without any driver invocation, * - For opaque keys this translates to an invocation of the drivers' * copy_key entry point through the dispatch layer. * */ if (psa_key_lifetime_is_external(actual_attributes.lifetime)) { status = psa_driver_wrapper_get_key_buffer_size(&actual_attributes, &storage_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_allocate_buffer_to_slot(target_slot, storage_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_copy_key(&actual_attributes, source_slot->key.data, source_slot->key.bytes, target_slot->key.data, target_slot->key.bytes, &target_slot->key.bytes); if (status != PSA_SUCCESS) { goto exit; } } else { status = psa_copy_key_material_into_slot(target_slot, source_slot->key.data, source_slot->key.bytes); if (status != PSA_SUCCESS) { goto exit; } } status = psa_finish_key_creation(target_slot, driver, target_key); exit: if (status != PSA_SUCCESS) { psa_fail_key_creation(target_slot, driver); } unlock_status = psa_unregister_read_under_mutex(source_slot); return (status == PSA_SUCCESS) ? unlock_status : status; } /****************************************************************/ /* Message digests */ /****************************************************************/ psa_status_t psa_hash_abort(psa_hash_operation_t *operation) { /* Aborting a non-active operation is allowed */ if (operation->id == 0) { return PSA_SUCCESS; } psa_status_t status = psa_driver_wrapper_hash_abort(operation); operation->id = 0; return status; } psa_status_t psa_hash_setup(psa_hash_operation_t *operation, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* A context must be freshly initialized before it can be set up. */ if (operation->id != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!PSA_ALG_IS_HASH(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } /* Ensure all of the context is zeroized, since PSA_HASH_OPERATION_INIT only * directly zeroes the int-sized dummy member of the context union. */ memset(&operation->ctx, 0, sizeof(operation->ctx)); status = psa_driver_wrapper_hash_setup(operation, alg); exit: if (status != PSA_SUCCESS) { psa_hash_abort(operation); } return status; } psa_status_t psa_hash_update(psa_hash_operation_t *operation, const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } /* Don't require hash implementations to behave correctly on a * zero-length input, which may have an invalid pointer. */ if (input_length == 0) { return PSA_SUCCESS; } LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_hash_update(operation, input, input_length); exit: if (status != PSA_SUCCESS) { psa_hash_abort(operation); } LOCAL_INPUT_FREE(input_external, input); return status; } static psa_status_t psa_hash_finish_internal(psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; *hash_length = 0; if (operation->id == 0) { return PSA_ERROR_BAD_STATE; } status = psa_driver_wrapper_hash_finish( operation, hash, hash_size, hash_length); psa_hash_abort(operation); return status; } psa_status_t psa_hash_finish(psa_hash_operation_t *operation, uint8_t *hash_external, size_t hash_size, size_t *hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(hash_external, hash); LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); status = psa_hash_finish_internal(operation, hash, hash_size, hash_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_OUTPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_verify(psa_hash_operation_t *operation, const uint8_t *hash_external, size_t hash_length) { uint8_t actual_hash[PSA_HASH_MAX_SIZE]; size_t actual_hash_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(hash_external, hash); status = psa_hash_finish_internal( operation, actual_hash, sizeof(actual_hash), &actual_hash_length); if (status != PSA_SUCCESS) { goto exit; } if (actual_hash_length != hash_length) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } exit: mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash)); if (status != PSA_SUCCESS) { psa_hash_abort(operation); } LOCAL_INPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_compute(psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *hash_external, size_t hash_size, size_t *hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(hash_external, hash); *hash_length = 0; if (!PSA_ALG_IS_HASH(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); status = psa_driver_wrapper_hash_compute(alg, input, input_length, hash, hash_size, hash_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_compare(psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *hash_external, size_t hash_length) { uint8_t actual_hash[PSA_HASH_MAX_SIZE]; size_t actual_hash_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(hash_external, hash); if (!PSA_ALG_IS_HASH(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; return status; } LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_hash_compute( alg, input, input_length, actual_hash, sizeof(actual_hash), &actual_hash_length); if (status != PSA_SUCCESS) { goto exit; } if (actual_hash_length != hash_length) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } exit: mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash)); LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, psa_hash_operation_t *target_operation) { if (source_operation->id == 0 || target_operation->id != 0) { return PSA_ERROR_BAD_STATE; } psa_status_t status = psa_driver_wrapper_hash_clone(source_operation, target_operation); if (status != PSA_SUCCESS) { psa_hash_abort(target_operation); } return status; } /****************************************************************/ /* MAC */ /****************************************************************/ psa_status_t psa_mac_abort(psa_mac_operation_t *operation) { /* Aborting a non-active operation is allowed */ if (operation->id == 0) { return PSA_SUCCESS; } psa_status_t status = psa_driver_wrapper_mac_abort(operation); operation->mac_size = 0; operation->is_sign = 0; operation->id = 0; return status; } static psa_status_t psa_mac_finalize_alg_and_key_validation( psa_algorithm_t alg, const psa_key_attributes_t *attributes, uint8_t *mac_size) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t key_type = psa_get_key_type(attributes); size_t key_bits = psa_get_key_bits(attributes); if (!PSA_ALG_IS_MAC(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } /* Validate the combination of key type and algorithm */ status = psa_mac_key_can_do(alg, key_type); if (status != PSA_SUCCESS) { return status; } /* Get the output length for the algorithm and key combination */ *mac_size = PSA_MAC_LENGTH(key_type, key_bits, alg); if (*mac_size < 4) { /* A very short MAC is too short for security since it can be * brute-forced. Ancient protocols with 32-bit MACs do exist, * so we make this our minimum, even though 32 bits is still * too small for security. */ return PSA_ERROR_NOT_SUPPORTED; } if (*mac_size > PSA_MAC_LENGTH(key_type, key_bits, PSA_ALG_FULL_LENGTH_MAC(alg))) { /* It's impossible to "truncate" to a larger length than the full length * of the algorithm. */ return PSA_ERROR_INVALID_ARGUMENT; } if (*mac_size > PSA_MAC_MAX_SIZE) { /* PSA_MAC_LENGTH returns the correct length even for a MAC algorithm * that is disabled in the compile-time configuration. The result can * therefore be larger than PSA_MAC_MAX_SIZE, which does take the * configuration into account. In this case, force a return of * PSA_ERROR_NOT_SUPPORTED here. Otherwise psa_mac_verify(), or * psa_mac_compute(mac_size=PSA_MAC_MAX_SIZE), would return * PSA_ERROR_BUFFER_TOO_SMALL for an unsupported algorithm whose MAC size * is larger than PSA_MAC_MAX_SIZE, which is misleading and which breaks * systematically generated tests. */ return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } static psa_status_t psa_mac_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, int is_sign) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; /* A context must be freshly initialized before it can be set up. */ if (operation->id != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE, alg); if (status != PSA_SUCCESS) { goto exit; } status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr, &operation->mac_size); if (status != PSA_SUCCESS) { goto exit; } operation->is_sign = is_sign; /* Dispatch the MAC setup call with validated input */ if (is_sign) { status = psa_driver_wrapper_mac_sign_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } else { status = psa_driver_wrapper_mac_verify_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } exit: if (status != PSA_SUCCESS) { psa_mac_abort(operation); } unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_mac_setup(operation, key, alg, 1); } psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_mac_setup(operation, key, alg, 0); } psa_status_t psa_mac_update(psa_mac_operation_t *operation, const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; return status; } /* Don't require hash implementations to behave correctly on a * zero-length input, which may have an invalid pointer. */ if (input_length == 0) { status = PSA_SUCCESS; return status; } LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_mac_update(operation, input, input_length); if (status != PSA_SUCCESS) { psa_mac_abort(operation); } #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); return status; } psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, uint8_t *mac_external, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(mac_external, mac); LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!operation->is_sign) { status = PSA_ERROR_BAD_STATE; goto exit; } /* Sanity check. This will guarantee that mac_size != 0 (and so mac != NULL) * once all the error checks are done. */ if (operation->mac_size == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (mac_size < operation->mac_size) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } status = psa_driver_wrapper_mac_sign_finish(operation, mac, operation->mac_size, mac_length); exit: /* In case of success, set the potential excess room in the output buffer * to an invalid value, to avoid potentially leaking a longer MAC. * In case of error, set the output length and content to a safe default, * such that in case the caller misses an error check, the output would be * an unachievable MAC. */ if (status != PSA_SUCCESS) { *mac_length = mac_size; operation->mac_size = 0; } if (mac != NULL) { psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length); } abort_status = psa_mac_abort(operation); LOCAL_OUTPUT_FREE(mac_external, mac); return status == PSA_SUCCESS ? abort_status : status; } psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, const uint8_t *mac_external, size_t mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(mac_external, mac); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->is_sign) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->mac_size != mac_length) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); status = psa_driver_wrapper_mac_verify_finish(operation, mac, mac_length); exit: abort_status = psa_mac_abort(operation); LOCAL_INPUT_FREE(mac_external, mac); return status == PSA_SUCCESS ? abort_status : status; } static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length, int is_sign) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; uint8_t operation_mac_size = 0; status = psa_get_and_lock_key_slot_with_policy( key, &slot, is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE, alg); if (status != PSA_SUCCESS) { goto exit; } status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr, &operation_mac_size); if (status != PSA_SUCCESS) { goto exit; } if (mac_size < operation_mac_size) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } status = psa_driver_wrapper_mac_compute( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, mac, operation_mac_size, mac_length); exit: /* In case of success, set the potential excess room in the output buffer * to an invalid value, to avoid potentially leaking a longer MAC. * In case of error, set the output length and content to a safe default, * such that in case the caller misses an error check, the output would be * an unachievable MAC. */ if (status != PSA_SUCCESS) { *mac_length = mac_size; operation_mac_size = 0; } psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length); unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *mac_external, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(mac_external, mac); LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); status = psa_mac_compute_internal(key, alg, input, input_length, mac, mac_size, mac_length, 1); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(mac_external, mac); return status; } psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *mac_external, size_t mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t actual_mac[PSA_MAC_MAX_SIZE]; size_t actual_mac_length; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(mac_external, mac); LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_mac_compute_internal(key, alg, input, input_length, actual_mac, sizeof(actual_mac), &actual_mac_length, 0); if (status != PSA_SUCCESS) { goto exit; } if (mac_length != actual_mac_length) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); if (mbedtls_ct_memcmp(mac, actual_mac, actual_mac_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } exit: mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac)); LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(mac_external, mac); return status; } /****************************************************************/ /* Asymmetric cryptography */ /****************************************************************/ static psa_status_t psa_sign_verify_check_alg(int input_is_message, psa_algorithm_t alg) { if (input_is_message) { if (!PSA_ALG_IS_SIGN_MESSAGE(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } if (PSA_ALG_IS_SIGN_HASH(alg)) { if (!PSA_ALG_IS_HASH(PSA_ALG_SIGN_GET_HASH(alg))) { return PSA_ERROR_INVALID_ARGUMENT; } } } else { if (!PSA_ALG_IS_SIGN_HASH(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } } return PSA_SUCCESS; } static psa_status_t psa_sign_internal(mbedtls_svc_key_id_t key, int input_is_message, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; *signature_length = 0; status = psa_sign_verify_check_alg(input_is_message, alg); if (status != PSA_SUCCESS) { return status; } /* Immediately reject a zero-length signature buffer. This guarantees * that signature must be a valid pointer. (On the other hand, the input * buffer can in principle be empty since it doesn't actually have * to be a hash.) */ if (signature_size == 0) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, input_is_message ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_SIGN_HASH, alg); if (status != PSA_SUCCESS) { goto exit; } if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } if (input_is_message) { status = psa_driver_wrapper_sign_message( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_size, signature_length); } else { status = psa_driver_wrapper_sign_hash( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_size, signature_length); } exit: psa_wipe_tag_output_buffer(signature, status, signature_size, *signature_length); unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } static psa_status_t psa_verify_internal(mbedtls_svc_key_id_t key, int input_is_message, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; status = psa_sign_verify_check_alg(input_is_message, alg); if (status != PSA_SUCCESS) { return status; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, input_is_message ? PSA_KEY_USAGE_VERIFY_MESSAGE : PSA_KEY_USAGE_VERIFY_HASH, alg); if (status != PSA_SUCCESS) { return status; } if (input_is_message) { status = psa_driver_wrapper_verify_message( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_length); } else { status = psa_driver_wrapper_verify_hash( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_length); } unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_sign_message_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (PSA_ALG_IS_SIGN_HASH(alg)) { size_t hash_length; uint8_t hash[PSA_HASH_MAX_SIZE]; status = psa_driver_wrapper_hash_compute( PSA_ALG_SIGN_GET_HASH(alg), input, input_length, hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { return status; } return psa_driver_wrapper_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length); } return PSA_ERROR_NOT_SUPPORTED; } psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *signature_external, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(signature_external, signature); LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); status = psa_sign_internal(key, 1, alg, input, input_length, signature, signature_size, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(signature_external, signature); return status; } psa_status_t psa_verify_message_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (PSA_ALG_IS_SIGN_HASH(alg)) { size_t hash_length; uint8_t hash[PSA_HASH_MAX_SIZE]; status = psa_driver_wrapper_hash_compute( PSA_ALG_SIGN_GET_HASH(alg), input, input_length, hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { return status; } return psa_driver_wrapper_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length); } return PSA_ERROR_NOT_SUPPORTED; } psa_status_t psa_verify_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *signature_external, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(signature_external, signature); LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); status = psa_verify_internal(key, 1, alg, input, input_length, signature, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(signature_external, signature); return status; } psa_status_t psa_sign_hash_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || PSA_ALG_IS_RSA_PSS(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) return mbedtls_psa_rsa_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ } else { return PSA_ERROR_INVALID_ARGUMENT; } } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) { if (PSA_ALG_IS_ECDSA(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) return mbedtls_psa_ecdsa_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ } else { return PSA_ERROR_INVALID_ARGUMENT; } } (void) key_buffer; (void) key_buffer_size; (void) hash; (void) hash_length; (void) signature; (void) signature_size; (void) signature_length; return PSA_ERROR_NOT_SUPPORTED; } psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash_external, size_t hash_length, uint8_t *signature_external, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(hash_external, hash); LOCAL_OUTPUT_DECLARE(signature_external, signature); LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); status = psa_sign_internal(key, 0, alg, hash, hash_length, signature, signature_size, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(hash_external, hash); LOCAL_OUTPUT_FREE(signature_external, signature); return status; } psa_status_t psa_verify_hash_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { if (PSA_KEY_TYPE_IS_RSA(attributes->type)) { if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || PSA_ALG_IS_RSA_PSS(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) return mbedtls_psa_rsa_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ } else { return PSA_ERROR_INVALID_ARGUMENT; } } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) { if (PSA_ALG_IS_ECDSA(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) return mbedtls_psa_ecdsa_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ } else { return PSA_ERROR_INVALID_ARGUMENT; } } (void) key_buffer; (void) key_buffer_size; (void) hash; (void) hash_length; (void) signature; (void) signature_length; return PSA_ERROR_NOT_SUPPORTED; } psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash_external, size_t hash_length, const uint8_t *signature_external, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(hash_external, hash); LOCAL_INPUT_DECLARE(signature_external, signature); LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); status = psa_verify_internal(key, 0, alg, hash, hash_length, signature, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(hash_external, hash); LOCAL_INPUT_FREE(signature_external, signature); return status; } psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *salt_external, size_t salt_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(salt_external, salt); LOCAL_OUTPUT_DECLARE(output_external, output); (void) input; (void) input_length; (void) salt; (void) output; (void) output_size; *output_length = 0; if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); if (status != PSA_SUCCESS) { return status; } if (!(PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type) || PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type))) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_asymmetric_encrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, salt, salt_length, output, output_size, output_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(salt_external, salt); LOCAL_OUTPUT_FREE(output_external, output); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *salt_external, size_t salt_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(salt_external, salt); LOCAL_OUTPUT_DECLARE(output_external, output); (void) input; (void) input_length; (void) salt; (void) output; (void) output_size; *output_length = 0; if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_DECRYPT, alg); if (status != PSA_SUCCESS) { return status; } if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_asymmetric_decrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, salt, salt_length, output, output_size, output_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(salt_external, salt); LOCAL_OUTPUT_FREE(output_external, output); return (status == PSA_SUCCESS) ? unlock_status : status; } /****************************************************************/ /* Asymmetric interruptible cryptography */ /****************************************************************/ static uint32_t psa_interruptible_max_ops = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED; void psa_interruptible_set_max_ops(uint32_t max_ops) { psa_interruptible_max_ops = max_ops; } uint32_t psa_interruptible_get_max_ops(void) { return psa_interruptible_max_ops; } uint32_t psa_sign_hash_get_num_ops( const psa_sign_hash_interruptible_operation_t *operation) { return operation->num_ops; } uint32_t psa_verify_hash_get_num_ops( const psa_verify_hash_interruptible_operation_t *operation) { return operation->num_ops; } static psa_status_t psa_sign_hash_abort_internal( psa_sign_hash_interruptible_operation_t *operation) { if (operation->id == 0) { /* The object has (apparently) been initialized but it is not (yet) * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_driver_wrapper_sign_hash_abort(operation); operation->id = 0; /* Do not clear either the error_occurred or num_ops elements here as they * only want to be cleared by the application calling abort, not by abort * being called at completion of an operation. */ return status; } psa_status_t psa_sign_hash_start( psa_sign_hash_interruptible_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash_external, size_t hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(hash_external, hash); /* Check that start has not been previously called, or operation has not * previously errored. */ if (operation->id != 0 || operation->error_occurred) { return PSA_ERROR_BAD_STATE; } status = psa_sign_verify_check_alg(0, alg); if (status != PSA_SUCCESS) { operation->error_occurred = 1; return status; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_SIGN_HASH, alg); if (status != PSA_SUCCESS) { goto exit; } if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); /* Ensure ops count gets reset, in case of operation re-use. */ operation->num_ops = 0; status = psa_driver_wrapper_sign_hash_start(operation, &slot->attr, slot->key.data, slot->key.bytes, alg, hash, hash_length); exit: if (status != PSA_SUCCESS) { operation->error_occurred = 1; psa_sign_hash_abort_internal(operation); } unlock_status = psa_unregister_read_under_mutex(slot); if (unlock_status != PSA_SUCCESS) { operation->error_occurred = 1; } LOCAL_INPUT_FREE(hash_external, hash); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_sign_hash_complete( psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature_external, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(signature_external, signature); *signature_length = 0; /* Check that start has been called first, and that operation has not * previously errored. */ if (operation->id == 0 || operation->error_occurred) { status = PSA_ERROR_BAD_STATE; goto exit; } /* Immediately reject a zero-length signature buffer. This guarantees that * signature must be a valid pointer. */ if (signature_size == 0) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); status = psa_driver_wrapper_sign_hash_complete(operation, signature, signature_size, signature_length); /* Update ops count with work done. */ operation->num_ops = psa_driver_wrapper_sign_hash_get_num_ops(operation); exit: if (signature != NULL) { psa_wipe_tag_output_buffer(signature, status, signature_size, *signature_length); } if (status != PSA_OPERATION_INCOMPLETE) { if (status != PSA_SUCCESS) { operation->error_occurred = 1; } psa_sign_hash_abort_internal(operation); } LOCAL_OUTPUT_FREE(signature_external, signature); return status; } psa_status_t psa_sign_hash_abort( psa_sign_hash_interruptible_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_sign_hash_abort_internal(operation); /* We clear the number of ops done here, so that it is not cleared when * the operation fails or succeeds, only on manual abort. */ operation->num_ops = 0; /* Likewise, failure state. */ operation->error_occurred = 0; return status; } static psa_status_t psa_verify_hash_abort_internal( psa_verify_hash_interruptible_operation_t *operation) { if (operation->id == 0) { /* The object has (apparently) been initialized but it is not (yet) * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_driver_wrapper_verify_hash_abort(operation); operation->id = 0; /* Do not clear either the error_occurred or num_ops elements here as they * only want to be cleared by the application calling abort, not by abort * being called at completion of an operation. */ return status; } psa_status_t psa_verify_hash_start( psa_verify_hash_interruptible_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash_external, size_t hash_length, const uint8_t *signature_external, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(hash_external, hash); LOCAL_INPUT_DECLARE(signature_external, signature); /* Check that start has not been previously called, or operation has not * previously errored. */ if (operation->id != 0 || operation->error_occurred) { return PSA_ERROR_BAD_STATE; } status = psa_sign_verify_check_alg(0, alg); if (status != PSA_SUCCESS) { operation->error_occurred = 1; return status; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_VERIFY_HASH, alg); if (status != PSA_SUCCESS) { operation->error_occurred = 1; return status; } LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); /* Ensure ops count gets reset, in case of operation re-use. */ operation->num_ops = 0; status = psa_driver_wrapper_verify_hash_start(operation, &slot->attr, slot->key.data, slot->key.bytes, alg, hash, hash_length, signature, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif if (status != PSA_SUCCESS) { operation->error_occurred = 1; psa_verify_hash_abort_internal(operation); } unlock_status = psa_unregister_read_under_mutex(slot); if (unlock_status != PSA_SUCCESS) { operation->error_occurred = 1; } LOCAL_INPUT_FREE(hash_external, hash); LOCAL_INPUT_FREE(signature_external, signature); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_verify_hash_complete( psa_verify_hash_interruptible_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Check that start has been called first, and that operation has not * previously errored. */ if (operation->id == 0 || operation->error_occurred) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_driver_wrapper_verify_hash_complete(operation); /* Update ops count with work done. */ operation->num_ops = psa_driver_wrapper_verify_hash_get_num_ops( operation); exit: if (status != PSA_OPERATION_INCOMPLETE) { if (status != PSA_SUCCESS) { operation->error_occurred = 1; } psa_verify_hash_abort_internal(operation); } return status; } psa_status_t psa_verify_hash_abort( psa_verify_hash_interruptible_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_verify_hash_abort_internal(operation); /* We clear the number of ops done here, so that it is not cleared when * the operation fails or succeeds, only on manual abort. */ operation->num_ops = 0; /* Likewise, failure state. */ operation->error_occurred = 0; return status; } /****************************************************************/ /* Asymmetric interruptible cryptography internal */ /* implementations */ /****************************************************************/ void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) /* Internal implementation uses zero to indicate infinite number max ops, * therefore avoid this value, and set to minimum possible. */ if (max_ops == 0) { max_ops = 1; } mbedtls_ecp_set_max_ops(max_ops); #else (void) max_ops; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } uint32_t mbedtls_psa_sign_hash_get_num_ops( const mbedtls_psa_sign_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) return operation->num_ops; #else (void) operation; return 0; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } uint32_t mbedtls_psa_verify_hash_get_num_ops( const mbedtls_psa_verify_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) return operation->num_ops; #else (void) operation; return 0; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_sign_hash_start( mbedtls_psa_sign_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t required_hash_length; if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) { return PSA_ERROR_NOT_SUPPORTED; } if (!PSA_ALG_IS_ECDSA(alg)) { return PSA_ERROR_NOT_SUPPORTED; } #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecdsa_restart_init(&operation->restart_ctx); /* Ensure num_ops is zero'ed in case of context re-use. */ operation->num_ops = 0; status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, key_buffer, key_buffer_size, &operation->ctx); if (status != PSA_SUCCESS) { return status; } operation->coordinate_bytes = PSA_BITS_TO_BYTES( operation->ctx->grp.nbits); psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); operation->md_alg = mbedtls_md_type_from_psa_alg(hash_alg); operation->alg = alg; /* We only need to store the same length of hash as the private key size * here, it would be truncated by the internal implementation anyway. */ required_hash_length = (hash_length < operation->coordinate_bytes ? hash_length : operation->coordinate_bytes); if (required_hash_length > sizeof(operation->hash)) { /* Shouldn't happen, but better safe than sorry. */ return PSA_ERROR_CORRUPTION_DETECTED; } memcpy(operation->hash, hash, required_hash_length); operation->hash_length = required_hash_length; return PSA_SUCCESS; #else (void) operation; (void) key_buffer; (void) key_buffer_size; (void) alg; (void) hash; (void) hash_length; (void) status; (void) required_hash_length; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_sign_hash_complete( mbedtls_psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature, size_t signature_size, size_t *signature_length) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_mpi r; mbedtls_mpi s; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); /* Ensure max_ops is set to the current value (or default). */ mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops()); if (signature_size < 2 * operation->coordinate_bytes) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) status = mbedtls_to_psa_error( mbedtls_ecdsa_sign_det_restartable(&operation->ctx->grp, &r, &s, &operation->ctx->d, operation->hash, operation->hash_length, operation->md_alg, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, &operation->restart_ctx)); #else /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ status = PSA_ERROR_NOT_SUPPORTED; goto exit; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ } else { status = mbedtls_to_psa_error( mbedtls_ecdsa_sign_restartable(&operation->ctx->grp, &r, &s, &operation->ctx->d, operation->hash, operation->hash_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, &operation->restart_ctx)); } /* Hide the fact that the restart context only holds a delta of number of * ops done during the last operation, not an absolute value. */ operation->num_ops += operation->restart_ctx.ecp.ops_done; if (status == PSA_SUCCESS) { status = mbedtls_to_psa_error( mbedtls_mpi_write_binary(&r, signature, operation->coordinate_bytes) ); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_to_psa_error( mbedtls_mpi_write_binary(&s, signature + operation->coordinate_bytes, operation->coordinate_bytes) ); if (status != PSA_SUCCESS) { goto exit; } *signature_length = operation->coordinate_bytes * 2; status = PSA_SUCCESS; } exit: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); return status; #else (void) operation; (void) signature; (void) signature_size; (void) signature_length; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_sign_hash_abort( mbedtls_psa_sign_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) if (operation->ctx) { mbedtls_ecdsa_free(operation->ctx); mbedtls_free(operation->ctx); operation->ctx = NULL; } mbedtls_ecdsa_restart_free(&operation->restart_ctx); operation->num_ops = 0; return PSA_SUCCESS; #else (void) operation; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_verify_hash_start( mbedtls_psa_verify_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t coordinate_bytes = 0; size_t required_hash_length = 0; if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) { return PSA_ERROR_NOT_SUPPORTED; } if (!PSA_ALG_IS_ECDSA(alg)) { return PSA_ERROR_NOT_SUPPORTED; } #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecdsa_restart_init(&operation->restart_ctx); mbedtls_mpi_init(&operation->r); mbedtls_mpi_init(&operation->s); /* Ensure num_ops is zero'ed in case of context re-use. */ operation->num_ops = 0; status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, key_buffer, key_buffer_size, &operation->ctx); if (status != PSA_SUCCESS) { return status; } coordinate_bytes = PSA_BITS_TO_BYTES(operation->ctx->grp.nbits); if (signature_length != 2 * coordinate_bytes) { return PSA_ERROR_INVALID_SIGNATURE; } status = mbedtls_to_psa_error( mbedtls_mpi_read_binary(&operation->r, signature, coordinate_bytes)); if (status != PSA_SUCCESS) { return status; } status = mbedtls_to_psa_error( mbedtls_mpi_read_binary(&operation->s, signature + coordinate_bytes, coordinate_bytes)); if (status != PSA_SUCCESS) { return status; } status = mbedtls_psa_ecp_load_public_part(operation->ctx); if (status != PSA_SUCCESS) { return status; } /* We only need to store the same length of hash as the private key size * here, it would be truncated by the internal implementation anyway. */ required_hash_length = (hash_length < coordinate_bytes ? hash_length : coordinate_bytes); if (required_hash_length > sizeof(operation->hash)) { /* Shouldn't happen, but better safe than sorry. */ return PSA_ERROR_CORRUPTION_DETECTED; } memcpy(operation->hash, hash, required_hash_length); operation->hash_length = required_hash_length; return PSA_SUCCESS; #else (void) operation; (void) key_buffer; (void) key_buffer_size; (void) alg; (void) hash; (void) hash_length; (void) signature; (void) signature_length; (void) status; (void) coordinate_bytes; (void) required_hash_length; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_verify_hash_complete( mbedtls_psa_verify_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Ensure max_ops is set to the current value (or default). */ mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops()); status = mbedtls_to_psa_error( mbedtls_ecdsa_verify_restartable(&operation->ctx->grp, operation->hash, operation->hash_length, &operation->ctx->Q, &operation->r, &operation->s, &operation->restart_ctx)); /* Hide the fact that the restart context only holds a delta of number of * ops done during the last operation, not an absolute value. */ operation->num_ops += operation->restart_ctx.ecp.ops_done; return status; #else (void) operation; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_verify_hash_abort( mbedtls_psa_verify_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) if (operation->ctx) { mbedtls_ecdsa_free(operation->ctx); mbedtls_free(operation->ctx); operation->ctx = NULL; } mbedtls_ecdsa_restart_free(&operation->restart_ctx); operation->num_ops = 0; mbedtls_mpi_free(&operation->r); mbedtls_mpi_free(&operation->s); return PSA_SUCCESS; #else (void) operation; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } static psa_status_t psa_generate_random_internal(uint8_t *output, size_t output_size) { GUARD_MODULE_INITIALIZED; #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) psa_status_t status; size_t output_length = 0; status = mbedtls_psa_external_get_random(&global_data.rng, output, output_size, &output_length); if (status != PSA_SUCCESS) { return status; } /* Breaking up a request into smaller chunks is currently not supported * for the external RNG interface. */ if (output_length != output_size) { return PSA_ERROR_INSUFFICIENT_ENTROPY; } return PSA_SUCCESS; #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ while (output_size > 0) { int ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; size_t request_size = (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ? MBEDTLS_PSA_RANDOM_MAX_REQUEST : output_size); #if defined(MBEDTLS_CTR_DRBG_C) ret = mbedtls_ctr_drbg_random(&global_data.rng.drbg, output, request_size); #elif defined(MBEDTLS_HMAC_DRBG_C) ret = mbedtls_hmac_drbg_random(&global_data.rng.drbg, output, request_size); #endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ if (ret != 0) { return mbedtls_to_psa_error(ret); } output_size -= request_size; output += request_size; } return PSA_SUCCESS; #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } /****************************************************************/ /* Symmetric cryptography */ /****************************************************************/ static psa_status_t psa_cipher_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, mbedtls_operation_t cipher_operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; psa_key_usage_t usage = (cipher_operation == MBEDTLS_ENCRYPT ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); /* A context must be freshly initialized before it can be set up. */ if (operation->id != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!PSA_ALG_IS_CIPHER(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg); if (status != PSA_SUCCESS) { goto exit; } /* Initialize the operation struct members, except for id. The id member * is used to indicate to psa_cipher_abort that there are resources to free, * so we only set it (in the driver wrapper) after resources have been * allocated/initialized. */ operation->iv_set = 0; if (alg == PSA_ALG_ECB_NO_PADDING) { operation->iv_required = 0; } else { operation->iv_required = 1; } operation->default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); /* Try doing the operation through a driver before using software fallback. */ if (cipher_operation == MBEDTLS_ENCRYPT) { status = psa_driver_wrapper_cipher_encrypt_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } else { status = psa_driver_wrapper_cipher_decrypt_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } exit: if (status != PSA_SUCCESS) { psa_cipher_abort(operation); } unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_cipher_setup(operation, key, alg, MBEDTLS_ENCRYPT); } psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_cipher_setup(operation, key, alg, MBEDTLS_DECRYPT); } psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, uint8_t *iv_external, size_t iv_size, size_t *iv_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t default_iv_length = 0; LOCAL_OUTPUT_DECLARE(iv_external, iv); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->iv_set || !operation->iv_required) { status = PSA_ERROR_BAD_STATE; goto exit; } default_iv_length = operation->default_iv_length; if (iv_size < default_iv_length) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { status = PSA_ERROR_GENERIC_ERROR; goto exit; } LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv); status = psa_generate_random_internal(iv, default_iv_length); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_cipher_set_iv(operation, iv, default_iv_length); exit: if (status == PSA_SUCCESS) { *iv_length = default_iv_length; operation->iv_set = 1; } else { *iv_length = 0; psa_cipher_abort(operation); if (iv != NULL) { mbedtls_platform_zeroize(iv, default_iv_length); } } LOCAL_OUTPUT_FREE(iv_external, iv); return status; } psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, const uint8_t *iv_external, size_t iv_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(iv_external, iv); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->iv_set || !operation->iv_required) { status = PSA_ERROR_BAD_STATE; goto exit; } if (iv_length > PSA_CIPHER_IV_MAX_SIZE) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(iv_external, iv_length, iv); status = psa_driver_wrapper_cipher_set_iv(operation, iv, iv_length); exit: if (status == PSA_SUCCESS) { operation->iv_set = 1; } else { psa_cipher_abort(operation); } LOCAL_INPUT_FREE(iv_external, iv); return status; } psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, const uint8_t *input_external, size_t input_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(output_external, output); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->iv_required && !operation->iv_set) { status = PSA_ERROR_BAD_STATE; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_cipher_update(operation, input, input_length, output, output_size, output_length); exit: if (status != PSA_SUCCESS) { psa_cipher_abort(operation); } LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(output_external, output); return status; } psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; LOCAL_OUTPUT_DECLARE(output_external, output); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->iv_required && !operation->iv_set) { status = PSA_ERROR_BAD_STATE; goto exit; } LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_cipher_finish(operation, output, output_size, output_length); exit: if (status == PSA_SUCCESS) { status = psa_cipher_abort(operation); } else { *output_length = 0; (void) psa_cipher_abort(operation); } LOCAL_OUTPUT_FREE(output_external, output); return status; } psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) { if (operation->id == 0) { /* The object has (apparently) been initialized but it is not (yet) * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } psa_driver_wrapper_cipher_abort(operation); operation->id = 0; operation->iv_set = 0; operation->iv_required = 0; return PSA_SUCCESS; } psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; size_t default_iv_length = 0; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(output_external, output); if (!PSA_ALG_IS_CIPHER(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); if (status != PSA_SUCCESS) { goto exit; } default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { status = PSA_ERROR_GENERIC_ERROR; goto exit; } if (default_iv_length > 0) { if (output_size < default_iv_length) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } status = psa_generate_random_internal(local_iv, default_iv_length); if (status != PSA_SUCCESS) { goto exit; } } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_cipher_encrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, local_iv, default_iv_length, input, input_length, psa_crypto_buffer_offset(output, default_iv_length), output_size - default_iv_length, output_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); if (status == PSA_SUCCESS) { status = unlock_status; } if (status == PSA_SUCCESS) { if (default_iv_length > 0) { memcpy(output, local_iv, default_iv_length); } *output_length += default_iv_length; } else { *output_length = 0; } LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(output_external, output); return status; } psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(output_external, output); if (!PSA_ALG_IS_CIPHER(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_DECRYPT, alg); if (status != PSA_SUCCESS) { goto exit; } if (input_length < PSA_CIPHER_IV_LENGTH(slot->attr.type, alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_cipher_decrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, output, output_size, output_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); if (status == PSA_SUCCESS) { status = unlock_status; } if (status != PSA_SUCCESS) { *output_length = 0; } LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(output_external, output); return status; } /****************************************************************/ /* AEAD */ /****************************************************************/ /* Helper function to get the base algorithm from its variants. */ static psa_algorithm_t psa_aead_get_base_algorithm(psa_algorithm_t alg) { return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg); } /* Helper function to perform common nonce length checks. */ static psa_status_t psa_aead_check_nonce_length(psa_algorithm_t alg, size_t nonce_length) { psa_algorithm_t base_alg = psa_aead_get_base_algorithm(alg); switch (base_alg) { #if defined(PSA_WANT_ALG_GCM) case PSA_ALG_GCM: /* Not checking max nonce size here as GCM spec allows almost * arbitrarily large nonces. Please note that we do not generally * recommend the usage of nonces of greater length than * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter * size, which can then lead to collisions if you encrypt a very * large number of messages.*/ if (nonce_length != 0) { return PSA_SUCCESS; } break; #endif /* PSA_WANT_ALG_GCM */ #if defined(PSA_WANT_ALG_CCM) case PSA_ALG_CCM: if (nonce_length >= 7 && nonce_length <= 13) { return PSA_SUCCESS; } break; #endif /* PSA_WANT_ALG_CCM */ #if defined(PSA_WANT_ALG_CHACHA20_POLY1305) case PSA_ALG_CHACHA20_POLY1305: if (nonce_length == 12) { return PSA_SUCCESS; } else if (nonce_length == 8) { return PSA_ERROR_NOT_SUPPORTED; } break; #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ default: (void) nonce_length; return PSA_ERROR_NOT_SUPPORTED; } return PSA_ERROR_INVALID_ARGUMENT; } static psa_status_t psa_aead_check_algorithm(psa_algorithm_t alg) { if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } return PSA_SUCCESS; } psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *nonce_external, size_t nonce_length, const uint8_t *additional_data_external, size_t additional_data_length, const uint8_t *plaintext_external, size_t plaintext_length, uint8_t *ciphertext_external, size_t ciphertext_size, size_t *ciphertext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(nonce_external, nonce); LOCAL_INPUT_DECLARE(additional_data_external, additional_data); LOCAL_INPUT_DECLARE(plaintext_external, plaintext); LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext); *ciphertext_length = 0; status = psa_aead_check_algorithm(alg); if (status != PSA_SUCCESS) { return status; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); if (status != PSA_SUCCESS) { return status; } LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data); LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext); LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext); status = psa_aead_check_nonce_length(alg, nonce_length); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_aead_encrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, nonce, nonce_length, additional_data, additional_data_length, plaintext, plaintext_length, ciphertext, ciphertext_size, ciphertext_length); if (status != PSA_SUCCESS && ciphertext_size != 0) { memset(ciphertext, 0, ciphertext_size); } exit: LOCAL_INPUT_FREE(nonce_external, nonce); LOCAL_INPUT_FREE(additional_data_external, additional_data); LOCAL_INPUT_FREE(plaintext_external, plaintext); LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext); psa_unregister_read_under_mutex(slot); return status; } psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *nonce_external, size_t nonce_length, const uint8_t *additional_data_external, size_t additional_data_length, const uint8_t *ciphertext_external, size_t ciphertext_length, uint8_t *plaintext_external, size_t plaintext_size, size_t *plaintext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(nonce_external, nonce); LOCAL_INPUT_DECLARE(additional_data_external, additional_data); LOCAL_INPUT_DECLARE(ciphertext_external, ciphertext); LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext); *plaintext_length = 0; status = psa_aead_check_algorithm(alg); if (status != PSA_SUCCESS) { return status; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_DECRYPT, alg); if (status != PSA_SUCCESS) { return status; } LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data); LOCAL_INPUT_ALLOC(ciphertext_external, ciphertext_length, ciphertext); LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext); status = psa_aead_check_nonce_length(alg, nonce_length); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_aead_decrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, nonce, nonce_length, additional_data, additional_data_length, ciphertext, ciphertext_length, plaintext, plaintext_size, plaintext_length); if (status != PSA_SUCCESS && plaintext_size != 0) { memset(plaintext, 0, plaintext_size); } exit: LOCAL_INPUT_FREE(nonce_external, nonce); LOCAL_INPUT_FREE(additional_data_external, additional_data); LOCAL_INPUT_FREE(ciphertext_external, ciphertext); LOCAL_OUTPUT_FREE(plaintext_external, plaintext); psa_unregister_read_under_mutex(slot); return status; } static psa_status_t psa_validate_tag_length(psa_algorithm_t alg) { const uint8_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { #if defined(PSA_WANT_ALG_CCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.*/ if (tag_len < 4 || tag_len > 16 || tag_len % 2) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif /* PSA_WANT_ALG_CCM */ #if defined(PSA_WANT_ALG_GCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. */ if (tag_len != 4 && tag_len != 8 && (tag_len < 12 || tag_len > 16)) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif /* PSA_WANT_ALG_GCM */ #if defined(PSA_WANT_ALG_CHACHA20_POLY1305) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): /* We only support the default tag length. */ if (tag_len != 16) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ default: (void) tag_len; return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } /* Set the key for a multipart authenticated operation. */ static psa_status_t psa_aead_setup(psa_aead_operation_t *operation, int is_encrypt, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; psa_key_usage_t key_usage = 0; status = psa_aead_check_algorithm(alg); if (status != PSA_SUCCESS) { goto exit; } if (operation->id != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->nonce_set || operation->lengths_set || operation->ad_started || operation->body_started) { status = PSA_ERROR_BAD_STATE; goto exit; } if (is_encrypt) { key_usage = PSA_KEY_USAGE_ENCRYPT; } else { key_usage = PSA_KEY_USAGE_DECRYPT; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, key_usage, alg); if (status != PSA_SUCCESS) { goto exit; } if ((status = psa_validate_tag_length(alg)) != PSA_SUCCESS) { goto exit; } if (is_encrypt) { status = psa_driver_wrapper_aead_encrypt_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } else { status = psa_driver_wrapper_aead_decrypt_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } if (status != PSA_SUCCESS) { goto exit; } operation->key_type = psa_get_key_type(&slot->attr); exit: unlock_status = psa_unregister_read_under_mutex(slot); if (status == PSA_SUCCESS) { status = unlock_status; operation->alg = psa_aead_get_base_algorithm(alg); operation->is_encrypt = is_encrypt; } else { psa_aead_abort(operation); } return status; } /* Set the key for a multipart authenticated encryption operation. */ psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_aead_setup(operation, 1, key, alg); } /* Set the key for a multipart authenticated decryption operation. */ psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_aead_setup(operation, 0, key, alg); } static psa_status_t psa_aead_set_nonce_internal(psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->nonce_set) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_aead_check_nonce_length(operation->alg, nonce_length); if (status != PSA_SUCCESS) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_driver_wrapper_aead_set_nonce(operation, nonce, nonce_length); exit: if (status == PSA_SUCCESS) { operation->nonce_set = 1; } else { psa_aead_abort(operation); } return status; } /* Generate a random nonce / IV for multipart AEAD operation */ psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, uint8_t *nonce_external, size_t nonce_size, size_t *nonce_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t local_nonce[PSA_AEAD_NONCE_MAX_SIZE]; size_t required_nonce_size = 0; LOCAL_OUTPUT_DECLARE(nonce_external, nonce); LOCAL_OUTPUT_ALLOC(nonce_external, nonce_size, nonce); *nonce_length = 0; if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->nonce_set || !operation->is_encrypt) { status = PSA_ERROR_BAD_STATE; goto exit; } /* For CCM, this size may not be correct according to the PSA * specification. The PSA Crypto 1.0.1 specification states: * * CCM encodes the plaintext length pLen in L octets, with L the smallest * integer >= 2 where pLen < 2^(8L). The nonce length is then 15 - L bytes. * * However this restriction that L has to be the smallest integer is not * applied in practice, and it is not implementable here since the * plaintext length may or may not be known at this time. */ required_nonce_size = PSA_AEAD_NONCE_LENGTH(operation->key_type, operation->alg); if (nonce_size < required_nonce_size) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } status = psa_generate_random_internal(local_nonce, required_nonce_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_aead_set_nonce_internal(operation, local_nonce, required_nonce_size); exit: if (status == PSA_SUCCESS) { memcpy(nonce, local_nonce, required_nonce_size); *nonce_length = required_nonce_size; } else { psa_aead_abort(operation); } LOCAL_OUTPUT_FREE(nonce_external, nonce); return status; } /* Set the nonce for a multipart authenticated encryption or decryption operation.*/ psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, const uint8_t *nonce_external, size_t nonce_length) { psa_status_t status; LOCAL_INPUT_DECLARE(nonce_external, nonce); LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); status = psa_aead_set_nonce_internal(operation, nonce, nonce_length); /* Exit label is only needed for buffer copying, prevent unused warnings. */ #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(nonce_external, nonce); return status; } /* Declare the lengths of the message and additional data for multipart AEAD. */ psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->lengths_set || operation->ad_started || operation->body_started) { status = PSA_ERROR_BAD_STATE; goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_GCM) case PSA_ALG_GCM: /* Lengths can only be too large for GCM if size_t is bigger than 32 * bits. Without the guard this code will generate warnings on 32bit * builds. */ #if SIZE_MAX > UINT32_MAX if (((uint64_t) ad_length) >> 61 != 0 || ((uint64_t) plaintext_length) > 0xFFFFFFFE0ull) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } #endif break; #endif /* PSA_WANT_ALG_GCM */ #if defined(PSA_WANT_ALG_CCM) case PSA_ALG_CCM: if (ad_length > 0xFF00) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } break; #endif /* PSA_WANT_ALG_CCM */ #if defined(PSA_WANT_ALG_CHACHA20_POLY1305) case PSA_ALG_CHACHA20_POLY1305: /* No length restrictions for ChaChaPoly. */ break; #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ default: break; } status = psa_driver_wrapper_aead_set_lengths(operation, ad_length, plaintext_length); exit: if (status == PSA_SUCCESS) { operation->ad_remaining = ad_length; operation->body_remaining = plaintext_length; operation->lengths_set = 1; } else { psa_aead_abort(operation); } return status; } /* Pass additional data to an active multipart AEAD operation. */ psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_ALLOC(input_external, input_length, input); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!operation->nonce_set || operation->body_started) { status = PSA_ERROR_BAD_STATE; goto exit; } /* No input to add (zero length), nothing to do. */ if (input_length == 0) { status = PSA_SUCCESS; goto exit; } if (operation->lengths_set) { if (operation->ad_remaining < input_length) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } operation->ad_remaining -= input_length; } #if defined(PSA_WANT_ALG_CCM) else if (operation->alg == PSA_ALG_CCM) { status = PSA_ERROR_BAD_STATE; goto exit; } #endif /* PSA_WANT_ALG_CCM */ status = psa_driver_wrapper_aead_update_ad(operation, input, input_length); exit: if (status == PSA_SUCCESS) { operation->ad_started = 1; } else { psa_aead_abort(operation); } LOCAL_INPUT_FREE(input_external, input); return status; } /* Encrypt or decrypt a message fragment in an active multipart AEAD operation.*/ psa_status_t psa_aead_update(psa_aead_operation_t *operation, const uint8_t *input_external, size_t input_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(output_external, output); LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); *output_length = 0; if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!operation->nonce_set) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->lengths_set) { /* Additional data length was supplied, but not all the additional data was supplied.*/ if (operation->ad_remaining != 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } /* Too much data provided. */ if (operation->body_remaining < input_length) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } operation->body_remaining -= input_length; } #if defined(PSA_WANT_ALG_CCM) else if (operation->alg == PSA_ALG_CCM) { status = PSA_ERROR_BAD_STATE; goto exit; } #endif /* PSA_WANT_ALG_CCM */ status = psa_driver_wrapper_aead_update(operation, input, input_length, output, output_size, output_length); exit: if (status == PSA_SUCCESS) { operation->body_started = 1; } else { psa_aead_abort(operation); } LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(output_external, output); return status; } static psa_status_t psa_aead_final_checks(const psa_aead_operation_t *operation) { if (operation->id == 0 || !operation->nonce_set) { return PSA_ERROR_BAD_STATE; } if (operation->lengths_set && (operation->ad_remaining != 0 || operation->body_remaining != 0)) { return PSA_ERROR_INVALID_ARGUMENT; } return PSA_SUCCESS; } /* Finish encrypting a message in a multipart AEAD operation. */ psa_status_t psa_aead_finish(psa_aead_operation_t *operation, uint8_t *ciphertext_external, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag_external, size_t tag_size, size_t *tag_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext); LOCAL_OUTPUT_DECLARE(tag_external, tag); LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext); LOCAL_OUTPUT_ALLOC(tag_external, tag_size, tag); *ciphertext_length = 0; *tag_length = tag_size; status = psa_aead_final_checks(operation); if (status != PSA_SUCCESS) { goto exit; } if (!operation->is_encrypt) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_driver_wrapper_aead_finish(operation, ciphertext, ciphertext_size, ciphertext_length, tag, tag_size, tag_length); exit: /* In case the operation fails and the user fails to check for failure or * the zero tag size, make sure the tag is set to something implausible. * Even if the operation succeeds, make sure we clear the rest of the * buffer to prevent potential leakage of anything previously placed in * the same buffer.*/ psa_wipe_tag_output_buffer(tag, status, tag_size, *tag_length); psa_aead_abort(operation); LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext); LOCAL_OUTPUT_FREE(tag_external, tag); return status; } /* Finish authenticating and decrypting a message in a multipart AEAD operation.*/ psa_status_t psa_aead_verify(psa_aead_operation_t *operation, uint8_t *plaintext_external, size_t plaintext_size, size_t *plaintext_length, const uint8_t *tag_external, size_t tag_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext); LOCAL_INPUT_DECLARE(tag_external, tag); LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext); LOCAL_INPUT_ALLOC(tag_external, tag_length, tag); *plaintext_length = 0; status = psa_aead_final_checks(operation); if (status != PSA_SUCCESS) { goto exit; } if (operation->is_encrypt) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_driver_wrapper_aead_verify(operation, plaintext, plaintext_size, plaintext_length, tag, tag_length); exit: psa_aead_abort(operation); LOCAL_OUTPUT_FREE(plaintext_external, plaintext); LOCAL_INPUT_FREE(tag_external, tag); return status; } /* Abort an AEAD operation. */ psa_status_t psa_aead_abort(psa_aead_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->id == 0) { /* The object has (apparently) been initialized but it is not (yet) * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } status = psa_driver_wrapper_aead_abort(operation); memset(operation, 0, sizeof(*operation)); return status; } /****************************************************************/ /* Generators */ /****************************************************************/ #if defined(BUILTIN_ALG_ANY_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \ defined(PSA_HAVE_SOFT_PBKDF2) #define AT_LEAST_ONE_BUILTIN_KDF #endif /* At least one builtin KDF */ #if defined(BUILTIN_ALG_ANY_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) static psa_status_t psa_key_derivation_start_hmac( psa_mac_operation_t *operation, psa_algorithm_t hash_alg, const uint8_t *hmac_key, size_t hmac_key_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(hmac_key_length)); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); operation->is_sign = 1; operation->mac_size = PSA_HASH_LENGTH(hash_alg); status = psa_driver_wrapper_mac_sign_setup(operation, &attributes, hmac_key, hmac_key_length, PSA_ALG_HMAC(hash_alg)); psa_reset_key_attributes(&attributes); return status; } #endif /* KDF algorithms reliant on HMAC */ #define HKDF_STATE_INIT 0 /* no input yet */ #define HKDF_STATE_STARTED 1 /* got salt */ #define HKDF_STATE_KEYED 2 /* got key */ #define HKDF_STATE_OUTPUT 3 /* output started */ static psa_algorithm_t psa_key_derivation_get_kdf_alg( const psa_key_derivation_operation_t *operation) { if (PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { return PSA_ALG_KEY_AGREEMENT_GET_KDF(operation->alg); } else { return operation->alg; } } psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation) { psa_status_t status = PSA_SUCCESS; psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); if (kdf_alg == 0) { /* The object has (apparently) been initialized but it is not * in use. It's ok to call abort on such an object, and there's * nothing to do. */ } else #if defined(BUILTIN_ALG_ANY_HKDF) if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { mbedtls_free(operation->ctx.hkdf.info); status = psa_mac_abort(&operation->ctx.hkdf.hmac); } else #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */ PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { if (operation->ctx.tls12_prf.secret != NULL) { mbedtls_zeroize_and_free(operation->ctx.tls12_prf.secret, operation->ctx.tls12_prf.secret_length); } if (operation->ctx.tls12_prf.seed != NULL) { mbedtls_zeroize_and_free(operation->ctx.tls12_prf.seed, operation->ctx.tls12_prf.seed_length); } if (operation->ctx.tls12_prf.label != NULL) { mbedtls_zeroize_and_free(operation->ctx.tls12_prf.label, operation->ctx.tls12_prf.label_length); } #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (operation->ctx.tls12_prf.other_secret != NULL) { mbedtls_zeroize_and_free(operation->ctx.tls12_prf.other_secret, operation->ctx.tls12_prf.other_secret_length); } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ status = PSA_SUCCESS; /* We leave the fields Ai and output_block to be erased safely by the * mbedtls_platform_zeroize() in the end of this function. */ } else #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { mbedtls_platform_zeroize(operation->ctx.tls12_ecjpake_to_pms.data, sizeof(operation->ctx.tls12_ecjpake_to_pms.data)); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) */ #if defined(PSA_HAVE_SOFT_PBKDF2) if (PSA_ALG_IS_PBKDF2(kdf_alg)) { if (operation->ctx.pbkdf2.salt != NULL) { mbedtls_zeroize_and_free(operation->ctx.pbkdf2.salt, operation->ctx.pbkdf2.salt_length); } status = PSA_SUCCESS; } else #endif /* defined(PSA_HAVE_SOFT_PBKDF2) */ { status = PSA_ERROR_BAD_STATE; } mbedtls_platform_zeroize(operation, sizeof(*operation)); return status; } psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation, size_t *capacity) { if (operation->alg == 0) { /* This is a blank key derivation operation. */ return PSA_ERROR_BAD_STATE; } *capacity = operation->capacity; return PSA_SUCCESS; } psa_status_t psa_key_derivation_set_capacity(psa_key_derivation_operation_t *operation, size_t capacity) { if (operation->alg == 0) { return PSA_ERROR_BAD_STATE; } if (capacity > operation->capacity) { return PSA_ERROR_INVALID_ARGUMENT; } operation->capacity = capacity; return PSA_SUCCESS; } #if defined(BUILTIN_ALG_ANY_HKDF) /* Read some bytes from an HKDF-based operation. */ static psa_status_t psa_key_derivation_hkdf_read(psa_hkdf_key_derivation_t *hkdf, psa_algorithm_t kdf_alg, uint8_t *output, size_t output_length) { psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); size_t hmac_output_length; psa_status_t status; #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) const uint8_t last_block = PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) ? 0 : 0xff; #else const uint8_t last_block = 0xff; #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ if (hkdf->state < HKDF_STATE_KEYED || (!hkdf->info_set #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) && !PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ )) { return PSA_ERROR_BAD_STATE; } hkdf->state = HKDF_STATE_OUTPUT; while (output_length != 0) { /* Copy what remains of the current block */ uint8_t n = hash_length - hkdf->offset_in_block; if (n > output_length) { n = (uint8_t) output_length; } memcpy(output, hkdf->output_block + hkdf->offset_in_block, n); output += n; output_length -= n; hkdf->offset_in_block += n; if (output_length == 0) { break; } /* We can't be wanting more output after the last block, otherwise * the capacity check in psa_key_derivation_output_bytes() would have * prevented this call. It could happen only if the operation * object was corrupted or if this function is called directly * inside the library. */ if (hkdf->block_number == last_block) { return PSA_ERROR_BAD_STATE; } /* We need a new block */ ++hkdf->block_number; hkdf->offset_in_block = 0; status = psa_key_derivation_start_hmac(&hkdf->hmac, hash_alg, hkdf->prk, hash_length); if (status != PSA_SUCCESS) { return status; } if (hkdf->block_number != 1) { status = psa_mac_update(&hkdf->hmac, hkdf->output_block, hash_length); if (status != PSA_SUCCESS) { return status; } } status = psa_mac_update(&hkdf->hmac, hkdf->info, hkdf->info_length); if (status != PSA_SUCCESS) { return status; } status = psa_mac_update(&hkdf->hmac, &hkdf->block_number, 1); if (status != PSA_SUCCESS) { return status; } status = psa_mac_sign_finish(&hkdf->hmac, hkdf->output_block, sizeof(hkdf->output_block), &hmac_output_length); if (status != PSA_SUCCESS) { return status; } } return PSA_SUCCESS; } #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( psa_tls12_prf_key_derivation_t *tls12_prf, psa_algorithm_t alg) { psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(alg); uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); psa_mac_operation_t hmac = PSA_MAC_OPERATION_INIT; size_t hmac_output_length; psa_status_t status, cleanup_status; /* We can't be wanting more output after block 0xff, otherwise * the capacity check in psa_key_derivation_output_bytes() would have * prevented this call. It could happen only if the operation * object was corrupted or if this function is called directly * inside the library. */ if (tls12_prf->block_number == 0xff) { return PSA_ERROR_CORRUPTION_DETECTED; } /* We need a new block */ ++tls12_prf->block_number; tls12_prf->left_in_block = hash_length; /* Recall the definition of the TLS-1.2-PRF from RFC 5246: * * PRF(secret, label, seed) = P_(secret, label + seed) * * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + * HMAC_hash(secret, A(2) + seed) + * HMAC_hash(secret, A(3) + seed) + ... * * A(0) = seed * A(i) = HMAC_hash(secret, A(i-1)) * * The `psa_tls12_prf_key_derivation` structure saves the block * `HMAC_hash(secret, A(i) + seed)` from which the output * is currently extracted as `output_block` and where i is * `block_number`. */ status = psa_key_derivation_start_hmac(&hmac, hash_alg, tls12_prf->secret, tls12_prf->secret_length); if (status != PSA_SUCCESS) { goto cleanup; } /* Calculate A(i) where i = tls12_prf->block_number. */ if (tls12_prf->block_number == 1) { /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads * the variable seed and in this instance means it in the context of the * P_hash function, where seed = label + seed.) */ status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length); if (status != PSA_SUCCESS) { goto cleanup; } } else { /* A(i) = HMAC_hash(secret, A(i-1)) */ status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); if (status != PSA_SUCCESS) { goto cleanup; } } status = psa_mac_sign_finish(&hmac, tls12_prf->Ai, hash_length, &hmac_output_length); if (hmac_output_length != hash_length) { status = PSA_ERROR_CORRUPTION_DETECTED; } if (status != PSA_SUCCESS) { goto cleanup; } /* Calculate HMAC_hash(secret, A(i) + label + seed). */ status = psa_key_derivation_start_hmac(&hmac, hash_alg, tls12_prf->secret, tls12_prf->secret_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_sign_finish(&hmac, tls12_prf->output_block, hash_length, &hmac_output_length); if (status != PSA_SUCCESS) { goto cleanup; } cleanup: cleanup_status = psa_mac_abort(&hmac); if (status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS) { status = cleanup_status; } return status; } static psa_status_t psa_key_derivation_tls12_prf_read( psa_tls12_prf_key_derivation_t *tls12_prf, psa_algorithm_t alg, uint8_t *output, size_t output_length) { psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH(alg); uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); psa_status_t status; uint8_t offset, length; switch (tls12_prf->state) { case PSA_TLS12_PRF_STATE_LABEL_SET: tls12_prf->state = PSA_TLS12_PRF_STATE_OUTPUT; break; case PSA_TLS12_PRF_STATE_OUTPUT: break; default: return PSA_ERROR_BAD_STATE; } while (output_length != 0) { /* Check if we have fully processed the current block. */ if (tls12_prf->left_in_block == 0) { status = psa_key_derivation_tls12_prf_generate_next_block(tls12_prf, alg); if (status != PSA_SUCCESS) { return status; } continue; } if (tls12_prf->left_in_block > output_length) { length = (uint8_t) output_length; } else { length = tls12_prf->left_in_block; } offset = hash_length - tls12_prf->left_in_block; memcpy(output, tls12_prf->output_block + offset, length); output += length; output_length -= length; tls12_prf->left_in_block -= length; } return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) static psa_status_t psa_key_derivation_tls12_ecjpake_to_pms_read( psa_tls12_ecjpake_to_pms_t *ecjpake, uint8_t *output, size_t output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_size = 0; if (output_length != 32) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_hash_compute(PSA_ALG_SHA_256, ecjpake->data, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE, output, output_length, &output_size); if (status != PSA_SUCCESS) { return status; } if (output_size != output_length) { return PSA_ERROR_GENERIC_ERROR; } return PSA_SUCCESS; } #endif #if defined(PSA_HAVE_SOFT_PBKDF2) static psa_status_t psa_key_derivation_pbkdf2_generate_block( psa_pbkdf2_key_derivation_t *pbkdf2, psa_algorithm_t prf_alg, uint8_t prf_output_length, psa_key_attributes_t *attributes) { psa_status_t status; psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT; size_t mac_output_length; uint8_t U_i[PSA_MAC_MAX_SIZE]; uint8_t *U_accumulator = pbkdf2->output_block; uint64_t i; uint8_t block_counter[4]; mac_operation.is_sign = 1; mac_operation.mac_size = prf_output_length; MBEDTLS_PUT_UINT32_BE(pbkdf2->block_number, block_counter, 0); status = psa_driver_wrapper_mac_sign_setup(&mac_operation, attributes, pbkdf2->password, pbkdf2->password_length, prf_alg); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&mac_operation, pbkdf2->salt, pbkdf2->salt_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&mac_operation, block_counter, sizeof(block_counter)); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_sign_finish(&mac_operation, U_i, sizeof(U_i), &mac_output_length); if (status != PSA_SUCCESS) { goto cleanup; } if (mac_output_length != prf_output_length) { status = PSA_ERROR_CORRUPTION_DETECTED; goto cleanup; } memcpy(U_accumulator, U_i, prf_output_length); for (i = 1; i < pbkdf2->input_cost; i++) { /* We are passing prf_output_length as mac_size because the driver * function directly sets mac_output_length as mac_size upon success. * See https://github.com/Mbed-TLS/mbedtls/issues/7801 */ status = psa_driver_wrapper_mac_compute(attributes, pbkdf2->password, pbkdf2->password_length, prf_alg, U_i, prf_output_length, U_i, prf_output_length, &mac_output_length); if (status != PSA_SUCCESS) { goto cleanup; } mbedtls_xor(U_accumulator, U_accumulator, U_i, prf_output_length); } cleanup: /* Zeroise buffers to clear sensitive data from memory. */ mbedtls_platform_zeroize(U_i, PSA_MAC_MAX_SIZE); return status; } static psa_status_t psa_key_derivation_pbkdf2_read( psa_pbkdf2_key_derivation_t *pbkdf2, psa_algorithm_t kdf_alg, uint8_t *output, size_t output_length) { psa_status_t status; psa_algorithm_t prf_alg; uint8_t prf_output_length; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(pbkdf2->password_length)); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { prf_alg = PSA_ALG_HMAC(PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg)); prf_output_length = PSA_HASH_LENGTH(prf_alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); } else if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { prf_alg = PSA_ALG_CMAC; prf_output_length = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); } else { return PSA_ERROR_INVALID_ARGUMENT; } switch (pbkdf2->state) { case PSA_PBKDF2_STATE_PASSWORD_SET: /* Initially we need a new block so bytes_used is equal to block size*/ pbkdf2->bytes_used = prf_output_length; pbkdf2->state = PSA_PBKDF2_STATE_OUTPUT; break; case PSA_PBKDF2_STATE_OUTPUT: break; default: return PSA_ERROR_BAD_STATE; } while (output_length != 0) { uint8_t n = prf_output_length - pbkdf2->bytes_used; if (n > output_length) { n = (uint8_t) output_length; } memcpy(output, pbkdf2->output_block + pbkdf2->bytes_used, n); output += n; output_length -= n; pbkdf2->bytes_used += n; if (output_length == 0) { break; } /* We need a new block */ pbkdf2->bytes_used = 0; pbkdf2->block_number++; status = psa_key_derivation_pbkdf2_generate_block(pbkdf2, prf_alg, prf_output_length, &attributes); if (status != PSA_SUCCESS) { return status; } } return PSA_SUCCESS; } #endif /* PSA_HAVE_SOFT_PBKDF2 */ psa_status_t psa_key_derivation_output_bytes( psa_key_derivation_operation_t *operation, uint8_t *output_external, size_t output_length) { psa_status_t status; LOCAL_OUTPUT_DECLARE(output_external, output); psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); if (operation->alg == 0) { /* This is a blank operation. */ return PSA_ERROR_BAD_STATE; } if (output_length == 0 && operation->capacity == 0) { /* Edge case: this is a finished operation, and 0 bytes * were requested. The right error in this case could * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return * INSUFFICIENT_CAPACITY, which is right for a finished * operation, for consistency with the case when * output_length > 0. */ return PSA_ERROR_INSUFFICIENT_DATA; } LOCAL_OUTPUT_ALLOC(output_external, output_length, output); if (output_length > operation->capacity) { operation->capacity = 0; /* Go through the error path to wipe all confidential data now * that the operation object is useless. */ status = PSA_ERROR_INSUFFICIENT_DATA; goto exit; } operation->capacity -= output_length; #if defined(BUILTIN_ALG_ANY_HKDF) if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { status = psa_key_derivation_hkdf_read(&operation->ctx.hkdf, kdf_alg, output, output_length); } else #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { status = psa_key_derivation_tls12_prf_read(&operation->ctx.tls12_prf, kdf_alg, output, output_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { status = psa_key_derivation_tls12_ecjpake_to_pms_read( &operation->ctx.tls12_ecjpake_to_pms, output, output_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(PSA_HAVE_SOFT_PBKDF2) if (PSA_ALG_IS_PBKDF2(kdf_alg)) { status = psa_key_derivation_pbkdf2_read(&operation->ctx.pbkdf2, kdf_alg, output, output_length); } else #endif /* PSA_HAVE_SOFT_PBKDF2 */ { (void) kdf_alg; status = PSA_ERROR_BAD_STATE; LOCAL_OUTPUT_FREE(output_external, output); return status; } exit: if (status != PSA_SUCCESS) { /* Preserve the algorithm upon errors, but clear all sensitive state. * This allows us to differentiate between exhausted operations and * blank operations, so we can return PSA_ERROR_BAD_STATE on blank * operations. */ psa_algorithm_t alg = operation->alg; psa_key_derivation_abort(operation); operation->alg = alg; if (output != NULL) { memset(output, '!', output_length); } } LOCAL_OUTPUT_FREE(output_external, output); return status; } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) static void psa_des_set_key_parity(uint8_t *data, size_t data_size) { if (data_size >= 8) { mbedtls_des_key_set_parity(data); } if (data_size >= 16) { mbedtls_des_key_set_parity(data + 8); } if (data_size >= 24) { mbedtls_des_key_set_parity(data + 16); } } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ /* * ECC keys on a Weierstrass elliptic curve require the generation * of a private key which is an integer * in the range [1, N - 1], where N is the boundary of the private key domain: * N is the prime p for Diffie-Hellman, or the order of the * curve’s base point for ECC. * * Let m be the bit size of N, such that 2^m > N >= 2^(m-1). * This function generates the private key using the following process: * * 1. Draw a byte string of length ceiling(m/8) bytes. * 2. If m is not a multiple of 8, set the most significant * (8 * ceiling(m/8) - m) bits of the first byte in the string to zero. * 3. Convert the string to integer k by decoding it as a big-endian byte string. * 4. If k > N - 2, discard the result and return to step 1. * 5. Output k + 1 as the private key. * * This method allows compliance to NIST standards, specifically the methods titled * Key-Pair Generation by Testing Candidates in the following publications: * - NIST Special Publication 800-56A: Recommendation for Pair-Wise Key-Establishment * Schemes Using Discrete Logarithm Cryptography [SP800-56A] §5.6.1.1.4 for * Diffie-Hellman keys. * * - [SP800-56A] §5.6.1.2.2 or FIPS Publication 186-4: Digital Signature * Standard (DSS) [FIPS186-4] §B.4.2 for elliptic curve keys. * * Note: Function allocates memory for *data buffer, so given *data should be * always NULL. */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper( psa_key_slot_t *slot, size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data ) { unsigned key_out_of_range = 1; mbedtls_mpi k; mbedtls_mpi diff_N_2; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t m; size_t m_bytes; mbedtls_mpi_init(&k); mbedtls_mpi_init(&diff_N_2); psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( slot->attr.type); mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_from_psa(curve, bits); if (grp_id == MBEDTLS_ECP_DP_NONE) { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto cleanup; } mbedtls_ecp_group ecp_group; mbedtls_ecp_group_init(&ecp_group); MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ecp_group, grp_id)); /* N is the boundary of the private key domain (ecp_group.N). */ /* Let m be the bit size of N. */ m = ecp_group.nbits; m_bytes = PSA_BITS_TO_BYTES(m); /* Calculate N - 2 - it will be needed later. */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&diff_N_2, &ecp_group.N, 2)); /* Note: This function is always called with *data == NULL and it * allocates memory for the data buffer. */ *data = mbedtls_calloc(1, m_bytes); if (*data == NULL) { ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED; goto cleanup; } while (key_out_of_range) { /* 1. Draw a byte string of length ceiling(m/8) bytes. */ if ((status = psa_key_derivation_output_bytes(operation, *data, m_bytes)) != 0) { goto cleanup; } /* 2. If m is not a multiple of 8 */ if (m % 8 != 0) { /* Set the most significant * (8 * ceiling(m/8) - m) bits of the first byte in * the string to zero. */ uint8_t clear_bit_mask = (1 << (m % 8)) - 1; (*data)[0] &= clear_bit_mask; } /* 3. Convert the string to integer k by decoding it as a * big-endian byte string. */ MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&k, *data, m_bytes)); /* 4. If k > N - 2, discard the result and return to step 1. * Result of comparison is returned. When it indicates error * then this function is called again. */ MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(&diff_N_2, &k, &key_out_of_range)); } /* 5. Output k + 1 as the private key. */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&k, &k, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&k, *data, m_bytes)); cleanup: if (ret != 0) { status = mbedtls_to_psa_error(ret); } if (status != PSA_SUCCESS) { mbedtls_free(*data); *data = NULL; } mbedtls_mpi_free(&k); mbedtls_mpi_free(&diff_N_2); return status; } /* ECC keys on a Montgomery elliptic curve draws a byte string whose length * is determined by the curve, and sets the mandatory bits accordingly. That is: * * - Curve25519 (PSA_ECC_FAMILY_MONTGOMERY, 255 bits): * draw a 32-byte string and process it as specified in * Elliptic Curves for Security [RFC7748] §5. * * - Curve448 (PSA_ECC_FAMILY_MONTGOMERY, 448 bits): * draw a 56-byte string and process it as specified in [RFC7748] §5. * * Note: Function allocates memory for *data buffer, so given *data should be * always NULL. */ static psa_status_t psa_generate_derived_ecc_key_montgomery_helper( size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data ) { size_t output_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; switch (bits) { case 255: output_length = 32; break; case 448: output_length = 56; break; default: return PSA_ERROR_INVALID_ARGUMENT; break; } *data = mbedtls_calloc(1, output_length); if (*data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } status = psa_key_derivation_output_bytes(operation, *data, output_length); if (status != PSA_SUCCESS) { return status; } switch (bits) { case 255: (*data)[0] &= 248; (*data)[31] &= 127; (*data)[31] |= 64; break; case 448: (*data)[0] &= 252; (*data)[55] |= 128; break; default: return PSA_ERROR_CORRUPTION_DETECTED; break; } return status; } #else /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper( psa_key_slot_t *slot, size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data) { (void) slot; (void) bits; (void) operation; (void) data; return PSA_ERROR_NOT_SUPPORTED; } static psa_status_t psa_generate_derived_ecc_key_montgomery_helper( size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data) { (void) bits; (void) operation; (void) data; return PSA_ERROR_NOT_SUPPORTED; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ static psa_status_t psa_generate_derived_key_internal( psa_key_slot_t *slot, size_t bits, psa_key_derivation_operation_t *operation) { uint8_t *data = NULL; size_t bytes = PSA_BITS_TO_BYTES(bits); size_t storage_size = bytes; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) { return PSA_ERROR_INVALID_ARGUMENT; } #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) if (PSA_KEY_TYPE_IS_ECC(slot->attr.type)) { psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(slot->attr.type); if (PSA_ECC_FAMILY_IS_WEIERSTRASS(curve)) { /* Weierstrass elliptic curve */ status = psa_generate_derived_ecc_key_weierstrass_helper(slot, bits, operation, &data); if (status != PSA_SUCCESS) { goto exit; } } else { /* Montgomery elliptic curve */ status = psa_generate_derived_ecc_key_montgomery_helper(bits, operation, &data); if (status != PSA_SUCCESS) { goto exit; } } } else #endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) */ if (key_type_is_raw_bytes(slot->attr.type)) { if (bits % 8 != 0) { return PSA_ERROR_INVALID_ARGUMENT; } data = mbedtls_calloc(1, bytes); if (data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } status = psa_key_derivation_output_bytes(operation, data, bytes); if (status != PSA_SUCCESS) { goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) if (slot->attr.type == PSA_KEY_TYPE_DES) { psa_des_set_key_parity(data, bytes); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) */ } else { return PSA_ERROR_NOT_SUPPORTED; } slot->attr.bits = (psa_key_bits_t) bits; if (psa_key_lifetime_is_external(slot->attr.lifetime)) { status = psa_driver_wrapper_get_key_buffer_size(&slot->attr, &storage_size); if (status != PSA_SUCCESS) { goto exit; } } status = psa_allocate_buffer_to_slot(slot, storage_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_import_key(&slot->attr, data, bytes, slot->key.data, slot->key.bytes, &slot->key.bytes, &bits); if (bits != slot->attr.bits) { status = PSA_ERROR_INVALID_ARGUMENT; } exit: mbedtls_free(data); return status; } static const psa_custom_key_parameters_t default_custom_production = PSA_CUSTOM_KEY_PARAMETERS_INIT; int psa_custom_key_parameters_are_default( const psa_custom_key_parameters_t *custom, size_t custom_data_length) { if (custom->flags != 0) { return 0; } if (custom_data_length != 0) { return 0; } return 1; } psa_status_t psa_key_derivation_output_key_custom( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, const psa_custom_key_parameters_t *custom, const uint8_t *custom_data, size_t custom_data_length, mbedtls_svc_key_id_t *key) { psa_status_t status; psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; *key = MBEDTLS_SVC_KEY_ID_INIT; /* Reject any attempt to create a zero-length key so that we don't * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ if (psa_get_key_bits(attributes) == 0) { return PSA_ERROR_INVALID_ARGUMENT; } (void) custom_data; /* We only accept 0-length data */ if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) { return PSA_ERROR_INVALID_ARGUMENT; } if (operation->alg == PSA_ALG_NONE) { return PSA_ERROR_BAD_STATE; } if (!operation->can_output_key) { return PSA_ERROR_NOT_PERMITTED; } status = psa_start_key_creation(PSA_KEY_CREATION_DERIVE, attributes, &slot, &driver); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if (driver != NULL) { /* Deriving a key in a secure element is not implemented yet. */ status = PSA_ERROR_NOT_SUPPORTED; } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ if (status == PSA_SUCCESS) { status = psa_generate_derived_key_internal(slot, attributes->bits, operation); } if (status == PSA_SUCCESS) { status = psa_finish_key_creation(slot, driver, key); } if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } return status; } psa_status_t psa_key_derivation_output_key_ext( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, const psa_key_production_parameters_t *params, size_t params_data_length, mbedtls_svc_key_id_t *key) { return psa_key_derivation_output_key_custom( attributes, operation, (const psa_custom_key_parameters_t *) params, params->data, params_data_length, key); } psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, mbedtls_svc_key_id_t *key) { return psa_key_derivation_output_key_custom(attributes, operation, &default_custom_production, NULL, 0, key); } /****************************************************************/ /* Key derivation */ /****************************************************************/ #if defined(AT_LEAST_ONE_BUILTIN_KDF) static int is_kdf_alg_supported(psa_algorithm_t kdf_alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) if (PSA_ALG_IS_HKDF(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { return 1; } #endif return 0; } static psa_status_t psa_hash_try_support(psa_algorithm_t alg) { psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; psa_status_t status = psa_hash_setup(&operation, alg); psa_hash_abort(&operation); return status; } static psa_status_t psa_key_derivation_set_maximum_capacity( psa_key_derivation_operation_t *operation, psa_algorithm_t kdf_alg) { #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { operation->capacity = PSA_HASH_LENGTH(PSA_ALG_SHA_256); return PSA_SUCCESS; } #endif #if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { #if (SIZE_MAX > UINT32_MAX) operation->capacity = UINT32_MAX * (size_t) PSA_MAC_LENGTH( PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); #else operation->capacity = SIZE_MAX; #endif return PSA_SUCCESS; } #endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */ /* After this point, if kdf_alg is not valid then value of hash_alg may be * invalid or meaningless but it does not affect this function */ psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(kdf_alg); size_t hash_size = PSA_HASH_LENGTH(hash_alg); if (hash_size == 0) { return PSA_ERROR_NOT_SUPPORTED; } /* Make sure that hash_alg is a supported hash algorithm. Otherwise * we might fail later, which is somewhat unfriendly and potentially * risk-prone. */ psa_status_t status = psa_hash_try_support(hash_alg); if (status != PSA_SUCCESS) { return status; } #if defined(PSA_WANT_ALG_HKDF) if (PSA_ALG_IS_HKDF(kdf_alg)) { operation->capacity = 255 * hash_size; } else #endif #if defined(PSA_WANT_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { operation->capacity = hash_size; } else #endif #if defined(PSA_WANT_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { operation->capacity = 255 * hash_size; } else #endif #if defined(PSA_WANT_ALG_TLS12_PRF) if (PSA_ALG_IS_TLS12_PRF(kdf_alg) && (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) { operation->capacity = SIZE_MAX; } else #endif #if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg) && (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) { /* Master Secret is always 48 bytes * https://datatracker.ietf.org/doc/html/rfc5246.html#section-8.1 */ operation->capacity = 48U; } else #endif #if defined(PSA_WANT_ALG_PBKDF2_HMAC) if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { #if (SIZE_MAX > UINT32_MAX) operation->capacity = UINT32_MAX * hash_size; #else operation->capacity = SIZE_MAX; #endif } else #endif /* PSA_WANT_ALG_PBKDF2_HMAC */ { (void) hash_size; status = PSA_ERROR_NOT_SUPPORTED; } return status; } static psa_status_t psa_key_derivation_setup_kdf( psa_key_derivation_operation_t *operation, psa_algorithm_t kdf_alg) { /* Make sure that operation->ctx is properly zero-initialised. (Macro * initialisers for this union leave some bytes unspecified.) */ memset(&operation->ctx, 0, sizeof(operation->ctx)); /* Make sure that kdf_alg is a supported key derivation algorithm. */ if (!is_kdf_alg_supported(kdf_alg)) { return PSA_ERROR_NOT_SUPPORTED; } psa_status_t status = psa_key_derivation_set_maximum_capacity(operation, kdf_alg); return status; } static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg) { #if defined(PSA_WANT_ALG_ECDH) if (alg == PSA_ALG_ECDH) { return PSA_SUCCESS; } #endif #if defined(PSA_WANT_ALG_FFDH) if (alg == PSA_ALG_FFDH) { return PSA_SUCCESS; } #endif (void) alg; return PSA_ERROR_NOT_SUPPORTED; } static int psa_key_derivation_allows_free_form_secret_input( psa_algorithm_t kdf_alg) { #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { return 0; } #endif (void) kdf_alg; return 1; } #endif /* AT_LEAST_ONE_BUILTIN_KDF */ psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, psa_algorithm_t alg) { psa_status_t status; if (operation->alg != 0) { return PSA_ERROR_BAD_STATE; } if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) { #if defined(AT_LEAST_ONE_BUILTIN_KDF) psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg); psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(alg); status = psa_key_agreement_try_support(ka_alg); if (status != PSA_SUCCESS) { return status; } if (!psa_key_derivation_allows_free_form_secret_input(kdf_alg)) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_key_derivation_setup_kdf(operation, kdf_alg); #else return PSA_ERROR_NOT_SUPPORTED; #endif /* AT_LEAST_ONE_BUILTIN_KDF */ } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) { #if defined(AT_LEAST_ONE_BUILTIN_KDF) status = psa_key_derivation_setup_kdf(operation, alg); #else return PSA_ERROR_NOT_SUPPORTED; #endif /* AT_LEAST_ONE_BUILTIN_KDF */ } else { return PSA_ERROR_INVALID_ARGUMENT; } if (status == PSA_SUCCESS) { operation->alg = alg; } return status; } #if defined(BUILTIN_ALG_ANY_HKDF) static psa_status_t psa_hkdf_input(psa_hkdf_key_derivation_t *hkdf, psa_algorithm_t kdf_alg, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); psa_status_t status; switch (step) { case PSA_KEY_DERIVATION_INPUT_SALT: #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { return PSA_ERROR_INVALID_ARGUMENT; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ if (hkdf->state != HKDF_STATE_INIT) { return PSA_ERROR_BAD_STATE; } else { status = psa_key_derivation_start_hmac(&hkdf->hmac, hash_alg, data, data_length); if (status != PSA_SUCCESS) { return status; } hkdf->state = HKDF_STATE_STARTED; return PSA_SUCCESS; } case PSA_KEY_DERIVATION_INPUT_SECRET: #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { /* We shouldn't be in different state as HKDF_EXPAND only allows * two inputs: SECRET (this case) and INFO which does not modify * the state. It could happen only if the hkdf * object was corrupted. */ if (hkdf->state != HKDF_STATE_INIT) { return PSA_ERROR_BAD_STATE; } /* Allow only input that fits expected prk size */ if (data_length != PSA_HASH_LENGTH(hash_alg)) { return PSA_ERROR_INVALID_ARGUMENT; } memcpy(hkdf->prk, data, data_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ { /* HKDF: If no salt was provided, use an empty salt. * HKDF-EXTRACT: salt is mandatory. */ if (hkdf->state == HKDF_STATE_INIT) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { return PSA_ERROR_BAD_STATE; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ status = psa_key_derivation_start_hmac(&hkdf->hmac, hash_alg, NULL, 0); if (status != PSA_SUCCESS) { return status; } hkdf->state = HKDF_STATE_STARTED; } if (hkdf->state != HKDF_STATE_STARTED) { return PSA_ERROR_BAD_STATE; } status = psa_mac_update(&hkdf->hmac, data, data_length); if (status != PSA_SUCCESS) { return status; } status = psa_mac_sign_finish(&hkdf->hmac, hkdf->prk, sizeof(hkdf->prk), &data_length); if (status != PSA_SUCCESS) { return status; } } hkdf->state = HKDF_STATE_KEYED; hkdf->block_number = 0; #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { /* The only block of output is the PRK. */ memcpy(hkdf->output_block, hkdf->prk, PSA_HASH_LENGTH(hash_alg)); hkdf->offset_in_block = 0; } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ { /* Block 0 is empty, and the next block will be * generated by psa_key_derivation_hkdf_read(). */ hkdf->offset_in_block = PSA_HASH_LENGTH(hash_alg); } return PSA_SUCCESS; case PSA_KEY_DERIVATION_INPUT_INFO: #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { return PSA_ERROR_INVALID_ARGUMENT; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg) && hkdf->state == HKDF_STATE_INIT) { return PSA_ERROR_BAD_STATE; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ if (hkdf->state == HKDF_STATE_OUTPUT) { return PSA_ERROR_BAD_STATE; } if (hkdf->info_set) { return PSA_ERROR_BAD_STATE; } hkdf->info_length = data_length; if (data_length != 0) { hkdf->info = mbedtls_calloc(1, data_length); if (hkdf->info == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(hkdf->info, data, data_length); } hkdf->info_set = 1; return PSA_SUCCESS; default: return PSA_ERROR_INVALID_ARGUMENT; } } #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) static psa_status_t psa_tls12_prf_set_seed(psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { if (prf->state != PSA_TLS12_PRF_STATE_INIT) { return PSA_ERROR_BAD_STATE; } if (data_length != 0) { prf->seed = mbedtls_calloc(1, data_length); if (prf->seed == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(prf->seed, data, data_length); prf->seed_length = data_length; } prf->state = PSA_TLS12_PRF_STATE_SEED_SET; return PSA_SUCCESS; } static psa_status_t psa_tls12_prf_set_key(psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET && prf->state != PSA_TLS12_PRF_STATE_OTHER_KEY_SET) { return PSA_ERROR_BAD_STATE; } if (data_length != 0) { prf->secret = mbedtls_calloc(1, data_length); if (prf->secret == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(prf->secret, data, data_length); prf->secret_length = data_length; } prf->state = PSA_TLS12_PRF_STATE_KEY_SET; return PSA_SUCCESS; } static psa_status_t psa_tls12_prf_set_label(psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { if (prf->state != PSA_TLS12_PRF_STATE_KEY_SET) { return PSA_ERROR_BAD_STATE; } if (data_length != 0) { prf->label = mbedtls_calloc(1, data_length); if (prf->label == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(prf->label, data, data_length); prf->label_length = data_length; } prf->state = PSA_TLS12_PRF_STATE_LABEL_SET; return PSA_SUCCESS; } static psa_status_t psa_tls12_prf_input(psa_tls12_prf_key_derivation_t *prf, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { switch (step) { case PSA_KEY_DERIVATION_INPUT_SEED: return psa_tls12_prf_set_seed(prf, data, data_length); case PSA_KEY_DERIVATION_INPUT_SECRET: return psa_tls12_prf_set_key(prf, data, data_length); case PSA_KEY_DERIVATION_INPUT_LABEL: return psa_tls12_prf_set_label(prf, data, data_length); default: return PSA_ERROR_INVALID_ARGUMENT; } } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) static psa_status_t psa_tls12_prf_psk_to_ms_set_key( psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { psa_status_t status; const size_t pms_len = (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET ? 4 + data_length + prf->other_secret_length : 4 + 2 * data_length); if (data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE) { return PSA_ERROR_INVALID_ARGUMENT; } uint8_t *pms = mbedtls_calloc(1, pms_len); if (pms == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } uint8_t *cur = pms; /* pure-PSK: * Quoting RFC 4279, Section 2: * * The premaster secret is formed as follows: if the PSK is N octets * long, concatenate a uint16 with the value N, N zero octets, a second * uint16 with the value N, and the PSK itself. * * mixed-PSK: * In a DHE-PSK, RSA-PSK, ECDHE-PSK the premaster secret is formed as * follows: concatenate a uint16 with the length of the other secret, * the other secret itself, uint16 with the length of PSK, and the * PSK itself. * For details please check: * - RFC 4279, Section 4 for the definition of RSA-PSK, * - RFC 4279, Section 3 for the definition of DHE-PSK, * - RFC 5489 for the definition of ECDHE-PSK. */ if (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET) { *cur++ = MBEDTLS_BYTE_1(prf->other_secret_length); *cur++ = MBEDTLS_BYTE_0(prf->other_secret_length); if (prf->other_secret_length != 0) { memcpy(cur, prf->other_secret, prf->other_secret_length); mbedtls_platform_zeroize(prf->other_secret, prf->other_secret_length); cur += prf->other_secret_length; } } else { *cur++ = MBEDTLS_BYTE_1(data_length); *cur++ = MBEDTLS_BYTE_0(data_length); memset(cur, 0, data_length); cur += data_length; } *cur++ = MBEDTLS_BYTE_1(data_length); *cur++ = MBEDTLS_BYTE_0(data_length); memcpy(cur, data, data_length); cur += data_length; status = psa_tls12_prf_set_key(prf, pms, (size_t) (cur - pms)); mbedtls_zeroize_and_free(pms, pms_len); return status; } static psa_status_t psa_tls12_prf_psk_to_ms_set_other_key( psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET) { return PSA_ERROR_BAD_STATE; } if (data_length != 0) { prf->other_secret = mbedtls_calloc(1, data_length); if (prf->other_secret == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(prf->other_secret, data, data_length); prf->other_secret_length = data_length; } else { prf->other_secret_length = 0; } prf->state = PSA_TLS12_PRF_STATE_OTHER_KEY_SET; return PSA_SUCCESS; } static psa_status_t psa_tls12_prf_psk_to_ms_input( psa_tls12_prf_key_derivation_t *prf, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { switch (step) { case PSA_KEY_DERIVATION_INPUT_SECRET: return psa_tls12_prf_psk_to_ms_set_key(prf, data, data_length); break; case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET: return psa_tls12_prf_psk_to_ms_set_other_key(prf, data, data_length); break; default: return psa_tls12_prf_input(prf, step, data, data_length); break; } } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) static psa_status_t psa_tls12_ecjpake_to_pms_input( psa_tls12_ecjpake_to_pms_t *ecjpake, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { if (data_length != PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE || step != PSA_KEY_DERIVATION_INPUT_SECRET) { return PSA_ERROR_INVALID_ARGUMENT; } /* Check if the passed point is in an uncompressed form */ if (data[0] != 0x04) { return PSA_ERROR_INVALID_ARGUMENT; } /* Only K.X has to be extracted - bytes 1 to 32 inclusive. */ memcpy(ecjpake->data, data + 1, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE); return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(PSA_HAVE_SOFT_PBKDF2) static psa_status_t psa_pbkdf2_set_input_cost( psa_pbkdf2_key_derivation_t *pbkdf2, psa_key_derivation_step_t step, uint64_t data) { if (step != PSA_KEY_DERIVATION_INPUT_COST) { return PSA_ERROR_INVALID_ARGUMENT; } if (pbkdf2->state != PSA_PBKDF2_STATE_INIT) { return PSA_ERROR_BAD_STATE; } if (data > PSA_VENDOR_PBKDF2_MAX_ITERATIONS) { return PSA_ERROR_NOT_SUPPORTED; } if (data == 0) { return PSA_ERROR_INVALID_ARGUMENT; } pbkdf2->input_cost = data; pbkdf2->state = PSA_PBKDF2_STATE_INPUT_COST_SET; return PSA_SUCCESS; } static psa_status_t psa_pbkdf2_set_salt(psa_pbkdf2_key_derivation_t *pbkdf2, const uint8_t *data, size_t data_length) { if (pbkdf2->state == PSA_PBKDF2_STATE_INPUT_COST_SET) { pbkdf2->state = PSA_PBKDF2_STATE_SALT_SET; } else if (pbkdf2->state == PSA_PBKDF2_STATE_SALT_SET) { /* Appending to existing salt. No state change. */ } else { return PSA_ERROR_BAD_STATE; } if (data_length == 0) { /* Appending an empty string, nothing to do. */ } else { uint8_t *next_salt; next_salt = mbedtls_calloc(1, data_length + pbkdf2->salt_length); if (next_salt == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } if (pbkdf2->salt_length != 0) { memcpy(next_salt, pbkdf2->salt, pbkdf2->salt_length); } memcpy(next_salt + pbkdf2->salt_length, data, data_length); pbkdf2->salt_length += data_length; mbedtls_free(pbkdf2->salt); pbkdf2->salt = next_salt; } return PSA_SUCCESS; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) static psa_status_t psa_pbkdf2_hmac_set_password(psa_algorithm_t hash_alg, const uint8_t *input, size_t input_len, uint8_t *output, size_t *output_len) { psa_status_t status = PSA_SUCCESS; if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) { return psa_hash_compute(hash_alg, input, input_len, output, PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len); } else if (input_len > 0) { memcpy(output, input, input_len); } *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg); return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) static psa_status_t psa_pbkdf2_cmac_set_password(const uint8_t *input, size_t input_len, uint8_t *output, size_t *output_len) { psa_status_t status = PSA_SUCCESS; if (input_len != PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC)) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; uint8_t zeros[16] = { 0 }; psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(sizeof(zeros))); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); /* Passing PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC) as * mac_size as the driver function sets mac_output_length = mac_size * on success. See https://github.com/Mbed-TLS/mbedtls/issues/7801 */ status = psa_driver_wrapper_mac_compute(&attributes, zeros, sizeof(zeros), PSA_ALG_CMAC, input, input_len, output, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC), output_len); } else { memcpy(output, input, input_len); *output_len = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */ static psa_status_t psa_pbkdf2_set_password(psa_pbkdf2_key_derivation_t *pbkdf2, psa_algorithm_t kdf_alg, const uint8_t *data, size_t data_length) { psa_status_t status = PSA_SUCCESS; if (pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) { return PSA_ERROR_BAD_STATE; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { psa_algorithm_t hash_alg = PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg); status = psa_pbkdf2_hmac_set_password(hash_alg, data, data_length, pbkdf2->password, &pbkdf2->password_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { status = psa_pbkdf2_cmac_set_password(data, data_length, pbkdf2->password, &pbkdf2->password_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */ { return PSA_ERROR_INVALID_ARGUMENT; } pbkdf2->state = PSA_PBKDF2_STATE_PASSWORD_SET; return status; } static psa_status_t psa_pbkdf2_input(psa_pbkdf2_key_derivation_t *pbkdf2, psa_algorithm_t kdf_alg, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { switch (step) { case PSA_KEY_DERIVATION_INPUT_SALT: return psa_pbkdf2_set_salt(pbkdf2, data, data_length); case PSA_KEY_DERIVATION_INPUT_PASSWORD: return psa_pbkdf2_set_password(pbkdf2, kdf_alg, data, data_length); default: return PSA_ERROR_INVALID_ARGUMENT; } } #endif /* PSA_HAVE_SOFT_PBKDF2 */ /** Check whether the given key type is acceptable for the given * input step of a key derivation. * * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE. * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA. * Both secret and non-secret inputs can alternatively have the type * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning * that the input was passed as a buffer rather than via a key object. */ static int psa_key_derivation_check_input_type( psa_key_derivation_step_t step, psa_key_type_t key_type) { switch (step) { case PSA_KEY_DERIVATION_INPUT_SECRET: if (key_type == PSA_KEY_TYPE_DERIVE) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_NONE) { return PSA_SUCCESS; } break; case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET: if (key_type == PSA_KEY_TYPE_DERIVE) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_NONE) { return PSA_SUCCESS; } break; case PSA_KEY_DERIVATION_INPUT_LABEL: case PSA_KEY_DERIVATION_INPUT_SALT: case PSA_KEY_DERIVATION_INPUT_INFO: case PSA_KEY_DERIVATION_INPUT_SEED: if (key_type == PSA_KEY_TYPE_RAW_DATA) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_NONE) { return PSA_SUCCESS; } break; case PSA_KEY_DERIVATION_INPUT_PASSWORD: if (key_type == PSA_KEY_TYPE_PASSWORD) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_DERIVE) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_NONE) { return PSA_SUCCESS; } break; } return PSA_ERROR_INVALID_ARGUMENT; } static psa_status_t psa_key_derivation_input_internal( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, psa_key_type_t key_type, const uint8_t *data, size_t data_length) { psa_status_t status; psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); status = psa_key_derivation_check_input_type(step, key_type); if (status != PSA_SUCCESS) { goto exit; } #if defined(BUILTIN_ALG_ANY_HKDF) if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { status = psa_hkdf_input(&operation->ctx.hkdf, kdf_alg, step, data, data_length); } else #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { status = psa_tls12_prf_input(&operation->ctx.tls12_prf, step, data, data_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { status = psa_tls12_prf_psk_to_ms_input(&operation->ctx.tls12_prf, step, data, data_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { status = psa_tls12_ecjpake_to_pms_input( &operation->ctx.tls12_ecjpake_to_pms, step, data, data_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(PSA_HAVE_SOFT_PBKDF2) if (PSA_ALG_IS_PBKDF2(kdf_alg)) { status = psa_pbkdf2_input(&operation->ctx.pbkdf2, kdf_alg, step, data, data_length); } else #endif /* PSA_HAVE_SOFT_PBKDF2 */ { /* This can't happen unless the operation object was not initialized */ (void) data; (void) data_length; (void) kdf_alg; return PSA_ERROR_BAD_STATE; } exit: if (status != PSA_SUCCESS) { psa_key_derivation_abort(operation); } return status; } static psa_status_t psa_key_derivation_input_integer_internal( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, uint64_t value) { psa_status_t status; psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); #if defined(PSA_HAVE_SOFT_PBKDF2) if (PSA_ALG_IS_PBKDF2(kdf_alg)) { status = psa_pbkdf2_set_input_cost( &operation->ctx.pbkdf2, step, value); } else #endif /* PSA_HAVE_SOFT_PBKDF2 */ { (void) step; (void) value; (void) kdf_alg; status = PSA_ERROR_INVALID_ARGUMENT; } if (status != PSA_SUCCESS) { psa_key_derivation_abort(operation); } return status; } psa_status_t psa_key_derivation_input_bytes( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, const uint8_t *data_external, size_t data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(data_external, data); LOCAL_INPUT_ALLOC(data_external, data_length, data); status = psa_key_derivation_input_internal(operation, step, PSA_KEY_TYPE_NONE, data, data_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(data_external, data); return status; } psa_status_t psa_key_derivation_input_integer( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, uint64_t value) { return psa_key_derivation_input_integer_internal(operation, step, value); } psa_status_t psa_key_derivation_input_key( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, mbedtls_svc_key_id_t key) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; status = psa_get_and_lock_transparent_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); if (status != PSA_SUCCESS) { psa_key_derivation_abort(operation); return status; } /* Passing a key object as a SECRET or PASSWORD input unlocks the * permission to output to a key object. */ if (step == PSA_KEY_DERIVATION_INPUT_SECRET || step == PSA_KEY_DERIVATION_INPUT_PASSWORD) { operation->can_output_key = 1; } status = psa_key_derivation_input_internal(operation, step, slot->attr.type, slot->key.data, slot->key.bytes); unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } /****************************************************************/ /* Key agreement */ /****************************************************************/ psa_status_t psa_key_agreement_raw_builtin(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length) { switch (alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) case PSA_ALG_ECDH: return mbedtls_psa_key_agreement_ecdh(attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length); #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) case PSA_ALG_FFDH: return mbedtls_psa_ffdh_key_agreement(attributes, peer_key, peer_key_length, key_buffer, key_buffer_size, shared_secret, shared_secret_size, shared_secret_length); #endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */ default: (void) attributes; (void) key_buffer; (void) key_buffer_size; (void) peer_key; (void) peer_key_length; (void) shared_secret; (void) shared_secret_size; (void) shared_secret_length; return PSA_ERROR_NOT_SUPPORTED; } } /** Internal function for raw key agreement * Calls the driver wrapper which will hand off key agreement task * to the driver's implementation if a driver is present. * Fallback specified in the driver wrapper is built-in raw key agreement * (psa_key_agreement_raw_builtin). */ static psa_status_t psa_key_agreement_raw_internal(psa_algorithm_t alg, psa_key_slot_t *private_key, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length) { if (!PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { return PSA_ERROR_NOT_SUPPORTED; } return psa_driver_wrapper_key_agreement(&private_key->attr, private_key->key.data, private_key->key.bytes, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length); } /* Note that if this function fails, you must call psa_key_derivation_abort() * to potentially free embedded data structures and wipe confidential data. */ static psa_status_t psa_key_agreement_internal(psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, psa_key_slot_t *private_key, const uint8_t *peer_key, size_t peer_key_length) { psa_status_t status; uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 }; size_t shared_secret_length = 0; psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg); /* Step 1: run the secret agreement algorithm to generate the shared * secret. */ status = psa_key_agreement_raw_internal(ka_alg, private_key, peer_key, peer_key_length, shared_secret, sizeof(shared_secret), &shared_secret_length); if (status != PSA_SUCCESS) { goto exit; } /* Step 2: set up the key derivation to generate key material from * the shared secret. A shared secret is permitted wherever a key * of type DERIVE is permitted. */ status = psa_key_derivation_input_internal(operation, step, PSA_KEY_TYPE_DERIVE, shared_secret, shared_secret_length); exit: mbedtls_platform_zeroize(shared_secret, shared_secret_length); return status; } psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, mbedtls_svc_key_id_t private_key, const uint8_t *peer_key_external, size_t peer_key_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(peer_key_external, peer_key); if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_get_and_lock_transparent_key_slot_with_policy( private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); if (status != PSA_SUCCESS) { return status; } LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); status = psa_key_agreement_internal(operation, step, slot, peer_key, peer_key_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif if (status != PSA_SUCCESS) { psa_key_derivation_abort(operation); } else { /* If a private key has been added as SECRET, we allow the derived * key material to be used as a key in PSA Crypto. */ if (step == PSA_KEY_DERIVATION_INPUT_SECRET) { operation->can_output_key = 1; } } unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_INPUT_FREE(peer_key_external, peer_key); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, mbedtls_svc_key_id_t private_key, const uint8_t *peer_key_external, size_t peer_key_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; size_t expected_length; LOCAL_INPUT_DECLARE(peer_key_external, peer_key); LOCAL_OUTPUT_DECLARE(output_external, output); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_get_and_lock_transparent_key_slot_with_policy( private_key, &slot, PSA_KEY_USAGE_DERIVE, alg); if (status != PSA_SUCCESS) { goto exit; } /* PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is in general an upper bound * for the output size. The PSA specification only guarantees that this * function works if output_size >= PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(...), * but it might be nice to allow smaller buffers if the output fits. * At the time of writing this comment, with only ECDH implemented, * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is exact so the point is moot. * If FFDH is implemented, PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() can easily * be exact for it as well. */ expected_length = PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(slot->attr.type, slot->attr.bits); if (output_size < expected_length) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); status = psa_key_agreement_raw_internal(alg, slot, peer_key, peer_key_length, output, output_size, output_length); exit: /* Check for successful allocation of output, * with an unsuccessful status. */ if (output != NULL && status != PSA_SUCCESS) { /* If an error happens and is not handled properly, the output * may be used as a key to protect sensitive data. Arrange for such * a key to be random, which is likely to result in decryption or * verification errors. This is better than filling the buffer with * some constant data such as zeros, which would result in the data * being protected with a reproducible, easily knowable key. */ psa_generate_random_internal(output, output_size); *output_length = output_size; } if (output == NULL) { /* output allocation failed. */ *output_length = 0; } unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_INPUT_FREE(peer_key_external, peer_key); LOCAL_OUTPUT_FREE(output_external, output); return (status == PSA_SUCCESS) ? unlock_status : status; } /****************************************************************/ /* Random generation */ /****************************************************************/ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) #include "entropy_poll.h" #endif /** Initialize the PSA random generator. * * Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling * this function if mutexes are enabled. */ static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng) { #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) memset(rng, 0, sizeof(*rng)); #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ /* Set default configuration if * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ if (rng->entropy_init == NULL) { rng->entropy_init = mbedtls_entropy_init; } if (rng->entropy_free == NULL) { rng->entropy_free = mbedtls_entropy_free; } rng->entropy_init(&rng->entropy); #if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) /* The PSA entropy injection feature depends on using NV seed as an entropy * source. Add NV seed as an entropy source for PSA entropy injection. */ mbedtls_entropy_add_source(&rng->entropy, mbedtls_nv_seed_poll, NULL, MBEDTLS_ENTROPY_BLOCK_SIZE, MBEDTLS_ENTROPY_SOURCE_STRONG); #endif mbedtls_psa_drbg_init(&rng->drbg); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } /** Deinitialize the PSA random generator. * * Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling * this function if mutexes are enabled. */ static void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng) { #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) memset(rng, 0, sizeof(*rng)); #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ mbedtls_psa_drbg_free(&rng->drbg); rng->entropy_free(&rng->entropy); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } /** Seed the PSA random generator. */ static psa_status_t mbedtls_psa_random_seed(mbedtls_psa_random_context_t *rng) { #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) /* Do nothing: the external RNG seeds itself. */ (void) rng; return PSA_SUCCESS; #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ const unsigned char drbg_seed[] = "PSA"; int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy, drbg_seed, sizeof(drbg_seed) - 1); return mbedtls_to_psa_error(ret); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } psa_status_t psa_generate_random(uint8_t *output_external, size_t output_size) { psa_status_t status; LOCAL_OUTPUT_DECLARE(output_external, output); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_generate_random_internal(output, output_size); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_OUTPUT_FREE(output_external, output); return status; } #if defined(MBEDTLS_PSA_INJECT_ENTROPY) psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size) { if (psa_get_initialized()) { return PSA_ERROR_NOT_PERMITTED; } if (((seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) || (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) || (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) { return PSA_ERROR_INVALID_ARGUMENT; } return mbedtls_psa_storage_inject_entropy(seed, seed_size); } #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ /** Validate the key type and size for key generation * * \param type The key type * \param bits The number of bits of the key * * \retval #PSA_SUCCESS * The key type and size are valid. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size in bits of the key is not valid. * \retval #PSA_ERROR_NOT_SUPPORTED * The type and/or the size in bits of the key or the combination of * the two is not supported. */ static psa_status_t psa_validate_key_type_and_size_for_key_generation( psa_key_type_t type, size_t bits) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (key_type_is_raw_bytes(type)) { status = psa_validate_unstructured_key_bit_size(type, bits); if (status != PSA_SUCCESS) { return status; } } else #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_RSA(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) { return PSA_ERROR_NOT_SUPPORTED; } if (bits < PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS) { return PSA_ERROR_NOT_SUPPORTED; } /* Accept only byte-aligned keys, for the same reasons as * in psa_import_rsa_key(). */ if (bits % 8 != 0) { return PSA_ERROR_NOT_SUPPORTED; } } else #endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { /* To avoid empty block, return successfully here. */ return PSA_SUCCESS; } else #endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { if (psa_is_dh_key_size_valid(bits) == 0) { return PSA_ERROR_NOT_SUPPORTED; } } else #endif /* defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) */ { return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } psa_status_t psa_generate_key_internal( const psa_key_attributes_t *attributes, const psa_custom_key_parameters_t *custom, const uint8_t *custom_data, size_t custom_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t type = attributes->type; /* Only used for RSA */ (void) custom; (void) custom_data; (void) custom_data_length; if (key_type_is_raw_bytes(type)) { status = psa_generate_random_internal(key_buffer, key_buffer_size); if (status != PSA_SUCCESS) { return status; } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) if (type == PSA_KEY_TYPE_DES) { psa_des_set_key_parity(key_buffer, key_buffer_size); } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ } else #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { return mbedtls_psa_rsa_generate_key(attributes, custom_data, custom_data_length, key_buffer, key_buffer_size, key_buffer_length); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { return mbedtls_psa_ecp_generate_key(attributes, key_buffer, key_buffer_size, key_buffer_length); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { return mbedtls_psa_ffdh_generate_key(attributes, key_buffer, key_buffer_size, key_buffer_length); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) */ { (void) key_buffer_length; return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } psa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes, const psa_custom_key_parameters_t *custom, const uint8_t *custom_data, size_t custom_data_length, mbedtls_svc_key_id_t *key) { psa_status_t status; psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; size_t key_buffer_size; *key = MBEDTLS_SVC_KEY_ID_INIT; /* Reject any attempt to create a zero-length key so that we don't * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ if (psa_get_key_bits(attributes) == 0) { return PSA_ERROR_INVALID_ARGUMENT; } /* Reject any attempt to create a public key. */ if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->type)) { return PSA_ERROR_INVALID_ARGUMENT; } #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { if (custom->flags != 0) { return PSA_ERROR_INVALID_ARGUMENT; } } else #endif if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes, &slot, &driver); if (status != PSA_SUCCESS) { goto exit; } /* In the case of a transparent key or an opaque key stored in local * storage ( thus not in the case of generating a key in a secure element * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a * buffer to hold the generated key material. */ if (slot->key.data == NULL) { if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime) == PSA_KEY_LOCATION_LOCAL_STORAGE) { status = psa_validate_key_type_and_size_for_key_generation( attributes->type, attributes->bits); if (status != PSA_SUCCESS) { goto exit; } key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( attributes->type, attributes->bits); } else { status = psa_driver_wrapper_get_key_buffer_size( attributes, &key_buffer_size); if (status != PSA_SUCCESS) { goto exit; } } status = psa_allocate_buffer_to_slot(slot, key_buffer_size); if (status != PSA_SUCCESS) { goto exit; } } status = psa_driver_wrapper_generate_key(attributes, custom, custom_data, custom_data_length, slot->key.data, slot->key.bytes, &slot->key.bytes); if (status != PSA_SUCCESS) { psa_remove_key_data_from_memory(slot); } exit: if (status == PSA_SUCCESS) { status = psa_finish_key_creation(slot, driver, key); } if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } return status; } psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes, const psa_key_production_parameters_t *params, size_t params_data_length, mbedtls_svc_key_id_t *key) { return psa_generate_key_custom( attributes, (const psa_custom_key_parameters_t *) params, params->data, params_data_length, key); } psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key) { return psa_generate_key_custom(attributes, &default_custom_production, NULL, 0, key); } /****************************************************************/ /* Module setup */ /****************************************************************/ #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) psa_status_t mbedtls_psa_crypto_configure_entropy_sources( void (* entropy_init)(mbedtls_entropy_context *ctx), void (* entropy_free)(mbedtls_entropy_context *ctx)) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ if (global_data.rng_state != RNG_NOT_INITIALIZED) { status = PSA_ERROR_BAD_STATE; } else { global_data.rng.entropy_init = entropy_init; global_data.rng.entropy_free = entropy_free; status = PSA_SUCCESS; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ return status; } #endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ void mbedtls_psa_crypto_free(void) { #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ /* Nothing to do to free transaction. */ if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) { global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; } if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) { psa_wipe_all_key_slots(); global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ if (global_data.rng_state != RNG_NOT_INITIALIZED) { mbedtls_psa_random_free(&global_data.rng); } global_data.rng_state = RNG_NOT_INITIALIZED; mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ /* Terminate drivers */ if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) { psa_driver_wrapper_free(); global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ } #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) /** Recover a transaction that was interrupted by a power failure. * * This function is called during initialization, before psa_crypto_init() * returns. If this function returns a failure status, the initialization * fails. */ static psa_status_t psa_crypto_recover_transaction( const psa_crypto_transaction_t *transaction) { switch (transaction->unknown.type) { case PSA_CRYPTO_TRANSACTION_CREATE_KEY: case PSA_CRYPTO_TRANSACTION_DESTROY_KEY: /* TODO - fall through to the failure case until this * is implemented. * https://github.com/ARMmbed/mbed-crypto/issues/218 */ default: /* We found an unsupported transaction in the storage. * We don't know what state the storage is in. Give up. */ return PSA_ERROR_DATA_INVALID; } } #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ static psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem) { psa_status_t status = PSA_SUCCESS; uint8_t driver_wrappers_initialized = 0; switch (subsystem) { case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS: #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) { /* Init drivers */ status = psa_driver_wrapper_init(); /* Drivers need shutdown regardless of startup errors. */ global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED; } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ break; case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS: #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) { status = psa_initialize_key_slots(); /* Need to wipe keys even if initialization fails. */ global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED; } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ break; case PSA_CRYPTO_SUBSYSTEM_RNG: #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ driver_wrappers_initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED); #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ /* Need to use separate mutex here, as initialisation can require * testing of init flags, which requires locking the global data * mutex. */ #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ /* Initialize and seed the random generator. */ if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) { mbedtls_psa_random_init(&global_data.rng); global_data.rng_state = RNG_INITIALIZED; status = mbedtls_psa_random_seed(&global_data.rng); if (status == PSA_SUCCESS) { global_data.rng_state = RNG_SEEDED; } } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_rngdata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ break; case PSA_CRYPTO_SUBSYSTEM_TRANSACTION: #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) { #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) status = psa_crypto_load_transaction(); if (status == PSA_SUCCESS) { status = psa_crypto_recover_transaction(&psa_crypto_transaction); if (status == PSA_SUCCESS) { global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; } status = psa_crypto_stop_transaction(); } else if (status == PSA_ERROR_DOES_NOT_EXIST) { /* There's no transaction to complete. It's all good. */ global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; status = PSA_SUCCESS; } #else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */ global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; status = PSA_SUCCESS; #endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */ } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ break; default: status = PSA_ERROR_CORRUPTION_DETECTED; } /* Exit label only required when using threading macros. */ #if defined(MBEDTLS_THREADING_C) exit: #endif /* defined(MBEDTLS_THREADING_C) */ return status; } psa_status_t psa_crypto_init(void) { psa_status_t status; /* Double initialization is explicitly allowed. Early out if everything is * done. */ if (psa_get_initialized()) { return PSA_SUCCESS; } status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION); exit: if (status != PSA_SUCCESS) { mbedtls_psa_crypto_free(); } return status; } #if defined(PSA_WANT_ALG_SOME_PAKE) psa_status_t psa_crypto_driver_pake_get_password_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *password_len) { if (inputs->password_len == 0) { return PSA_ERROR_BAD_STATE; } *password_len = inputs->password_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_password( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *buffer, size_t buffer_size, size_t *buffer_length) { if (inputs->password_len == 0) { return PSA_ERROR_BAD_STATE; } if (buffer_size < inputs->password_len) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(buffer, inputs->password, inputs->password_len); *buffer_length = inputs->password_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_user_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *user_len) { if (inputs->user_len == 0) { return PSA_ERROR_BAD_STATE; } *user_len = inputs->user_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_user( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *user_id, size_t user_id_size, size_t *user_id_len) { if (inputs->user_len == 0) { return PSA_ERROR_BAD_STATE; } if (user_id_size < inputs->user_len) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(user_id, inputs->user, inputs->user_len); *user_id_len = inputs->user_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_peer_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *peer_len) { if (inputs->peer_len == 0) { return PSA_ERROR_BAD_STATE; } *peer_len = inputs->peer_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_peer( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length) { if (inputs->peer_len == 0) { return PSA_ERROR_BAD_STATE; } if (peer_id_size < inputs->peer_len) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(peer_id, inputs->peer, inputs->peer_len); *peer_id_length = inputs->peer_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_cipher_suite( const psa_crypto_driver_pake_inputs_t *inputs, psa_pake_cipher_suite_t *cipher_suite) { if (inputs->cipher_suite.algorithm == PSA_ALG_NONE) { return PSA_ERROR_BAD_STATE; } *cipher_suite = inputs->cipher_suite; return PSA_SUCCESS; } psa_status_t psa_pake_setup( psa_pake_operation_t *operation, const psa_pake_cipher_suite_t *cipher_suite) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->stage != PSA_PAKE_OPERATION_STAGE_SETUP) { status = PSA_ERROR_BAD_STATE; goto exit; } if (PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 || PSA_ALG_IS_HASH(cipher_suite->hash) == 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } memset(&operation->data.inputs, 0, sizeof(operation->data.inputs)); operation->alg = cipher_suite->algorithm; operation->primitive = PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family, cipher_suite->bits); operation->data.inputs.cipher_suite = *cipher_suite; #if defined(PSA_WANT_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { psa_jpake_computation_stage_t *computation_stage = &operation->computation_stage.jpake; memset(computation_stage, 0, sizeof(*computation_stage)); computation_stage->step = PSA_PAKE_STEP_KEY_SHARE; } else #endif /* PSA_WANT_ALG_JPAKE */ { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } operation->stage = PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS; return PSA_SUCCESS; exit: psa_pake_abort(operation); return status; } psa_status_t psa_pake_set_password_key( psa_pake_operation_t *operation, mbedtls_svc_key_id_t password) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; psa_key_type_t type; if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_get_and_lock_key_slot_with_policy(password, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); if (status != PSA_SUCCESS) { goto exit; } type = psa_get_key_type(&slot->attr); if (type != PSA_KEY_TYPE_PASSWORD && type != PSA_KEY_TYPE_PASSWORD_HASH) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } operation->data.inputs.password = mbedtls_calloc(1, slot->key.bytes); if (operation->data.inputs.password == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto exit; } memcpy(operation->data.inputs.password, slot->key.data, slot->key.bytes); operation->data.inputs.password_len = slot->key.bytes; operation->data.inputs.attributes = slot->attr; exit: if (status != PSA_SUCCESS) { psa_pake_abort(operation); } unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_pake_set_user( psa_pake_operation_t *operation, const uint8_t *user_id_external, size_t user_id_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(user_id_external, user_id); if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = PSA_ERROR_BAD_STATE; goto exit; } if (user_id_len == 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } if (operation->data.inputs.user_len != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } operation->data.inputs.user = mbedtls_calloc(1, user_id_len); if (operation->data.inputs.user == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto exit; } LOCAL_INPUT_ALLOC(user_id_external, user_id_len, user_id); memcpy(operation->data.inputs.user, user_id, user_id_len); operation->data.inputs.user_len = user_id_len; status = PSA_SUCCESS; exit: LOCAL_INPUT_FREE(user_id_external, user_id); if (status != PSA_SUCCESS) { psa_pake_abort(operation); } return status; } psa_status_t psa_pake_set_peer( psa_pake_operation_t *operation, const uint8_t *peer_id_external, size_t peer_id_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(peer_id_external, peer_id); if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = PSA_ERROR_BAD_STATE; goto exit; } if (peer_id_len == 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } if (operation->data.inputs.peer_len != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } operation->data.inputs.peer = mbedtls_calloc(1, peer_id_len); if (operation->data.inputs.peer == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto exit; } LOCAL_INPUT_ALLOC(peer_id_external, peer_id_len, peer_id); memcpy(operation->data.inputs.peer, peer_id, peer_id_len); operation->data.inputs.peer_len = peer_id_len; status = PSA_SUCCESS; exit: LOCAL_INPUT_FREE(peer_id_external, peer_id); if (status != PSA_SUCCESS) { psa_pake_abort(operation); } return status; } psa_status_t psa_pake_set_role( psa_pake_operation_t *operation, psa_pake_role_t role) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = PSA_ERROR_BAD_STATE; goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: if (role == PSA_PAKE_ROLE_NONE) { return PSA_SUCCESS; } status = PSA_ERROR_INVALID_ARGUMENT; break; #endif default: (void) role; status = PSA_ERROR_NOT_SUPPORTED; goto exit; } exit: psa_pake_abort(operation); return status; } /* Auxiliary function to convert core computation stage to single driver step. */ #if defined(PSA_WANT_ALG_JPAKE) static psa_crypto_driver_pake_step_t convert_jpake_computation_stage_to_driver_step( psa_jpake_computation_stage_t *stage) { psa_crypto_driver_pake_step_t key_share_step; if (stage->round == PSA_JPAKE_FIRST) { int is_x1; if (stage->io_mode == PSA_JPAKE_OUTPUT) { is_x1 = (stage->outputs < 1); } else { is_x1 = (stage->inputs < 1); } key_share_step = is_x1 ? PSA_JPAKE_X1_STEP_KEY_SHARE : PSA_JPAKE_X2_STEP_KEY_SHARE; } else if (stage->round == PSA_JPAKE_SECOND) { key_share_step = (stage->io_mode == PSA_JPAKE_OUTPUT) ? PSA_JPAKE_X2S_STEP_KEY_SHARE : PSA_JPAKE_X4S_STEP_KEY_SHARE; } else { return PSA_JPAKE_STEP_INVALID; } return (psa_crypto_driver_pake_step_t) (key_share_step + stage->step - PSA_PAKE_STEP_KEY_SHARE); } #endif /* PSA_WANT_ALG_JPAKE */ static psa_status_t psa_pake_complete_inputs( psa_pake_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Create copy of the inputs on stack as inputs share memory with the driver context which will be setup by the driver. */ psa_crypto_driver_pake_inputs_t inputs = operation->data.inputs; if (inputs.password_len == 0) { return PSA_ERROR_BAD_STATE; } if (operation->alg == PSA_ALG_JPAKE) { if (inputs.user_len == 0 || inputs.peer_len == 0) { return PSA_ERROR_BAD_STATE; } } /* Clear driver context */ mbedtls_platform_zeroize(&operation->data, sizeof(operation->data)); status = psa_driver_wrapper_pake_setup(operation, &inputs); /* Driver is responsible for creating its own copy of the password. */ mbedtls_zeroize_and_free(inputs.password, inputs.password_len); /* User and peer are translated to role. */ mbedtls_free(inputs.user); mbedtls_free(inputs.peer); if (status == PSA_SUCCESS) { #if defined(PSA_WANT_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { operation->stage = PSA_PAKE_OPERATION_STAGE_COMPUTATION; } else #endif /* PSA_WANT_ALG_JPAKE */ { status = PSA_ERROR_NOT_SUPPORTED; } } return status; } #if defined(PSA_WANT_ALG_JPAKE) static psa_status_t psa_jpake_prologue( psa_pake_operation_t *operation, psa_pake_step_t step, psa_jpake_io_mode_t io_mode) { if (step != PSA_PAKE_STEP_KEY_SHARE && step != PSA_PAKE_STEP_ZK_PUBLIC && step != PSA_PAKE_STEP_ZK_PROOF) { return PSA_ERROR_INVALID_ARGUMENT; } psa_jpake_computation_stage_t *computation_stage = &operation->computation_stage.jpake; if (computation_stage->round != PSA_JPAKE_FIRST && computation_stage->round != PSA_JPAKE_SECOND) { return PSA_ERROR_BAD_STATE; } /* Check that the step we are given is the one we were expecting */ if (step != computation_stage->step) { return PSA_ERROR_BAD_STATE; } if (step == PSA_PAKE_STEP_KEY_SHARE && computation_stage->inputs == 0 && computation_stage->outputs == 0) { /* Start of the round, so function decides whether we are inputting * or outputting */ computation_stage->io_mode = io_mode; } else if (computation_stage->io_mode != io_mode) { /* Middle of the round so the mode we are in must match the function * called by the user */ return PSA_ERROR_BAD_STATE; } return PSA_SUCCESS; } static psa_status_t psa_jpake_epilogue( psa_pake_operation_t *operation, psa_jpake_io_mode_t io_mode) { psa_jpake_computation_stage_t *stage = &operation->computation_stage.jpake; if (stage->step == PSA_PAKE_STEP_ZK_PROOF) { /* End of an input/output */ if (io_mode == PSA_JPAKE_INPUT) { stage->inputs++; if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round)) { stage->io_mode = PSA_JPAKE_OUTPUT; } } if (io_mode == PSA_JPAKE_OUTPUT) { stage->outputs++; if (stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) { stage->io_mode = PSA_JPAKE_INPUT; } } if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round) && stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) { /* End of a round, move to the next round */ stage->inputs = 0; stage->outputs = 0; stage->round++; } stage->step = PSA_PAKE_STEP_KEY_SHARE; } else { stage->step++; } return PSA_SUCCESS; } #endif /* PSA_WANT_ALG_JPAKE */ psa_status_t psa_pake_output( psa_pake_operation_t *operation, psa_pake_step_t step, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID; LOCAL_OUTPUT_DECLARE(output_external, output); *output_length = 0; if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = psa_pake_complete_inputs(operation); if (status != PSA_SUCCESS) { goto exit; } } if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { status = PSA_ERROR_BAD_STATE; goto exit; } if (output_size == 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: status = psa_jpake_prologue(operation, step, PSA_JPAKE_OUTPUT); if (status != PSA_SUCCESS) { goto exit; } driver_step = convert_jpake_computation_stage_to_driver_step( &operation->computation_stage.jpake); break; #endif /* PSA_WANT_ALG_JPAKE */ default: (void) step; status = PSA_ERROR_NOT_SUPPORTED; goto exit; } LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_pake_output(operation, driver_step, output, output_size, output_length); if (status != PSA_SUCCESS) { goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: status = psa_jpake_epilogue(operation, PSA_JPAKE_OUTPUT); if (status != PSA_SUCCESS) { goto exit; } break; #endif /* PSA_WANT_ALG_JPAKE */ default: status = PSA_ERROR_NOT_SUPPORTED; goto exit; } exit: LOCAL_OUTPUT_FREE(output_external, output); if (status != PSA_SUCCESS) { psa_pake_abort(operation); } return status; } psa_status_t psa_pake_input( psa_pake_operation_t *operation, psa_pake_step_t step, const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID; const size_t max_input_length = (size_t) PSA_PAKE_INPUT_SIZE(operation->alg, operation->primitive, step); LOCAL_INPUT_DECLARE(input_external, input); if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = psa_pake_complete_inputs(operation); if (status != PSA_SUCCESS) { goto exit; } } if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { status = PSA_ERROR_BAD_STATE; goto exit; } if (input_length == 0 || input_length > max_input_length) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: status = psa_jpake_prologue(operation, step, PSA_JPAKE_INPUT); if (status != PSA_SUCCESS) { goto exit; } driver_step = convert_jpake_computation_stage_to_driver_step( &operation->computation_stage.jpake); break; #endif /* PSA_WANT_ALG_JPAKE */ default: (void) step; status = PSA_ERROR_NOT_SUPPORTED; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_pake_input(operation, driver_step, input, input_length); if (status != PSA_SUCCESS) { goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: status = psa_jpake_epilogue(operation, PSA_JPAKE_INPUT); if (status != PSA_SUCCESS) { goto exit; } break; #endif /* PSA_WANT_ALG_JPAKE */ default: status = PSA_ERROR_NOT_SUPPORTED; goto exit; } exit: LOCAL_INPUT_FREE(input_external, input); if (status != PSA_SUCCESS) { psa_pake_abort(operation); } return status; } psa_status_t psa_pake_get_implicit_key( psa_pake_operation_t *operation, psa_key_derivation_operation_t *output) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t shared_key[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]; size_t shared_key_len = 0; if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { status = PSA_ERROR_BAD_STATE; goto exit; } #if defined(PSA_WANT_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { psa_jpake_computation_stage_t *computation_stage = &operation->computation_stage.jpake; if (computation_stage->round != PSA_JPAKE_FINISHED) { status = PSA_ERROR_BAD_STATE; goto exit; } } else #endif /* PSA_WANT_ALG_JPAKE */ { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = psa_driver_wrapper_pake_get_implicit_key(operation, shared_key, sizeof(shared_key), &shared_key_len); if (status != PSA_SUCCESS) { goto exit; } status = psa_key_derivation_input_bytes(output, PSA_KEY_DERIVATION_INPUT_SECRET, shared_key, shared_key_len); mbedtls_platform_zeroize(shared_key, sizeof(shared_key)); exit: abort_status = psa_pake_abort(operation); return status == PSA_SUCCESS ? abort_status : status; } psa_status_t psa_pake_abort( psa_pake_operation_t *operation) { psa_status_t status = PSA_SUCCESS; if (operation->stage == PSA_PAKE_OPERATION_STAGE_COMPUTATION) { status = psa_driver_wrapper_pake_abort(operation); } if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { if (operation->data.inputs.password != NULL) { mbedtls_zeroize_and_free(operation->data.inputs.password, operation->data.inputs.password_len); } if (operation->data.inputs.user != NULL) { mbedtls_free(operation->data.inputs.user); } if (operation->data.inputs.peer != NULL) { mbedtls_free(operation->data.inputs.peer); } } memset(operation, 0, sizeof(psa_pake_operation_t)); return status; } #endif /* PSA_WANT_ALG_SOME_PAKE */ /* Memory copying test hooks. These are called before input copy, after input * copy, before output copy and after output copy, respectively. * They are used by memory-poisoning tests to temporarily unpoison buffers * while they are copied. */ #if defined(MBEDTLS_TEST_HOOKS) void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len) = NULL; void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len) = NULL; void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len) = NULL; void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len) = NULL; #endif /** Copy from an input buffer to a local copy. * * \param[in] input Pointer to input buffer. * \param[in] input_len Length of the input buffer. * \param[out] input_copy Pointer to a local copy in which to store the input data. * \param[out] input_copy_len Length of the local copy buffer. * \return #PSA_SUCCESS, if the buffer was successfully * copied. * \return #PSA_ERROR_CORRUPTION_DETECTED, if the local * copy is too small to hold contents of the * input buffer. */ MBEDTLS_STATIC_TESTABLE psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len, uint8_t *input_copy, size_t input_copy_len) { if (input_len > input_copy_len) { return PSA_ERROR_CORRUPTION_DETECTED; } #if defined(MBEDTLS_TEST_HOOKS) if (psa_input_pre_copy_hook != NULL) { psa_input_pre_copy_hook(input, input_len); } #endif if (input_len > 0) { memcpy(input_copy, input, input_len); } #if defined(MBEDTLS_TEST_HOOKS) if (psa_input_post_copy_hook != NULL) { psa_input_post_copy_hook(input, input_len); } #endif return PSA_SUCCESS; } /** Copy from a local output buffer into a user-supplied one. * * \param[in] output_copy Pointer to a local buffer containing the output. * \param[in] output_copy_len Length of the local buffer. * \param[out] output Pointer to user-supplied output buffer. * \param[out] output_len Length of the user-supplied output buffer. * \return #PSA_SUCCESS, if the buffer was successfully * copied. * \return #PSA_ERROR_BUFFER_TOO_SMALL, if the * user-supplied output buffer is too small to * hold the contents of the local buffer. */ MBEDTLS_STATIC_TESTABLE psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len, uint8_t *output, size_t output_len) { if (output_len < output_copy_len) { return PSA_ERROR_BUFFER_TOO_SMALL; } #if defined(MBEDTLS_TEST_HOOKS) if (psa_output_pre_copy_hook != NULL) { psa_output_pre_copy_hook(output, output_len); } #endif if (output_copy_len > 0) { memcpy(output, output_copy, output_copy_len); } #if defined(MBEDTLS_TEST_HOOKS) if (psa_output_post_copy_hook != NULL) { psa_output_post_copy_hook(output, output_len); } #endif return PSA_SUCCESS; } psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len, psa_crypto_local_input_t *local_input) { psa_status_t status; *local_input = PSA_CRYPTO_LOCAL_INPUT_INIT; if (input_len == 0) { return PSA_SUCCESS; } local_input->buffer = mbedtls_calloc(input_len, 1); if (local_input->buffer == NULL) { /* Since we dealt with the zero-length case above, we know that * a NULL return value means a failure of allocation. */ return PSA_ERROR_INSUFFICIENT_MEMORY; } /* From now on, we must free local_input->buffer on error. */ local_input->length = input_len; status = psa_crypto_copy_input(input, input_len, local_input->buffer, local_input->length); if (status != PSA_SUCCESS) { goto error; } return PSA_SUCCESS; error: mbedtls_free(local_input->buffer); local_input->buffer = NULL; local_input->length = 0; return status; } void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input) { mbedtls_free(local_input->buffer); local_input->buffer = NULL; local_input->length = 0; } psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, psa_crypto_local_output_t *local_output) { *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; if (output_len == 0) { return PSA_SUCCESS; } local_output->buffer = mbedtls_calloc(output_len, 1); if (local_output->buffer == NULL) { /* Since we dealt with the zero-length case above, we know that * a NULL return value means a failure of allocation. */ return PSA_ERROR_INSUFFICIENT_MEMORY; } local_output->length = output_len; local_output->original = output; return PSA_SUCCESS; } psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output) { psa_status_t status; if (local_output->buffer == NULL) { local_output->length = 0; return PSA_SUCCESS; } if (local_output->original == NULL) { /* We have an internal copy but nothing to copy back to. */ return PSA_ERROR_CORRUPTION_DETECTED; } status = psa_crypto_copy_output(local_output->buffer, local_output->length, local_output->original, local_output->length); if (status != PSA_SUCCESS) { return status; } mbedtls_free(local_output->buffer); local_output->buffer = NULL; local_output->length = 0; return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_CRYPTO_C */ webfakes/src/mbedtls/library/entropy_poll.c0000644000176200001440000001533014740737024020632 0ustar liggesusers/* * Platform-specific and custom entropy polling functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #if defined(__linux__) || defined(__midipix__) /* Ensure that syscall() is available even when compiling with -std=c99 */ #if !defined(_GNU_SOURCE) #define _GNU_SOURCE #endif #endif #include "common.h" #include #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" #include "entropy_poll.h" #include "mbedtls/error.h" #if defined(MBEDTLS_TIMING_C) #include "mbedtls/timing.h" #endif #include "mbedtls/platform.h" #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ !defined(__HAIKU__) && !defined(__midipix__) && !defined(__MVS__) #error \ "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in mbedtls_config.h" #endif #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #include #include #if defined(__MINGW32__) // MINGW int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen) { HCRYPTPROV provider; ((void) data); *olen = 0; if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) { return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); } if (CryptGenRandom(provider, (DWORD) len, output) == FALSE ) { CryptReleaseContext( provider, 0 ); return(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED); } CryptReleaseContext(provider, 0); *olen = len; return 0; } #else int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen) { ((void) data); *olen = 0; /* * BCryptGenRandom takes ULONG for size, which is smaller than size_t on * 64-bit Windows platforms. Extract entropy in chunks of len (dependent * on ULONG_MAX) size. */ while (len != 0) { unsigned long ulong_bytes = (len > ULONG_MAX) ? ULONG_MAX : (unsigned long) len; if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, output, ulong_bytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG))) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } *olen += ulong_bytes; len -= ulong_bytes; } return 0; } #endif #else /* _WIN32 && !EFIX64 && !EFI32 */ /* * Test for Linux getrandom() support. * Since there is no wrapper in the libc yet, use the generic syscall wrapper * available in GNU libc and compatible libc's (eg uClibc). */ #if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__)) #include #include #if defined(SYS_getrandom) #define HAVE_GETRANDOM #include static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags) { /* MemSan cannot understand that the syscall writes to the buffer */ #if defined(__has_feature) #if __has_feature(memory_sanitizer) memset(buf, 0, buflen); #endif #endif return (int) syscall(SYS_getrandom, buf, buflen, flags); } #endif /* SYS_getrandom */ #endif /* __linux__ || __midipix__ */ #if defined(__FreeBSD__) || defined(__DragonFly__) #include #if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \ (defined(__DragonFly__) && __DragonFly_version >= 500700) #include #include #define HAVE_GETRANDOM static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags) { return (int) getrandom(buf, buflen, flags); } #endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) || (__DragonFly__ && __DragonFly_version >= 500700) */ #endif /* __FreeBSD__ || __DragonFly__ */ /* * Some BSD systems provide KERN_ARND. * This is equivalent to reading from /dev/urandom, only it doesn't require an * open file descriptor, and provides up to 256 bytes per call (basically the * same as getentropy(), but with a longer history). * * Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7 */ #if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM) #include #include #if defined(KERN_ARND) #define HAVE_SYSCTL_ARND static int sysctl_arnd_wrapper(unsigned char *buf, size_t buflen) { int name[2]; size_t len; name[0] = CTL_KERN; name[1] = KERN_ARND; while (buflen > 0) { len = buflen > 256 ? 256 : buflen; if (sysctl(name, 2, buf, &len, NULL, 0) == -1) { return -1; } buflen -= len; buf += len; } return 0; } #endif /* KERN_ARND */ #endif /* __FreeBSD__ || __NetBSD__ */ #include int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen) { FILE *file; size_t read_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ((void) data); #if defined(HAVE_GETRANDOM) ret = getrandom_wrapper(output, len, 0); if (ret >= 0) { *olen = (size_t) ret; return 0; } else if (errno != ENOSYS) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } /* Fall through if the system call isn't known. */ #else ((void) ret); #endif /* HAVE_GETRANDOM */ #if defined(HAVE_SYSCTL_ARND) ((void) file); ((void) read_len); if (sysctl_arnd_wrapper(output, len) == -1) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } *olen = len; return 0; #else *olen = 0; file = fopen("/dev/urandom", "rb"); if (file == NULL) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(file, NULL); read_len = fread(output, 1, len, file); if (read_len != len) { fclose(file); return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } fclose(file); *olen = len; return 0; #endif /* HAVE_SYSCTL_ARND */ } #endif /* _WIN32 && !EFIX64 && !EFI32 */ #endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ #if defined(MBEDTLS_ENTROPY_NV_SEED) int mbedtls_nv_seed_poll(void *data, unsigned char *output, size_t len, size_t *olen) { unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; ((void) data); memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE); if (mbedtls_nv_seed_read(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } if (len < use_len) { use_len = len; } memcpy(output, buf, use_len); *olen = use_len; return 0; } #endif /* MBEDTLS_ENTROPY_NV_SEED */ #endif /* MBEDTLS_ENTROPY_C */ webfakes/src/mbedtls/library/platform_util.c0000644000176200001440000002116114740737170020766 0ustar liggesusers/* * Common and shared functions used by multiple modules in the Mbed TLS * library. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Ensure gmtime_r is available even with -std=c99; must be defined before * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms * except OpenBSD, where it stops us accessing explicit_bzero. */ #if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__) #define _POSIX_C_SOURCE 200112L #endif #if !defined(_GNU_SOURCE) /* Clang requires this to get support for explicit_bzero */ #define _GNU_SOURCE #endif #include "common.h" #include "mbedtls/platform_util.h" #include "mbedtls/platform.h" #include "mbedtls/threading.h" #include #ifndef __STDC_WANT_LIB_EXT1__ #define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */ #endif #include #if defined(_WIN32) #include #endif // Detect platforms known to support explicit_bzero() #if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25) #define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1 #elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__) #define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1 #endif #if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) #undef HAVE_MEMORY_SANITIZER #if defined(__has_feature) #if __has_feature(memory_sanitizer) #include #define HAVE_MEMORY_SANITIZER #endif #endif /* * Where possible, we try to detect the presence of a platform-provided * secure memset, such as explicit_bzero(), that is safe against being optimized * out, and use that. * * For other platforms, we provide an implementation that aims not to be * optimized out by the compiler. * * This implementation for mbedtls_platform_zeroize() was inspired from Colin * Percival's blog article at: * * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html * * It uses a volatile function pointer to the standard memset(). Because the * pointer is volatile the compiler expects it to change at * any time and will not optimize out the call that could potentially perform * other operations on the input buffer instead of just setting it to 0. * Nevertheless, as pointed out by davidtgoldblatt on Hacker News * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for * details), optimizations of the following form are still possible: * * if (memset_func != memset) * memset_func(buf, 0, len); * * Note that it is extremely difficult to guarantee that * the memset() call will not be optimized out by aggressive compilers * in a portable way. For this reason, Mbed TLS also provides the configuration * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure * mbedtls_platform_zeroize() to use a suitable implementation for their * platform and needs. */ #if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !(defined(__STDC_LIB_EXT1__) && \ !defined(__IAR_SYSTEMS_ICC__)) \ && !defined(_WIN32) static void *(*const volatile memset_func)(void *, int, size_t) = memset; #endif void mbedtls_platform_zeroize(void *buf, size_t len) { if (len > 0) { #if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) explicit_bzero(buf, len); #if defined(HAVE_MEMORY_SANITIZER) /* You'd think that Msan would recognize explicit_bzero() as * equivalent to bzero(), but it actually doesn't on several * platforms, including Linux (Ubuntu 20.04). * https://github.com/google/sanitizers/issues/1507 * https://github.com/openssh/openssh-portable/commit/74433a19bb6f4cef607680fa4d1d7d81ca3826aa */ __msan_unpoison(buf, len); #endif #elif defined(__STDC_LIB_EXT1__) && !defined(__IAR_SYSTEMS_ICC__) memset_s(buf, len, 0, len); #elif defined(_WIN32) SecureZeroMemory(buf, len); #else memset_func(buf, 0, len); #endif #if defined(__GNUC__) /* For clang and recent gcc, pretend that we have some assembly that reads the * zero'd memory as an additional protection against being optimised away. */ #if defined(__clang__) || (__GNUC__ >= 10) #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wvla" #elif defined(MBEDTLS_COMPILER_IS_GCC) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wvla" #endif asm volatile ("" : : "m" (*(char (*)[len]) buf) :); #if defined(__clang__) # pragma clang diagnostic pop #elif defined(MBEDTLS_COMPILER_IS_GCC) # pragma GCC diagnostic pop #endif #endif #endif } } #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ void mbedtls_zeroize_and_free(void *buf, size_t len) { if (buf != NULL) { mbedtls_platform_zeroize(buf, len); } mbedtls_free(buf); } #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) #include #if !defined(_WIN32) && (defined(unix) || \ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ defined(__MACH__)) || defined(__midipix__)) #include #endif /* !_WIN32 && (unix || __unix || __unix__ || * (__APPLE__ && __MACH__) || __midipix__) */ #if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \ (defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \ _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L)) /* * This is a convenience shorthand macro to avoid checking the long * preprocessor conditions above. Ideally, we could expose this macro in * platform_util.h and simply use it in platform_util.c, threading.c and * threading.h. However, this macro is not part of the Mbed TLS public API, so * we keep it private by only defining it in this file */ #if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) || \ (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) #define PLATFORM_UTIL_USE_GMTIME #endif #endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt, struct tm *tm_buf) { #if defined(_WIN32) && !defined(PLATFORM_UTIL_USE_GMTIME) #if defined(__STDC_LIB_EXT1__) return (gmtime_s(tt, tm_buf) == 0) ? NULL : tm_buf; #else /* MSVC and mingw64 argument order and return value are inconsistent with the C11 standard */ return (gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL; #endif #elif !defined(PLATFORM_UTIL_USE_GMTIME) return gmtime_r(tt, tm_buf); #else struct tm *lt; #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_lock(&mbedtls_threading_gmtime_mutex) != 0) { return NULL; } #endif /* MBEDTLS_THREADING_C */ lt = gmtime(tt); if (lt != NULL) { memcpy(tm_buf, lt, sizeof(struct tm)); } #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&mbedtls_threading_gmtime_mutex) != 0) { return NULL; } #endif /* MBEDTLS_THREADING_C */ return (lt == NULL) ? NULL : tm_buf; #endif /* _WIN32 && !EFIX64 && !EFI32 */ } #endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ #if defined(MBEDTLS_TEST_HOOKS) void (*mbedtls_test_hook_test_fail)(const char *, int, const char *); #endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_HAVE_TIME) && !defined(MBEDTLS_PLATFORM_MS_TIME_ALT) #include #if !defined(_WIN32) && \ (defined(unix) || defined(__unix) || defined(__unix__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) || defined(__midipix__)) #include #endif \ /* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__) || __HAIKU__ || __midipix__) */ #if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L) || defined(__HAIKU__) mbedtls_ms_time_t mbedtls_ms_time(void) { int ret; struct timespec tv; mbedtls_ms_time_t current_ms; #if defined(__linux__) && defined(CLOCK_BOOTTIME) || defined(__midipix__) ret = clock_gettime(CLOCK_BOOTTIME, &tv); #else ret = clock_gettime(CLOCK_MONOTONIC, &tv); #endif if (ret) { return time(NULL) * 1000; } current_ms = tv.tv_sec; return current_ms*1000 + tv.tv_nsec / 1000000; } #elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ defined(__MINGW32__) || defined(_WIN64) #include mbedtls_ms_time_t mbedtls_ms_time(void) { FILETIME ct; mbedtls_ms_time_t current_ms; GetSystemTimeAsFileTime(&ct); current_ms = ((mbedtls_ms_time_t) ct.dwLowDateTime + ((mbedtls_ms_time_t) (ct.dwHighDateTime) << 32LL))/10000; return current_ms; } #else #error "No mbedtls_ms_time available" #endif #endif /* MBEDTLS_HAVE_TIME && !MBEDTLS_PLATFORM_MS_TIME_ALT */ webfakes/src/mbedtls/library/ssl_cache.c0000644000176200001440000002510214740737024020026 0ustar liggesusers/* * SSL session cache implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * These session callbacks use a simple chained list * to store and retrieve the session information. */ #include "common.h" #if defined(MBEDTLS_SSL_CACHE_C) #include "mbedtls/platform.h" #include "mbedtls/ssl_cache.h" #include "ssl_misc.h" #include "mbedtls/error.h" #include void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache) { memset(cache, 0, sizeof(mbedtls_ssl_cache_context)); cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&cache->mutex); #endif } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cache_find_entry(mbedtls_ssl_cache_context *cache, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_cache_entry **dst) { int ret = MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND; #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t t = mbedtls_time(NULL); #endif mbedtls_ssl_cache_entry *cur; for (cur = cache->chain; cur != NULL; cur = cur->next) { #if defined(MBEDTLS_HAVE_TIME) if (cache->timeout != 0 && (int) (t - cur->timestamp) > cache->timeout) { continue; } #endif if (session_id_len != cur->session_id_len || memcmp(session_id, cur->session_id, cur->session_id_len) != 0) { continue; } break; } if (cur != NULL) { *dst = cur; ret = 0; } return ret; } int mbedtls_ssl_cache_get(void *data, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; mbedtls_ssl_cache_entry *entry; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { return ret; } #endif ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry); if (ret != 0) { goto exit; } ret = mbedtls_ssl_session_load(session, entry->session, entry->session_len); if (ret != 0) { goto exit; } ret = 0; exit: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&cache->mutex) != 0) { ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* zeroize a cache entry */ static void ssl_cache_entry_zeroize(mbedtls_ssl_cache_entry *entry) { if (entry == NULL) { return; } /* zeroize and free session structure */ if (entry->session != NULL) { mbedtls_zeroize_and_free(entry->session, entry->session_len); } /* zeroize the whole entry structure */ mbedtls_platform_zeroize(entry, sizeof(mbedtls_ssl_cache_entry)); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cache_pick_writing_slot(mbedtls_ssl_cache_context *cache, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_cache_entry **dst) { #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t t = mbedtls_time(NULL), oldest = 0; #endif /* MBEDTLS_HAVE_TIME */ mbedtls_ssl_cache_entry *old = NULL; int count = 0; mbedtls_ssl_cache_entry *cur, *last; /* Check 1: Is there already an entry with the given session ID? * * If yes, overwrite it. * * If not, `count` will hold the size of the session cache * at the end of this loop, and `last` will point to the last * entry, both of which will be used later. */ last = NULL; for (cur = cache->chain; cur != NULL; cur = cur->next) { count++; if (session_id_len == cur->session_id_len && memcmp(session_id, cur->session_id, cur->session_id_len) == 0) { goto found; } last = cur; } /* Check 2: Is there an outdated entry in the cache? * * If so, overwrite it. * * If not, remember the oldest entry in `old` for later. */ #if defined(MBEDTLS_HAVE_TIME) for (cur = cache->chain; cur != NULL; cur = cur->next) { if (cache->timeout != 0 && (int) (t - cur->timestamp) > cache->timeout) { goto found; } if (oldest == 0 || cur->timestamp < oldest) { oldest = cur->timestamp; old = cur; } } #endif /* MBEDTLS_HAVE_TIME */ /* Check 3: Is there free space in the cache? */ if (count < cache->max_entries) { /* Create new entry */ cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry)); if (cur == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } /* Append to the end of the linked list. */ if (last == NULL) { cache->chain = cur; } else { last->next = cur; } goto found; } /* Last resort: The cache is full and doesn't contain any outdated * elements. In this case, we evict the oldest one, judged by timestamp * (if present) or cache-order. */ #if defined(MBEDTLS_HAVE_TIME) if (old == NULL) { /* This should only happen on an ill-configured cache * with max_entries == 0. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* MBEDTLS_HAVE_TIME */ /* Reuse first entry in chain, but move to last place. */ if (cache->chain == NULL) { /* This should never happen */ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } old = cache->chain; cache->chain = old->next; old->next = NULL; last->next = old; #endif /* MBEDTLS_HAVE_TIME */ /* Now `old` points to the oldest entry to be overwritten. */ cur = old; found: /* If we're reusing an entry, free it first. */ if (cur->session != NULL) { /* `ssl_cache_entry_zeroize` would break the chain, * so we reuse `old` to record `next` temporarily. */ old = cur->next; ssl_cache_entry_zeroize(cur); cur->next = old; } #if defined(MBEDTLS_HAVE_TIME) cur->timestamp = t; #endif *dst = cur; return 0; } int mbedtls_ssl_cache_set(void *data, unsigned char const *session_id, size_t session_id_len, const mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; mbedtls_ssl_cache_entry *cur; size_t session_serialized_len = 0; unsigned char *session_serialized = NULL; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { return ret; } #endif ret = ssl_cache_pick_writing_slot(cache, session_id, session_id_len, &cur); if (ret != 0) { goto exit; } /* Check how much space we need to serialize the session * and allocate a sufficiently large buffer. */ ret = mbedtls_ssl_session_save(session, NULL, 0, &session_serialized_len); if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { goto exit; } session_serialized = mbedtls_calloc(1, session_serialized_len); if (session_serialized == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } /* Now serialize the session into the allocated buffer. */ ret = mbedtls_ssl_session_save(session, session_serialized, session_serialized_len, &session_serialized_len); if (ret != 0) { goto exit; } if (session_id_len > sizeof(cur->session_id)) { ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; goto exit; } cur->session_id_len = session_id_len; memcpy(cur->session_id, session_id, session_id_len); cur->session = session_serialized; cur->session_len = session_serialized_len; session_serialized = NULL; ret = 0; exit: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&cache->mutex) != 0) { ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif if (session_serialized != NULL) { mbedtls_zeroize_and_free(session_serialized, session_serialized_len); session_serialized = NULL; } return ret; } int mbedtls_ssl_cache_remove(void *data, unsigned char const *session_id, size_t session_id_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; mbedtls_ssl_cache_entry *entry; mbedtls_ssl_cache_entry *prev; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { return ret; } #endif ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry); /* No valid entry found, exit with success */ if (ret != 0) { ret = 0; goto exit; } /* Now we remove the entry from the chain */ if (entry == cache->chain) { cache->chain = entry->next; goto free; } for (prev = cache->chain; prev->next != NULL; prev = prev->next) { if (prev->next == entry) { prev->next = entry->next; break; } } free: ssl_cache_entry_zeroize(entry); mbedtls_free(entry); ret = 0; exit: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&cache->mutex) != 0) { ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } #if defined(MBEDTLS_HAVE_TIME) void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout) { if (timeout < 0) { timeout = 0; } cache->timeout = timeout; } #endif /* MBEDTLS_HAVE_TIME */ void mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max) { if (max < 0) { max = 0; } cache->max_entries = max; } void mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache) { mbedtls_ssl_cache_entry *cur, *prv; cur = cache->chain; while (cur != NULL) { prv = cur; cur = cur->next; ssl_cache_entry_zeroize(prv); mbedtls_free(prv); } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&cache->mutex); #endif cache->chain = NULL; } #endif /* MBEDTLS_SSL_CACHE_C */ webfakes/src/mbedtls/library/ssl_client.h0000644000176200001440000000067314740737024020254 0ustar liggesusers/** * TLS 1.2 and 1.3 client-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CLIENT_H #define MBEDTLS_SSL_CLIENT_H #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) #include "ssl_misc.h" #endif #include MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_CLIENT_H */ webfakes/src/mbedtls/library/nist_kw.c0000644000176200001440000005451614740737024017573 0ustar liggesusers/* * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes * only * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Definition of Key Wrapping: * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" * * Note: RFC 3394 defines different methodology for intermediate operations for * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. */ #include "common.h" #if defined(MBEDTLS_NIST_KW_C) #include "mbedtls/nist_kw.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #include "constant_time_internal.h" #include #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_NIST_KW_ALT) #define KW_SEMIBLOCK_LENGTH 8 #define MIN_SEMIBLOCKS_COUNT 3 /*! The 64-bit default integrity check value (ICV) for KW mode. */ static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; /*! The 32-bit default integrity check value (ICV) for KWP mode. */ static const unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 }; /* * Initialize context */ void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx) { memset(ctx, 0, sizeof(mbedtls_nist_kw_context)); } int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits, const int is_wrap) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, MBEDTLS_MODE_ECB); if (cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* * SP 800-38F currently defines AES cipher as the only block cipher allowed: * "For KW and KWP, the underlying block cipher shall be approved, and the * block size shall be 128 bits. Currently, the AES block cipher, with key * lengths of 128, 192, or 256 bits, is the only block cipher that fits * this profile." * Currently we don't support other 128 bit block ciphers for key wrapping, * such as Camellia and Aria. */ if (cipher != MBEDTLS_CIPHER_ID_AES) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } mbedtls_cipher_free(&ctx->cipher_ctx); if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { return ret; } if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, is_wrap ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) ) != 0) { return ret; } return 0; } /* * Free context */ void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx) { if (ctx == NULL) { return; } mbedtls_cipher_free(&ctx->cipher_ctx); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context)); } /* * Helper function for Xoring the uint64_t "t" with the encrypted A. * Defined in NIST SP 800-38F section 6.1 */ static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t) { size_t i = 0; for (i = 0; i < sizeof(t); i++) { A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff; } } /* * KW-AE as defined in SP 800-38F section 6.2 * KWP-AE as defined in SP 800-38F section 6.3 */ int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, const unsigned char *input, size_t in_len, unsigned char *output, size_t *out_len, size_t out_size) { int ret = 0; size_t semiblocks = 0; size_t s; size_t olen, padlen = 0; uint64_t t = 0; unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; *out_len = 0; /* * Generate the String to work on */ if (mode == MBEDTLS_KW_MODE_KW) { if (out_size < in_len + KW_SEMIBLOCK_LENGTH) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* * According to SP 800-38F Table 1, the plaintext length for KW * must be between 2 to 2^54-1 semiblocks inclusive. */ if (in_len < 16 || #if SIZE_MAX > 0x1FFFFFFFFFFFFF8 in_len > 0x1FFFFFFFFFFFFF8 || #endif in_len % KW_SEMIBLOCK_LENGTH != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH); memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len); } else { if (in_len % 8 != 0) { padlen = (8 - (in_len % 8)); } if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* * According to SP 800-38F Table 1, the plaintext length for KWP * must be between 1 and 2^32-1 octets inclusive. */ if (in_len < 1 #if SIZE_MAX > 0xFFFFFFFF || in_len > 0xFFFFFFFF #endif ) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2); MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output, KW_SEMIBLOCK_LENGTH / 2); memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len); memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen); } semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1; s = 6 * (semiblocks - 1); if (mode == MBEDTLS_KW_MODE_KWP && in_len <= KW_SEMIBLOCK_LENGTH) { memcpy(inbuff, output, 16); ret = mbedtls_cipher_update(&ctx->cipher_ctx, inbuff, 16, output, &olen); if (ret != 0) { goto cleanup; } } else { unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; unsigned char *A = output; /* * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 */ if (semiblocks < MIN_SEMIBLOCKS_COUNT) { ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; goto cleanup; } /* Calculate intermediate values */ for (t = 1; t <= s; t++) { memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH); memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH); ret = mbedtls_cipher_update(&ctx->cipher_ctx, inbuff, 16, outbuff, &olen); if (ret != 0) { goto cleanup; } memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); calc_a_xor_t(A, t); memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); R2 += KW_SEMIBLOCK_LENGTH; if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) { R2 = output + KW_SEMIBLOCK_LENGTH; } } } *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; cleanup: if (ret != 0) { memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH); } mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2); mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2); return ret; } /* * W-1 function as defined in RFC 3394 section 2.2.2 * This function assumes the following: * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. * 3. Minimal number of semiblocks is 3. * 4. A is a buffer to hold the first semiblock of the input buffer. */ static int unwrap(mbedtls_nist_kw_context *ctx, const unsigned char *input, size_t semiblocks, unsigned char A[KW_SEMIBLOCK_LENGTH], unsigned char *output, size_t *out_len) { int ret = 0; const size_t s = 6 * (semiblocks - 1); size_t olen; uint64_t t = 0; unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; unsigned char *R = NULL; *out_len = 0; if (semiblocks < MIN_SEMIBLOCKS_COUNT) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } memcpy(A, input, KW_SEMIBLOCK_LENGTH); memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH); R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH; /* Calculate intermediate values */ for (t = s; t >= 1; t--) { calc_a_xor_t(A, t); memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH); memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH); ret = mbedtls_cipher_update(&ctx->cipher_ctx, inbuff, 16, outbuff, &olen); if (ret != 0) { goto cleanup; } memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); /* Set R as LSB64 of outbuff */ memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); if (R == output) { R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH; } else { R -= KW_SEMIBLOCK_LENGTH; } } *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH; cleanup: if (ret != 0) { memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH); } mbedtls_platform_zeroize(inbuff, sizeof(inbuff)); mbedtls_platform_zeroize(outbuff, sizeof(outbuff)); return ret; } /* * KW-AD as defined in SP 800-38F section 6.2 * KWP-AD as defined in SP 800-38F section 6.3 */ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, const unsigned char *input, size_t in_len, unsigned char *output, size_t *out_len, size_t out_size) { int ret = 0; size_t olen; unsigned char A[KW_SEMIBLOCK_LENGTH]; int diff; *out_len = 0; if (out_size < in_len - KW_SEMIBLOCK_LENGTH) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (mode == MBEDTLS_KW_MODE_KW) { /* * According to SP 800-38F Table 1, the ciphertext length for KW * must be between 3 to 2^54 semiblocks inclusive. */ if (in_len < 24 || #if SIZE_MAX > 0x200000000000000 in_len > 0x200000000000000 || #endif in_len % KW_SEMIBLOCK_LENGTH != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH, A, output, out_len); if (ret != 0) { goto cleanup; } /* Check ICV in "constant-time" */ diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH); if (diff != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; goto cleanup; } } else if (mode == MBEDTLS_KW_MODE_KWP) { size_t padlen = 0; uint32_t Plen; /* * According to SP 800-38F Table 1, the ciphertext length for KWP * must be between 2 to 2^29 semiblocks inclusive. */ if (in_len < KW_SEMIBLOCK_LENGTH * 2 || #if SIZE_MAX > 0x100000000 in_len > 0x100000000 || #endif in_len % KW_SEMIBLOCK_LENGTH != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (in_len == KW_SEMIBLOCK_LENGTH * 2) { unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; ret = mbedtls_cipher_update(&ctx->cipher_ctx, input, 16, outbuff, &olen); if (ret != 0) { goto cleanup; } memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); mbedtls_platform_zeroize(outbuff, sizeof(outbuff)); *out_len = KW_SEMIBLOCK_LENGTH; } else { /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH, A, output, out_len); if (ret != 0) { goto cleanup; } } /* Check ICV in "constant-time" */ diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2); if (diff != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2); /* * Plen is the length of the plaintext, when the input is valid. * If Plen is larger than the plaintext and padding, padlen will be * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7), MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); padlen &= 7; /* Check padding in "constant-time" */ const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 }; diff = mbedtls_ct_memcmp_partial( &output[*out_len - KW_SEMIBLOCK_LENGTH], zero, KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0); if (diff != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } if (ret != 0) { goto cleanup; } memset(output + Plen, 0, padlen); *out_len = Plen; } else { ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; goto cleanup; } cleanup: if (ret != 0) { memset(output, 0, *out_len); *out_len = 0; } mbedtls_platform_zeroize(&diff, sizeof(diff)); mbedtls_platform_zeroize(A, sizeof(A)); return ret; } #endif /* !MBEDTLS_NIST_KW_ALT */ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /* * Test vectors taken from NIST * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW */ static const unsigned int key_len[] = { 16, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 24, 32 #endif }; static const unsigned char kw_key[][32] = { { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } #endif }; static const unsigned char kw_msg[][40] = { { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } #endif }; static const size_t kw_msg_len[] = { 16, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 40, 24 #endif }; static const size_t kw_out_len[] = { 24, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 48, 32 #endif }; static const unsigned char kw_res[][48] = { { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } #endif }; static const unsigned char kwp_key[][32] = { { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } #endif }; static const unsigned char kwp_msg[][31] = { { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, 0x96 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, { 0xd1 } #endif }; static const size_t kwp_msg_len[] = { 9, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 31, 1 #endif }; static const unsigned char kwp_res[][48] = { { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } #endif }; static const size_t kwp_out_len[] = { 24, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 40, 16 #endif }; int mbedtls_nist_kw_self_test(int verbose) { mbedtls_nist_kw_context ctx; unsigned char out[48]; size_t olen; int i; int ret = 0; mbedtls_nist_kw_init(&ctx); /* * KW mode */ { static const int num_tests = sizeof(kw_key) / sizeof(*kw_key); for (i = 0; i < num_tests; i++) { if (verbose != 0) { mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8); } ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kw_key[i], key_len[i] * 8, 1); if (ret != 0) { if (verbose != 0) { mbedtls_printf(" KW: setup failed "); } goto end; } ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], kw_msg_len[i], out, &olen, sizeof(out)); if (ret != 0 || kw_out_len[i] != olen || memcmp(out, kw_res[i], kw_out_len[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed. "); } ret = 1; goto end; } if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kw_key[i], key_len[i] * 8, 0)) != 0) { if (verbose != 0) { mbedtls_printf(" KW: setup failed "); } goto end; } ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, out, olen, out, &olen, sizeof(out)); if (ret != 0 || olen != kw_msg_len[i] || memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto end; } if (verbose != 0) { mbedtls_printf(" passed\n"); } } } /* * KWP mode */ { static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key); for (i = 0; i < num_tests; i++) { olen = sizeof(out); if (verbose != 0) { mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8); } ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], key_len[i] * 8, 1); if (ret != 0) { if (verbose != 0) { mbedtls_printf(" KWP: setup failed "); } goto end; } ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], kwp_msg_len[i], out, &olen, sizeof(out)); if (ret != 0 || kwp_out_len[i] != olen || memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed. "); } ret = 1; goto end; } if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], key_len[i] * 8, 0)) != 0) { if (verbose != 0) { mbedtls_printf(" KWP: setup failed "); } goto end; } ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out, olen, out, &olen, sizeof(out)); if (ret != 0 || olen != kwp_msg_len[i] || memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed. "); } ret = 1; goto end; } if (verbose != 0) { mbedtls_printf(" passed\n"); } } } end: mbedtls_nist_kw_free(&ctx); if (verbose != 0) { mbedtls_printf("\n"); } return ret; } #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_NIST_KW_C */ webfakes/src/mbedtls/library/x509_csr.c0000644000176200001440000004653414740737024017472 0ustar liggesusers/* * X.509 Certificate Signing Request (CSR) parsing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. * * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ #include "common.h" #if defined(MBEDTLS_X509_CSR_PARSE_C) #include "mbedtls/x509_csr.h" #include "x509_internal.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #include "mbedtls/platform.h" #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) #include #endif /* * Version ::= INTEGER { v1(0) } */ static int x509_csr_get_version(unsigned char **p, const unsigned char *end, int *ver) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { *ver = 0; return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret); } return 0; } /* * Parse CSR extension requests in DER format */ static int x509_csr_parse_extensions(mbedtls_x509_csr *csr, unsigned char **p, const unsigned char *end, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *end_ext_data, *end_ext_octet; while (*p < end) { mbedtls_x509_buf extn_oid = { 0, 0, NULL }; int is_critical = 0; /* DEFAULT FALSE */ int ext_type = 0; /* Read sequence tag */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_ext_data = *p + len; /* Get extension ID */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } extn_oid.tag = MBEDTLS_ASN1_OID; extn_oid.p = *p; *p += extn_oid.len; /* Get optional critical */ if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Data should be octet string type */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_ext_octet = *p + len; if (end_ext_octet != end_ext_data) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * Detect supported extensions and skip unsupported extensions */ ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); if (ret != 0) { /* Give the callback (if any) a chance to handle the extension */ if (cb != NULL) { ret = cb(p_ctx, csr, &extn_oid, is_critical, *p, end_ext_octet); if (ret != 0 && is_critical) { return ret; } *p = end_ext_octet; continue; } /* No parser found, skip extension */ *p = end_ext_octet; if (is_critical) { /* Data is marked as critical: fail */ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } continue; } /* Forbid repeated extensions */ if ((csr->ext_types & ext_type) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_DATA); } csr->ext_types |= ext_type; switch (ext_type) { case MBEDTLS_X509_EXT_KEY_USAGE: /* Parse key usage */ if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data, &csr->key_usage)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: /* Parse subject alt name */ if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data, &csr->subject_alt_names)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_NS_CERT_TYPE: /* Parse netscape certificate type */ if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data, &csr->ns_cert_type)) != 0) { return ret; } break; default: /* * If this is a non-critical extension, which the oid layer * supports, but there isn't an x509 parser for it, * skip the extension. */ if (is_critical) { return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } else { *p = end_ext_octet; } } } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse CSR attributes in DER format */ static int x509_csr_parse_attributes(mbedtls_x509_csr *csr, const unsigned char *start, const unsigned char *end, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx) { int ret; size_t len; unsigned char *end_attr_data; unsigned char **p = (unsigned char **) &start; while (*p < end) { mbedtls_x509_buf attr_oid = { 0, 0, NULL }; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_attr_data = *p + len; /* Get attribute ID */ if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } attr_oid.tag = MBEDTLS_ASN1_OID; attr_oid.p = *p; *p += attr_oid.len; /* Check that this is an extension-request attribute */ if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) { if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if ((ret = x509_csr_parse_extensions(csr, p, *p + len, cb, p_ctx)) != 0) { return ret; } if (*p != end_attr_data) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } *p = end_attr_data; } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse a CSR in DER format */ static int mbedtls_x509_csr_parse_der_internal(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *p, *end; mbedtls_x509_buf sig_params; memset(&sig_params, 0, sizeof(mbedtls_x509_buf)); /* * Check for valid input */ if (csr == NULL || buf == NULL || buflen == 0) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } mbedtls_x509_csr_init(csr); /* * first copy the raw DER data */ p = mbedtls_calloc(1, len = buflen); if (p == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } memcpy(p, buf, buflen); csr->raw.p = p; csr->raw.len = len; end = p + len; /* * CertificationRequest ::= SEQUENCE { * certificationRequestInfo CertificationRequestInfo, * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERR_X509_INVALID_FORMAT; } if (len != (size_t) (end - p)) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * CertificationRequestInfo ::= SEQUENCE { */ csr->cri.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } end = p + len; csr->cri.len = (size_t) (end - csr->cri.p); /* * Version ::= INTEGER { v1(0) } */ if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) { mbedtls_x509_csr_free(csr); return ret; } if (csr->version != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERR_X509_UNKNOWN_VERSION; } csr->version++; /* * subject Name */ csr->subject_raw.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) { mbedtls_x509_csr_free(csr); return ret; } csr->subject_raw.len = (size_t) (p - csr->subject_raw.p); /* * subjectPKInfo SubjectPublicKeyInfo */ if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) { mbedtls_x509_csr_free(csr); return ret; } /* * attributes [0] Attributes * * The list of possible attributes is open-ended, though RFC 2985 * (PKCS#9) defines a few in section 5.4. We currently don't support any, * so we just ignore them. This is a safe thing to do as the worst thing * that could happen is that we issue a certificate that does not match * the requester's expectations - this cannot cause a violation of our * signature policies. */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if ((ret = x509_csr_parse_attributes(csr, p, p + len, cb, p_ctx)) != 0) { mbedtls_x509_csr_free(csr); return ret; } p += len; end = csr->raw.p + csr->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING */ if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) { mbedtls_x509_csr_free(csr); return ret; } if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params, &csr->sig_md, &csr->sig_pk, &csr->sig_opts)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG; } if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) { mbedtls_x509_csr_free(csr); return ret; } if (p != end) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse a CSR in DER format */ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen) { return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, NULL, NULL); } /* * Parse a CSR in DER format with callback for unknown extensions */ int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx) { return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, cb, p_ctx); } /* * Parse a CSR, allowing for PEM or raw DER encoding */ int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen) { #if defined(MBEDTLS_PEM_PARSE_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t use_len; mbedtls_pem_context pem; #endif /* * Check for valid input */ if (csr == NULL || buf == NULL || buflen == 0) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } #if defined(MBEDTLS_PEM_PARSE_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (buf[buflen - 1] == '\0') { mbedtls_pem_init(&pem); ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN CERTIFICATE REQUEST-----", "-----END CERTIFICATE REQUEST-----", buf, NULL, 0, &use_len); if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN NEW CERTIFICATE REQUEST-----", "-----END NEW CERTIFICATE REQUEST-----", buf, NULL, 0, &use_len); } if (ret == 0) { /* * Was PEM encoded, parse the result */ ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen); } mbedtls_pem_free(&pem); if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } } #endif /* MBEDTLS_PEM_PARSE_C */ return mbedtls_x509_csr_parse_der(csr, buf, buflen); } #if defined(MBEDTLS_FS_IO) /* * Load a CSR into the structure */ int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_x509_csr_parse(csr, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) #define BEFORE_COLON 14 #define BC "14" /* * Return an informational string about the CSR. */ int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_csr *csr) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; char *p; char key_size_str[BEFORE_COLON]; p = buf; n = size; ret = mbedtls_snprintf(p, n, "%sCSR version : %d", prefix, csr->version); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &csr->subject); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, csr->sig_opts); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON, mbedtls_pk_get_name(&csr->pk))) != 0) { return ret; } ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, (int) mbedtls_pk_get_bitlen(&csr->pk)); MBEDTLS_X509_SAFE_SNPRINTF; /* * Optional extensions */ if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n, &csr->subject_alt_names, prefix)) != 0) { return ret; } } if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) { ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) { return ret; } } if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) { ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) { return ret; } } if (csr->ext_types != 0) { ret = mbedtls_snprintf(p, n, "\n"); MBEDTLS_X509_SAFE_SNPRINTF; } return (int) (size - n); } #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Initialize a CSR */ void mbedtls_x509_csr_init(mbedtls_x509_csr *csr) { memset(csr, 0, sizeof(mbedtls_x509_csr)); } /* * Unallocate all CSR data */ void mbedtls_x509_csr_free(mbedtls_x509_csr *csr) { if (csr == NULL) { return; } mbedtls_pk_free(&csr->pk); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_free(csr->sig_opts); #endif mbedtls_asn1_free_named_data_list_shallow(csr->subject.next); mbedtls_asn1_sequence_free(csr->subject_alt_names.next); if (csr->raw.p != NULL) { mbedtls_zeroize_and_free(csr->raw.p, csr->raw.len); } mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr)); } #endif /* MBEDTLS_X509_CSR_PARSE_C */ webfakes/src/mbedtls/library/rsa_alt_helpers.h0000644000176200001440000002016114740737024021256 0ustar liggesusers/** * \file rsa_alt_helpers.h * * \brief Context-independent RSA helper functions * * This module declares some RSA-related helper functions useful when * implementing the RSA interface. These functions are provided in a separate * compilation unit in order to make it easy for designers of alternative RSA * implementations to use them in their own code, as it is conceived that the * functionality they provide will be necessary for most complete * implementations. * * End-users of Mbed TLS who are not providing their own alternative RSA * implementations should not use these functions directly, and should instead * use only the functions declared in rsa.h. * * The interface provided by this module will be maintained through LTS (Long * Term Support) branches of Mbed TLS, but may otherwise be subject to change, * and must be considered an internal interface of the library. * * There are two classes of helper functions: * * (1) Parameter-generating helpers. These are: * - mbedtls_rsa_deduce_primes * - mbedtls_rsa_deduce_private_exponent * - mbedtls_rsa_deduce_crt * Each of these functions takes a set of core RSA parameters and * generates some other, or CRT related parameters. * * (2) Parameter-checking helpers. These are: * - mbedtls_rsa_validate_params * - mbedtls_rsa_validate_crt * They take a set of core or CRT related RSA parameters and check their * validity. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RSA_ALT_HELPERS_H #define MBEDTLS_RSA_ALT_HELPERS_H #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" #ifdef __cplusplus extern "C" { #endif /** * \brief Compute RSA prime moduli P, Q from public modulus N=PQ * and a pair of private and public key. * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param N RSA modulus N = PQ, with P, Q to be found * \param E RSA public exponent * \param D RSA private exponent * \param P Pointer to MPI holding first prime factor of N on success * \param Q Pointer to MPI holding second prime factor of N on success * * \return * - 0 if successful. In this case, P and Q constitute a * factorization of N. * - A non-zero error code otherwise. * * \note It is neither checked that P, Q are prime nor that * D, E are modular inverses wrt. P-1 and Q-1. For that, * use the helper function \c mbedtls_rsa_validate_params. * */ int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N, mbedtls_mpi const *E, mbedtls_mpi const *D, mbedtls_mpi *P, mbedtls_mpi *Q); /** * \brief Compute RSA private exponent from * prime moduli and public key. * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param P First prime factor of RSA modulus * \param Q Second prime factor of RSA modulus * \param E RSA public exponent * \param D Pointer to MPI holding the private exponent on success. * * \return * - 0 if successful. In this case, D is set to a simultaneous * modular inverse of E modulo both P-1 and Q-1. * - A non-zero error code otherwise. * * \note This function does not check whether P and Q are primes. * */ int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P, mbedtls_mpi const *Q, mbedtls_mpi const *E, mbedtls_mpi *D); /** * \brief Generate RSA-CRT parameters * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param P First prime factor of N * \param Q Second prime factor of N * \param D RSA private exponent * \param DP Output variable for D modulo P-1 * \param DQ Output variable for D modulo Q-1 * \param QP Output variable for the modular inverse of Q modulo P. * * \return 0 on success, non-zero error code otherwise. * * \note This function does not check whether P, Q are * prime and whether D is a valid private exponent. * */ int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP); /** * \brief Check validity of core RSA parameters * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param N RSA modulus N = PQ * \param P First prime factor of N * \param Q Second prime factor of N * \param D RSA private exponent * \param E RSA public exponent * \param f_rng PRNG to be used for primality check, or NULL * \param p_rng PRNG context for f_rng, or NULL * * \return * - 0 if the following conditions are satisfied * if all relevant parameters are provided: * - P prime if f_rng != NULL (%) * - Q prime if f_rng != NULL (%) * - 1 < N = P * Q * - 1 < D, E < N * - D and E are modular inverses modulo P-1 and Q-1 * (%) This is only done if MBEDTLS_GENPRIME is defined. * - A non-zero error code otherwise. * * \note The function can be used with a restricted set of arguments * to perform specific checks only. E.g., calling it with * (-,P,-,-,-) and a PRNG amounts to a primality check for P. */ int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Check validity of RSA CRT parameters * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param P First prime factor of RSA modulus * \param Q Second prime factor of RSA modulus * \param D RSA private exponent * \param DP MPI to check for D modulo P-1 * \param DQ MPI to check for D modulo P-1 * \param QP MPI to check for the modular inverse of Q modulo P. * * \return * - 0 if the following conditions are satisfied: * - D = DP mod P-1 if P, D, DP != NULL * - Q = DQ mod P-1 if P, D, DQ != NULL * - QP = Q^-1 mod P if P, Q, QP != NULL * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, * potentially including \c MBEDTLS_ERR_MPI_XXX if some * MPI calculations failed. * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient * data was provided to check DP, DQ or QP. * * \note The function can be used with a restricted set of arguments * to perform specific checks only. E.g., calling it with the * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. */ int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *DP, const mbedtls_mpi *DQ, const mbedtls_mpi *QP); #ifdef __cplusplus } #endif #endif /* rsa_alt_helpers.h */ webfakes/src/mbedtls/library/common.h0000644000176200001440000004034614740737024017406 0ustar liggesusers/** * \file common.h * * \brief Utility macros for internal use in the library */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_LIBRARY_COMMON_H #define MBEDTLS_LIBRARY_COMMON_H #include "mbedtls/build_info.h" #include "alignment.h" #include #include #include #include #if defined(__ARM_NEON) #include #define MBEDTLS_HAVE_NEON_INTRINSICS #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) #include #define MBEDTLS_HAVE_NEON_INTRINSICS #endif /** Helper to define a function as static except when building invasive tests. * * If a function is only used inside its own source file and should be * declared `static` to allow the compiler to optimize for code size, * but that function has unit tests, define it with * ``` * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... } * ``` * and declare it in a header in the `library/` directory with * ``` * #if defined(MBEDTLS_TEST_HOOKS) * int mbedtls_foo(...); * #endif * ``` */ #if defined(MBEDTLS_TEST_HOOKS) #define MBEDTLS_STATIC_TESTABLE #else #define MBEDTLS_STATIC_TESTABLE static #endif #if defined(MBEDTLS_TEST_HOOKS) extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const char *file); #define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) \ do { \ if ((!(TEST)) && ((*mbedtls_test_hook_test_fail) != NULL)) \ { \ (*mbedtls_test_hook_test_fail)( #TEST, __LINE__, __FILE__); \ } \ } while (0) #else #define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) #endif /* defined(MBEDTLS_TEST_HOOKS) */ /** \def ARRAY_LENGTH * Return the number of elements of a static or stack array. * * \param array A value of array (not pointer) type. * * \return The number of elements of the array. */ /* A correct implementation of ARRAY_LENGTH, but which silently gives * a nonsensical result if called with a pointer rather than an array. */ #define ARRAY_LENGTH_UNSAFE(array) \ (sizeof(array) / sizeof(*(array))) #if defined(__GNUC__) /* Test if arg and &(arg)[0] have the same type. This is true if arg is * an array but not if it's a pointer. */ #define IS_ARRAY_NOT_POINTER(arg) \ (!__builtin_types_compatible_p(__typeof__(arg), \ __typeof__(&(arg)[0]))) /* A compile-time constant with the value 0. If `const_expr` is not a * compile-time constant with a nonzero value, cause a compile-time error. */ #define STATIC_ASSERT_EXPR(const_expr) \ (0 && sizeof(struct { unsigned int STATIC_ASSERT : 1 - 2 * !(const_expr); })) /* Return the scalar value `value` (possibly promoted). This is a compile-time * constant if `value` is. `condition` must be a compile-time constant. * If `condition` is false, arrange to cause a compile-time error. */ #define STATIC_ASSERT_THEN_RETURN(condition, value) \ (STATIC_ASSERT_EXPR(condition) ? 0 : (value)) #define ARRAY_LENGTH(array) \ (STATIC_ASSERT_THEN_RETURN(IS_ARRAY_NOT_POINTER(array), \ ARRAY_LENGTH_UNSAFE(array))) #else /* If we aren't sure the compiler supports our non-standard tricks, * fall back to the unsafe implementation. */ #define ARRAY_LENGTH(array) ARRAY_LENGTH_UNSAFE(array) #endif /** Allow library to access its structs' private members. * * Although structs defined in header files are publicly available, * their members are private and should not be accessed by the user. */ #define MBEDTLS_ALLOW_PRIVATE_ACCESS /** * \brief Securely zeroize a buffer then free it. * * Similar to making consecutive calls to * \c mbedtls_platform_zeroize() and \c mbedtls_free(), but has * code size savings, and potential for optimisation in the future. * * Guaranteed to be a no-op if \p buf is \c NULL and \p len is 0. * * \param buf Buffer to be zeroized then freed. * \param len Length of the buffer in bytes */ void mbedtls_zeroize_and_free(void *buf, size_t len); /** Return an offset into a buffer. * * This is just the addition of an offset to a pointer, except that this * function also accepts an offset of 0 into a buffer whose pointer is null. * (`p + n` has undefined behavior when `p` is null, even when `n == 0`. * A null pointer is a valid buffer pointer when the size is 0, for example * as the result of `malloc(0)` on some platforms.) * * \param p Pointer to a buffer of at least n bytes. * This may be \p NULL if \p n is zero. * \param n An offset in bytes. * \return Pointer to offset \p n in the buffer \p p. * Note that this is only a valid pointer if the size of the * buffer is at least \p n + 1. */ static inline unsigned char *mbedtls_buffer_offset( unsigned char *p, size_t n) { return p == NULL ? NULL : p + n; } /** Return an offset into a read-only buffer. * * Similar to mbedtls_buffer_offset(), but for const pointers. * * \param p Pointer to a buffer of at least n bytes. * This may be \p NULL if \p n is zero. * \param n An offset in bytes. * \return Pointer to offset \p n in the buffer \p p. * Note that this is only a valid pointer if the size of the * buffer is at least \p n + 1. */ static inline const unsigned char *mbedtls_buffer_offset_const( const unsigned char *p, size_t n) { return p == NULL ? NULL : p + n; } /* Always inline mbedtls_xor() for similar reasons as mbedtls_xor_no_simd(). */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif /** * Perform a fast block XOR operation, such that * r[i] = a[i] ^ b[i] where 0 <= i < n * * \param r Pointer to result (buffer of at least \p n bytes). \p r * may be equal to either \p a or \p b, but behaviour when * it overlaps in other ways is undefined. * \param a Pointer to input (buffer of at least \p n bytes) * \param b Pointer to input (buffer of at least \p n bytes) * \param n Number of bytes to process. * * \note Depending on the situation, it may be faster to use either mbedtls_xor() or * mbedtls_xor_no_simd() (these are functionally equivalent). * If the result is used immediately after the xor operation in non-SIMD code (e.g, in * AES-CBC), there may be additional latency to transfer the data from SIMD to scalar * registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where * the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster. * For targets without SIMD support, they will behave the same. */ static inline void mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n) { size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) #if defined(MBEDTLS_HAVE_NEON_INTRINSICS) && \ (!(defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION < 70300)) /* Old GCC versions generate a warning here, so disable the NEON path for these compilers */ for (; (i + 16) <= n; i += 16) { uint8x16_t v1 = vld1q_u8(a + i); uint8x16_t v2 = vld1q_u8(b + i); uint8x16_t x = veorq_u8(v1, v2); vst1q_u8(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case * where n is a constant multiple of 16. * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time * constant, and is a very small perf regression if n is not a compile-time constant. */ if (n % 16 == 0) { return; } #endif #elif defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64) /* This codepath probably only makes sense on architectures with 64-bit registers */ for (; (i + 8) <= n; i += 8) { uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i); mbedtls_put_unaligned_uint64(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) if (n % 8 == 0) { return; } #endif #else for (; (i + 4) <= n; i += 4) { uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i); mbedtls_put_unaligned_uint32(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) if (n % 4 == 0) { return; } #endif #endif #endif for (; i < n; i++) { r[i] = a[i] ^ b[i]; } } /* Always inline mbedtls_xor_no_simd() as we see significant perf regressions when it does not get * inlined (e.g., observed about 3x perf difference in gcm_mult_largetable with gcc 7 - 12) */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif /** * Perform a fast block XOR operation, such that * r[i] = a[i] ^ b[i] where 0 <= i < n * * In some situations, this can perform better than mbedtls_xor() (e.g., it's about 5% * better in AES-CBC). * * \param r Pointer to result (buffer of at least \p n bytes). \p r * may be equal to either \p a or \p b, but behaviour when * it overlaps in other ways is undefined. * \param a Pointer to input (buffer of at least \p n bytes) * \param b Pointer to input (buffer of at least \p n bytes) * \param n Number of bytes to process. * * \note Depending on the situation, it may be faster to use either mbedtls_xor() or * mbedtls_xor_no_simd() (these are functionally equivalent). * If the result is used immediately after the xor operation in non-SIMD code (e.g, in * AES-CBC), there may be additional latency to transfer the data from SIMD to scalar * registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where * the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster. * For targets without SIMD support, they will behave the same. */ static inline void mbedtls_xor_no_simd(unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n) { size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) #if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64) /* This codepath probably only makes sense on architectures with 64-bit registers */ for (; (i + 8) <= n; i += 8) { uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i); mbedtls_put_unaligned_uint64(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case * where n is a constant multiple of 8. * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time * constant, and is a very small perf regression if n is not a compile-time constant. */ if (n % 8 == 0) { return; } #endif #else for (; (i + 4) <= n; i += 4) { uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i); mbedtls_put_unaligned_uint32(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) if (n % 4 == 0) { return; } #endif #endif #endif for (; i < n; i++) { r[i] = a[i] ^ b[i]; } } /* Fix MSVC C99 compatible issue * MSVC support __func__ from visual studio 2015( 1900 ) * Use MSVC predefine macro to avoid name check fail. */ #if (defined(_MSC_VER) && (_MSC_VER <= 1900)) #define /*no-check-names*/ __func__ __FUNCTION__ #endif /* Define `asm` for compilers which don't define it. */ /* *INDENT-OFF* */ #ifndef asm #if defined(__IAR_SYSTEMS_ICC__) #define asm __asm #else #define asm __asm__ #endif #endif /* *INDENT-ON* */ /* * Define the constraint used for read-only pointer operands to aarch64 asm. * * This is normally the usual "r", but for aarch64_32 (aka ILP32, * as found in watchos), "p" is required to avoid warnings from clang. * * Note that clang does not recognise '+p' or '=p', and armclang * does not recognise 'p' at all. Therefore, to update a pointer from * aarch64 assembly, it is necessary to use something like: * * uintptr_t uptr = (uintptr_t) ptr; * asm( "ldr x4, [%x0], #8" ... : "+r" (uptr) : : ) * ptr = (void*) uptr; * * Note that the "x" in "%x0" is neccessary; writing "%0" will cause warnings. */ #if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM) #if UINTPTR_MAX == 0xfffffffful /* ILP32: Specify the pointer operand slightly differently, as per #7787. */ #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "p" #elif UINTPTR_MAX == 0xfffffffffffffffful /* Normal case (64-bit pointers): use "r" as the constraint for pointer operands to asm */ #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "r" #else #error "Unrecognised pointer size for aarch64" #endif #endif /* Always provide a static assert macro, so it can be used unconditionally. * It does nothing on systems where we don't know how to define a static assert. */ /* Can't use the C11-style `defined(static_assert)` on FreeBSD, since it * defines static_assert even with -std=c99, but then complains about it. */ #if defined(static_assert) && !defined(__FreeBSD__) #define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg) #else /* Make sure `MBEDTLS_STATIC_ASSERT(expr, msg);` is valid both inside and * outside a function. We choose a struct declaration, which can be repeated * any number of times and does not need a matching definition. */ #define MBEDTLS_STATIC_ASSERT(expr, msg) \ struct ISO_C_does_not_allow_extra_semicolon_outside_of_a_function #endif #if defined(__has_builtin) #define MBEDTLS_HAS_BUILTIN(x) __has_builtin(x) #else #define MBEDTLS_HAS_BUILTIN(x) 0 #endif /* Define compiler branch hints */ #if MBEDTLS_HAS_BUILTIN(__builtin_expect) #define MBEDTLS_LIKELY(x) __builtin_expect(!!(x), 1) #define MBEDTLS_UNLIKELY(x) __builtin_expect(!!(x), 0) #else #define MBEDTLS_LIKELY(x) x #define MBEDTLS_UNLIKELY(x) x #endif /* MBEDTLS_ASSUME may be used to provide additional information to the compiler * which can result in smaller code-size. */ #if MBEDTLS_HAS_BUILTIN(__builtin_assume) /* clang provides __builtin_assume */ #define MBEDTLS_ASSUME(x) __builtin_assume(x) #elif MBEDTLS_HAS_BUILTIN(__builtin_unreachable) /* gcc and IAR can use __builtin_unreachable */ #define MBEDTLS_ASSUME(x) do { if (!(x)) __builtin_unreachable(); } while (0) #elif defined(_MSC_VER) /* Supported by MSVC since VS 2005 */ #define MBEDTLS_ASSUME(x) __assume(x) #else #define MBEDTLS_ASSUME(x) do { } while (0) #endif /* For gcc -Os, override with -O2 for a given function. * * This will not affect behaviour for other optimisation settings, e.g. -O0. */ #if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__OPTIMIZE_SIZE__) #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE __attribute__((optimize("-O2"))) #else #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE #endif /* Suppress compiler warnings for unused functions and variables. */ #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__has_attribute) # if __has_attribute(unused) # define MBEDTLS_MAYBE_UNUSED __attribute__((unused)) # endif #endif #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__GNUC__) # define MBEDTLS_MAYBE_UNUSED __attribute__((unused)) #endif #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__IAR_SYSTEMS_ICC__) && defined(__VER__) /* IAR does support __attribute__((unused)), but only if the -e flag (extended language support) * is given; the pragma always works. * Unfortunately the pragma affects the rest of the file where it is used, but this is harmless. * Check for version 5.2 or later - this pragma may be supported by earlier versions, but I wasn't * able to find documentation). */ # if (__VER__ >= 5020000) # define MBEDTLS_MAYBE_UNUSED _Pragma("diag_suppress=Pe177") # endif #endif #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(_MSC_VER) # define MBEDTLS_MAYBE_UNUSED __pragma(warning(suppress:4189)) #endif #if !defined(MBEDTLS_MAYBE_UNUSED) # define MBEDTLS_MAYBE_UNUSED #endif #endif /* MBEDTLS_LIBRARY_COMMON_H */ webfakes/src/mbedtls/library/lmots.c0000644000176200001440000006505614740737024017254 0ustar liggesusers/* * The LM-OTS one-time public-key signature scheme * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this implementation * of the LM-OTS algorithm: * * [1] IETF RFC8554 * D. McGrew, M. Curcio, S.Fluhrer * https://datatracker.ietf.org/doc/html/rfc8554 * * [2] NIST Special Publication 800-208 * David A. Cooper et. al. * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf */ #include "common.h" #if defined(MBEDTLS_LMS_C) #include #include "lmots.h" #include "mbedtls/lms.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "psa_util_internal.h" #include "psa/crypto.h" /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_lms_errors, ARRAY_LENGTH(psa_to_lms_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #define PUBLIC_KEY_TYPE_OFFSET (0) #define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ MBEDTLS_LMOTS_TYPE_LEN) #define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ MBEDTLS_LMOTS_I_KEY_ID_LEN) #define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \ MBEDTLS_LMOTS_Q_LEAF_ID_LEN) /* We only support parameter sets that use 8-bit digits, as it does not require * translation logic between digits and bytes */ #define W_WINTERNITZ_PARAMETER (8u) #define CHECKSUM_LEN (2) #define I_DIGIT_IDX_LEN (2) #define J_HASH_IDX_LEN (1) #define D_CONST_LEN (2) #define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) #define D_CONST_LEN (2) static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 }; static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 }; #if defined(MBEDTLS_TEST_HOOKS) int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL; #endif /* defined(MBEDTLS_TEST_HOOKS) */ /* Calculate the checksum digits that are appended to the end of the LMOTS digit * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of * the checksum algorithm. * * params The LMOTS parameter set, I and q values which * describe the key being used. * * digest The digit string to create the digest from. As * this does not contain a checksum, it is the same * size as a hash output. */ static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params, const unsigned char *digest) { size_t idx; unsigned sum = 0; for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) { sum += DIGIT_MAX_VALUE - digest[idx]; } return sum; } /* Create the string of digest digits (in the base determined by the Winternitz * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm * 4b step 3) for details. * * params The LMOTS parameter set, I and q values which * describe the key being used. * * msg The message that will be hashed to create the * digest. * * msg_size The size of the message. * * C_random_value The random value that will be combined with the * message digest. This is always the same size as a * hash output for whichever hash algorithm is * determined by the parameter set. * * output An output containing the digit string (+ * checksum) of length P digits (in the case of * MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of * size P bytes). */ static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params, const unsigned char *msg, size_t msg_len, const unsigned char *C_random_value, unsigned char *out) { psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned short checksum; status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, C_random_value, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, msg, msg_len); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } checksum = lmots_checksum_calculate(params, out); MBEDTLS_PUT_UINT16_BE(checksum, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); exit: psa_hash_abort(&op); return PSA_TO_MBEDTLS_ERR(status); } /* Hash each element of the string of digits (+ checksum), producing a hash * output for each element. This is used in several places (by varying the * hash_idx_min/max_values) in order to calculate a public key from a private * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554 * Algorithm 3 step 5), and to calculate a public key candidate from a * signature and message (RFC8554 Algorithm 4b step 3). * * params The LMOTS parameter set, I and q values which * describe the key being used. * * x_digit_array The array of digits (of size P, 34 in the case of * MBEDTLS_LMOTS_SHA256_N32_W8). * * hash_idx_min_values An array of the starting values of the j iterator * for each of the members of the digit array. If * this value in NULL, then all iterators will start * at 0. * * hash_idx_max_values An array of the upper bound values of the j * iterator for each of the members of the digit * array. If this value in NULL, then iterator is * bounded to be less than 2^w - 1 (255 in the case * of MBEDTLS_LMOTS_SHA256_N32_W8) * * output An array containing a hash output for each member * of the digit string P. In the case of * MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 * * 34. */ static int hash_digit_array(const mbedtls_lmots_parameters_t *params, const unsigned char *x_digit_array, const unsigned char *hash_idx_min_values, const unsigned char *hash_idx_max_values, unsigned char *output) { unsigned int i_digit_idx; unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN]; unsigned int j_hash_idx; unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN]; unsigned int j_hash_idx_min; unsigned int j_hash_idx_max; psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; for (i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); i_digit_idx++) { memcpy(tmp_hash, &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], MBEDTLS_LMOTS_N_HASH_LEN(params->type)); j_hash_idx_min = hash_idx_min_values != NULL ? hash_idx_min_values[i_digit_idx] : 0; j_hash_idx_max = hash_idx_max_values != NULL ? hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; for (j_hash_idx = j_hash_idx_min; j_hash_idx < j_hash_idx_max; j_hash_idx++) { status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0); status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); if (status != PSA_SUCCESS) { goto exit; } j_hash_idx_bytes[0] = (uint8_t) j_hash_idx; status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } psa_hash_abort(&op); } memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); } exit: psa_hash_abort(&op); mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash)); return PSA_TO_MBEDTLS_ERR(status); } /* Combine the hashes of the digit array into a public key. This is used in * in order to calculate a public key from a private key (RFC8554 Algorithm 1 * step 4), and to calculate a public key candidate from a signature and message * (RFC8554 Algorithm 4b step 3). * * params The LMOTS parameter set, I and q values which describe * the key being used. * y_hashed_digits The array of hashes, one hash for each digit of the * symbol array (which is of size P, 34 in the case of * MBEDTLS_LMOTS_SHA256_N32_W8) * * pub_key The output public key (or candidate public key in * case this is being run as part of signature * verification), in the form of a hash output. */ static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params, const unsigned char *y_hashed_digits, unsigned char *pub_key) { psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, y_hashed_digits, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) * MBEDTLS_LMOTS_N_HASH_LEN(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN(params->type), &output_hash_len); if (status != PSA_SUCCESS) { exit: psa_hash_abort(&op); } return PSA_TO_MBEDTLS_ERR(status); } #if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_lms_error_from_psa(psa_status_t status) { switch (status) { case PSA_SUCCESS: return 0; case PSA_ERROR_HARDWARE_FAILURE: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; case PSA_ERROR_BUFFER_TOO_SMALL: return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; case PSA_ERROR_INVALID_ARGUMENT: return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; default: return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } } #endif /* !MBEDTLS_DEPRECATED_REMOVED */ void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(*ctx)); } int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, const unsigned char *key, size_t key_len) { if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.type = (mbedtls_lmots_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } memcpy(ctx->params.I_key_identifier, key + PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN); memcpy(ctx->params.q_leaf_identifier, key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); memcpy(ctx->public_key, key + PUBLIC_KEY_KEY_HASH_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); ctx->have_public_key = 1; return 0; } int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len) { if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; } if (!ctx->have_public_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, ctx->params.q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); if (key_len != NULL) { *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type); } return 0; } int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size, unsigned char *out, size_t out_size, size_t *out_len) { unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (msg == NULL && msg_size != 0) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) || out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ret = create_digit_array_with_checksum(params, msg, msg_size, sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_digit_array); if (ret) { return ret; } ret = hash_digit_array(params, sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type), tmp_digit_array, NULL, (unsigned char *) y_hashed_digits); if (ret) { return ret; } ret = public_key_from_hashed_digit_array(params, (unsigned char *) y_hashed_digits, out); if (ret) { return ret; } if (out_len != NULL) { *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type); } return 0; } int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size) { unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (msg == NULL && msg_size != 0) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (!ctx->have_public_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (MBEDTLS_GET_UINT32_BE(sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params, msg, msg_size, sig, sig_size, Kc_public_key_candidate, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), NULL); if (ret) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (memcmp(&Kc_public_key_candidate, ctx->public_key, sizeof(ctx->public_key))) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } return 0; } #if defined(MBEDTLS_LMS_PRIVATE) void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(*ctx)); } int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, mbedtls_lmots_algorithm_type_t type, const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], uint32_t q_leaf_identifier, const unsigned char *seed, size_t seed_size) { psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned int i_digit_idx; unsigned char i_digit_idx_bytes[2]; unsigned char const_bytes[1] = { 0xFF }; if (ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (type != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.type = type; memcpy(ctx->params.I_key_identifier, I_key_identifier, sizeof(ctx->params.I_key_identifier)); MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ctx->params.q_leaf_identifier, 0); for (i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type); i_digit_idx++) { status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, ctx->params.I_key_identifier, sizeof(ctx->params.I_key_identifier)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, ctx->params.q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0); status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, const_bytes, sizeof(const_bytes)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, seed, seed_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, ctx->private_key[i_digit_idx], MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } psa_hash_abort(&op); } ctx->have_private_key = 1; exit: psa_hash_abort(&op); return PSA_TO_MBEDTLS_ERR(status); } int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, const mbedtls_lmots_private_t *priv_ctx) { unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Check that a private key is loaded */ if (!priv_ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ret = hash_digit_array(&priv_ctx->params, (unsigned char *) priv_ctx->private_key, NULL, NULL, (unsigned char *) y_hashed_digits); if (ret) { goto exit; } ret = public_key_from_hashed_digit_array(&priv_ctx->params, (unsigned char *) y_hashed_digits, ctx->public_key); if (ret) { goto exit; } memcpy(&ctx->params, &priv_ctx->params, sizeof(ctx->params)); ctx->have_public_key = 1; exit: mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits)); return ret; } int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *msg, size_t msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len) { unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; /* Create a temporary buffer to prepare the signature in. This allows us to * finish creating a signature (ensuring the process doesn't fail), and then * erase the private key **before** writing any data into the sig parameter * buffer. If data were directly written into the sig buffer, it might leak * a partial signature on failure, which effectively compromises the private * key. */ unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (msg == NULL && msg_size != 0) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; } /* Check that a private key is loaded */ if (!ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ret = f_rng(p_rng, tmp_c_random, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); if (ret) { return ret; } ret = create_digit_array_with_checksum(&ctx->params, msg, msg_size, tmp_c_random, tmp_digit_array); if (ret) { goto exit; } ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key, NULL, tmp_digit_array, (unsigned char *) tmp_sig); if (ret) { goto exit; } MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); /* Test hook to check if sig is being written to before we invalidate the * private key. */ #if defined(MBEDTLS_TEST_HOOKS) if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) { ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig); if (ret != 0) { return ret; } } #endif /* defined(MBEDTLS_TEST_HOOKS) */ /* We've got a valid signature now, so it's time to make sure the private * key can't be reused. */ ctx->have_private_key = 0; mbedtls_platform_zeroize(ctx->private_key, sizeof(ctx->private_key)); memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type)); memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type) * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); if (sig_len != NULL) { *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type); } ret = 0; exit: mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array)); mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig)); return ret; } #endif /* defined(MBEDTLS_LMS_PRIVATE) */ #endif /* defined(MBEDTLS_LMS_C) */ webfakes/src/mbedtls/library/ctr_drbg.c0000644000176200001440000007746614740737024017714 0ustar liggesusers/* * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The NIST SP 800-90 DRBGs are described in the following publication. * * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf */ #include "common.h" #if defined(MBEDTLS_CTR_DRBG_C) #include "ctr.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_FS_IO) #include #endif /* Using error translation functions from PSA to MbedTLS */ #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) #include "psa_util_internal.h" #endif #include "mbedtls/platform.h" #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx, unsigned char *key, size_t key_len) { psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status; psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES); status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id); if (status != PSA_SUCCESS) { goto exit; } status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING); if (status != PSA_SUCCESS) { goto exit; } exit: psa_reset_key_attributes(&key_attr); return status; } static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx) { psa_cipher_abort(&psa_ctx->operation); psa_destroy_key(psa_ctx->key_id); psa_ctx->operation = psa_cipher_operation_init(); psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT; } #endif /* * CTR_DRBG context initialization */ void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx) { memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context)); #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; ctx->psa_ctx.operation = psa_cipher_operation_init(); #else mbedtls_aes_init(&ctx->aes_ctx); #endif /* Indicate that the entropy nonce length is not set explicitly. * See mbedtls_ctr_drbg_set_nonce_len(). */ ctx->reseed_counter = -1; ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; } /* * This function resets CTR_DRBG context to the state immediately * after initial call of mbedtls_ctr_drbg_init(). */ void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_THREADING_C) /* The mutex is initialized iff f_entropy is set. */ if (ctx->f_entropy != NULL) { mbedtls_mutex_free(&ctx->mutex); } #endif #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); #else mbedtls_aes_free(&ctx->aes_ctx); #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context)); ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; ctx->reseed_counter = -1; } void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx, int resistance) { ctx->prediction_resistance = resistance; } void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, size_t len) { ctx->entropy_len = len; } int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx, size_t len) { /* If mbedtls_ctr_drbg_seed() has already been called, it's * too late. Return the error code that's closest to making sense. */ if (ctx->f_entropy != NULL) { return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } /* This shouldn't be an issue because * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible * configuration, but make sure anyway. */ if (len > INT_MAX) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } /* For backward compatibility with Mbed TLS <= 2.19, store the * entropy nonce length in a field that already exists, but isn't * used until after the initial seeding. */ /* Due to the capping of len above, the value fits in an int. */ ctx->reseed_counter = (int) len; return 0; } void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, int interval) { ctx->reseed_interval = interval; } static int block_cipher_df(unsigned char *output, const unsigned char *data, size_t data_len) { unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; unsigned char *p, *iv; int ret = 0; #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) psa_status_t status; size_t tmp_len; mbedtls_ctr_drbg_psa_context psa_ctx; psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_ctx.operation = psa_cipher_operation_init(); #else mbedtls_aes_context aes_ctx; #endif int i, j; size_t buf_len, use_len; if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16); /* * Construct IV (16 bytes) and S in buffer * IV = Counter (in 32-bits) padded to 16 with zeroes * S = Length input string (in 32-bits) || Length of output (in 32-bits) || * data || 0x80 * (Total is padded to a multiple of 16-bytes with zeroes) */ p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; MBEDTLS_PUT_UINT32_BE(data_len, p, 0); p += 4 + 3; *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; memcpy(p, data, data_len); p[data_len] = 0x80; buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) { key[i] = i; } #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key)); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #else mbedtls_aes_init(&aes_ctx); if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { goto exit; } #endif /* * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data */ for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { p = buf; memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE); use_len = buf_len; while (use_len > 0) { mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE); p += MBEDTLS_CTR_DRBG_BLOCKSIZE; use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #else if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain)) != 0) { goto exit; } #endif } memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE); /* * Update IV */ buf[3]++; } /* * Do final encryption with reduced data */ #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) ctr_drbg_destroy_psa_contex(&psa_ctx); status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #else if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { goto exit; } #endif iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; p = output; for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #else if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv)) != 0) { goto exit; } #endif memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE); p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } exit: #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) ctr_drbg_destroy_psa_contex(&psa_ctx); #else mbedtls_aes_free(&aes_ctx); #endif /* * tidy up the stack */ mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize(tmp, sizeof(tmp)); mbedtls_platform_zeroize(key, sizeof(key)); mbedtls_platform_zeroize(chain, sizeof(chain)); if (0 != ret) { /* * wipe partial seed from memory */ mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN); } return ret; } /* CTR_DRBG_Update (SP 800-90A §10.2.1.2) * ctr_drbg_update_internal(ctx, provided_data) * implements * CTR_DRBG_Update(provided_data, Key, V) * with inputs and outputs * ctx->aes_ctx = Key * ctx->counter = V */ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx, const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN]) { unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char *p = tmp; int j; int ret = 0; #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) psa_status_t status; size_t tmp_len; #endif memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN); for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { /* * Increase counter */ mbedtls_ctr_increment_counter(ctx->counter); /* * Crypt counter block */ #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #else if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p)) != 0) { goto exit; } #endif p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN); /* * Update key and counter */ #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #else if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { goto exit; } #endif memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE); exit: mbedtls_platform_zeroize(tmp, sizeof(tmp)); return ret; } /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) * mbedtls_ctr_drbg_update(ctx, additional, add_len) * implements * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, * security_strength) -> initial_working_state * with inputs * ctx->counter = all-bits-0 * ctx->aes_ctx = context from all-bits-0 key * additional[:add_len] = entropy_input || nonce || personalization_string * and with outputs * ctx = initial_working_state */ int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t add_len) { unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (add_len == 0) { return 0; } if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) { goto exit; } if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) { goto exit; } exit: mbedtls_platform_zeroize(add_input, sizeof(add_input)); return ret; } /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) * implements * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) * -> new_working_state * with inputs * ctx contains working_state * additional[:len] = additional_input * and entropy_input comes from calling ctx->f_entropy * for (ctx->entropy_len + nonce_len) bytes * and with output * ctx contains new_working_state */ static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len, size_t nonce_len) { unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; size_t seedlen = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT); /* Gather entropy_len bytes of entropy to seed state. */ if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) { return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } seedlen += ctx->entropy_len; /* Gather entropy for a nonce if requested. */ if (nonce_len != 0) { if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) { return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } seedlen += nonce_len; } /* Add additional data if provided. */ if (additional != NULL && len != 0) { memcpy(seed + seedlen, additional, len); seedlen += len; } /* Reduce to 384 bits. */ if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) { goto exit; } /* Update state. */ if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) { goto exit; } ctx->reseed_counter = 1; exit: mbedtls_platform_zeroize(seed, sizeof(seed)); return ret; } int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len) { return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0); } /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length * is sufficient to achieve the maximum security strength given the key * size and entropy length. If there is enough entropy in the initial * call to the entropy function to serve as both the entropy input and * the nonce, don't make a second call to get a nonce. */ static size_t good_nonce_len(size_t entropy_len) { if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) { return 0; } else { return (entropy_len + 1) / 2; } } /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) * implements * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, * security_strength) -> initial_working_state * with inputs * custom[:len] = nonce || personalization_string * where entropy_input comes from f_entropy for ctx->entropy_len bytes * and with outputs * ctx = initial_working_state */ int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; size_t nonce_len; memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE); /* The mutex is initialized iff f_entropy is set. */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif ctx->f_entropy = f_entropy; ctx->p_entropy = p_entropy; if (ctx->entropy_len == 0) { ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; } /* ctx->reseed_counter contains the desired amount of entropy to * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). * If it's -1, indicating that the entropy nonce length was not set * explicitly, use a sufficiently large nonce for security. */ nonce_len = (ctx->reseed_counter >= 0 ? (size_t) ctx->reseed_counter : good_nonce_len(ctx->entropy_len)); /* Initialize with an empty key. */ #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) psa_status_t status; status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); return status; } #else if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { return ret; } #endif /* Do the initial seeding. */ if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len, nonce_len)) != 0) { return ret; } return 0; } /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) * implements * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) * -> working_state_after_reseed * if required, then * CTR_DRBG_Generate(working_state_after_reseed, * requested_number_of_bits, additional_input) * -> status, returned_bits, new_working_state * with inputs * ctx contains working_state * requested_number_of_bits = 8 * output_len * additional[:add_len] = additional_input * and entropy_input comes from calling ctx->f_entropy * and with outputs * status = SUCCESS (this function does the reseed internally) * returned_bits = output[:output_len] * ctx contains new_working_state */ int mbedtls_ctr_drbg_random_with_add(void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len) { int ret = 0; mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; unsigned char *p = output; struct { unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; } locals; size_t use_len; if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) { return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG; } if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN); if (ctx->reseed_counter > ctx->reseed_interval || ctx->prediction_resistance) { if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) { return ret; } add_len = 0; } if (add_len > 0) { if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) { goto exit; } if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { goto exit; } } while (output_len > 0) { /* * Increase counter (treat it as a 128-bit big-endian integer). */ mbedtls_ctr_increment_counter(ctx->counter); /* * Crypt counter block */ #if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO) psa_status_t status; size_t tmp_len; status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #else if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, locals.tmp)) != 0) { goto exit; } #endif use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; /* * Copy random block to destination */ memcpy(p, locals.tmp, use_len); p += use_len; output_len -= use_len; } if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { goto exit; } ctx->reseed_counter++; exit: mbedtls_platform_zeroize(&locals, sizeof(locals)); return ret; } int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, size_t output_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } #if defined(MBEDTLS_FS_IO) int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path) { int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; FILE *f; unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; if ((f = fopen(path, "wb")) == NULL) { return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); if ((ret = mbedtls_ctr_drbg_random(ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) { goto exit; } if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) != MBEDTLS_CTR_DRBG_MAX_INPUT) { ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; } else { ret = 0; } exit: mbedtls_platform_zeroize(buf, sizeof(buf)); fclose(f); return ret; } int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path) { int ret = 0; FILE *f = NULL; size_t n; unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; unsigned char c; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); n = fread(buf, 1, sizeof(buf), f); if (fread(&c, 1, 1, f) != 0) { ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; goto exit; } if (n == 0 || ferror(f)) { ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; goto exit; } fclose(f); f = NULL; ret = mbedtls_ctr_drbg_update(ctx, buf, n); exit: mbedtls_platform_zeroize(buf, sizeof(buf)); if (f != NULL) { fclose(f); } if (ret != 0) { return ret; } return mbedtls_ctr_drbg_write_seed_file(ctx, path); } #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /* The CTR_DRBG NIST test vectors used here are available at * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip * * The parameters used to derive the test data are: * * [AES-128 use df] * [PredictionResistance = True/False] * [EntropyInputLen = 128] * [NonceLen = 64] * [PersonalizationStringLen = 128] * [AdditionalInputLen = 0] * [ReturnedBitsLen = 512] * * [AES-256 use df] * [PredictionResistance = True/False] * [EntropyInputLen = 256] * [NonceLen = 128] * [PersonalizationStringLen = 256] * [AdditionalInputLen = 0] * [ReturnedBitsLen = 512] * */ #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) static const unsigned char entropy_source_pr[] = { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92, 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8, 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0, 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad, 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 }; static const unsigned char entropy_source_nopr[] = { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20, 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f, 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c }; static const unsigned char pers_pr[] = { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a, 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad }; static const unsigned char pers_nopr[] = { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c, 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f }; static const unsigned char result_pr[] = { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff, 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10, 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc, 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06, 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf }; static const unsigned char result_nopr[] = { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0, 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf, 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2, 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02, 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 }; #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ static const unsigned char entropy_source_pr[] = { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a, 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85, 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15, 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45, 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c, 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3, 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e, 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76, 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe }; static const unsigned char entropy_source_nopr[] = { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0, 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73, 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2, 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1, 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb, 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a, 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 }; static const unsigned char pers_pr[] = { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e, 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0, 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 }; static const unsigned char pers_nopr[] = { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf, 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb, 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b }; static const unsigned char result_pr[] = { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d, 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62, 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39, 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40, 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 }; static const unsigned char result_nopr[] = { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3, 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b, 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30, 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a, 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 }; #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ static size_t test_offset; static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf, size_t len) { const unsigned char *p = data; memcpy(buf, p + test_offset, len); test_offset += len; return 0; } #define CHK(c) if ((c) != 0) \ { \ if (verbose != 0) \ mbedtls_printf("failed\n"); \ return 1; \ } #define SELF_TEST_OUTPUT_DISCARD_LENGTH 64 /* * Checkup routine */ int mbedtls_ctr_drbg_self_test(int verbose) { mbedtls_ctr_drbg_context ctx; unsigned char buf[sizeof(result_pr)]; mbedtls_ctr_drbg_init(&ctx); /* * Based on a NIST CTR_DRBG test vector (PR = True) */ if (verbose != 0) { mbedtls_printf(" CTR_DRBG (PR = TRUE) : "); } test_offset = 0; mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); CHK(mbedtls_ctr_drbg_seed(&ctx, ctr_drbg_self_test_entropy, (void *) entropy_source_pr, pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE)); mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON); CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr))); CHK(memcmp(buf, result_pr, sizeof(result_pr))); mbedtls_ctr_drbg_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } /* * Based on a NIST CTR_DRBG test vector (PR = FALSE) */ if (verbose != 0) { mbedtls_printf(" CTR_DRBG (PR = FALSE): "); } mbedtls_ctr_drbg_init(&ctx); test_offset = 0; mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); CHK(mbedtls_ctr_drbg_seed(&ctx, ctr_drbg_self_test_entropy, (void *) entropy_source_nopr, pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE)); CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0)); CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr))); CHK(memcmp(buf, result_nopr, sizeof(result_nopr))); mbedtls_ctr_drbg_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_CTR_DRBG_C */ webfakes/src/mbedtls/library/base64.c0000644000176200001440000001752314740737024017176 0ustar liggesusers/* * RFC 1521 base64 encoding/decoding * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include #include "common.h" #if defined(MBEDTLS_BASE64_C) #include "mbedtls/base64.h" #include "base64_internal.h" #include "constant_time_internal.h" #include #if defined(MBEDTLS_SELF_TEST) #include #include "mbedtls/platform.h" #endif /* MBEDTLS_SELF_TEST */ MBEDTLS_STATIC_TESTABLE unsigned char mbedtls_ct_base64_enc_char(unsigned char value) { unsigned char digit = 0; /* For each range of values, if value is in that range, mask digit with * the corresponding value. Since value can only be in a single range, * only at most one masking will change digit. */ digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value); digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26); digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52); digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+'); digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/'); return digit; } MBEDTLS_STATIC_TESTABLE signed char mbedtls_ct_base64_dec_value(unsigned char c) { unsigned char val = 0; /* For each range of digits, if c is in that range, mask val with * the corresponding value. Since c can only be in a single range, * only at most one masking will change val. Set val to one plus * the desired value so that it stays 0 if c is in none of the ranges. */ val |= mbedtls_ct_uchar_in_range_if('A', 'Z', c, c - 'A' + 0 + 1); val |= mbedtls_ct_uchar_in_range_if('a', 'z', c, c - 'a' + 26 + 1); val |= mbedtls_ct_uchar_in_range_if('0', '9', c, c - '0' + 52 + 1); val |= mbedtls_ct_uchar_in_range_if('+', '+', c, c - '+' + 62 + 1); val |= mbedtls_ct_uchar_in_range_if('/', '/', c, c - '/' + 63 + 1); /* At this point, val is 0 if c is an invalid digit and v+1 if c is * a digit with the value v. */ return val - 1; } /* * Encode a buffer into base64 format */ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen) { size_t i, n; int C1, C2, C3; unsigned char *p; if (slen == 0) { *olen = 0; return 0; } n = slen / 3 + (slen % 3 != 0); if (n > (SIZE_MAX - 1) / 4) { *olen = SIZE_MAX; return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; } n *= 4; if ((dlen < n + 1) || (NULL == dst)) { *olen = n + 1; return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; } n = (slen / 3) * 3; for (i = 0, p = dst; i < n; i += 3) { C1 = *src++; C2 = *src++; C3 = *src++; *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F); *p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4)) & 0x3F); *p++ = mbedtls_ct_base64_enc_char((((C2 & 15) << 2) + (C3 >> 6)) & 0x3F); *p++ = mbedtls_ct_base64_enc_char(C3 & 0x3F); } if (i < slen) { C1 = *src++; C2 = ((i + 1) < slen) ? *src++ : 0; *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F); *p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4)) & 0x3F); if ((i + 1) < slen) { *p++ = mbedtls_ct_base64_enc_char(((C2 & 15) << 2) & 0x3F); } else { *p++ = '='; } *p++ = '='; } *olen = (size_t) (p - dst); *p = 0; return 0; } /* * Decode a base64-formatted buffer */ int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen) { size_t i; /* index in source */ size_t n; /* number of digits or trailing = in source */ uint32_t x; /* value accumulator */ unsigned accumulated_digits = 0; unsigned equals = 0; int spaces_present = 0; unsigned char *p; /* First pass: check for validity and get output length */ for (i = n = 0; i < slen; i++) { /* Skip spaces before checking for EOL */ spaces_present = 0; while (i < slen && src[i] == ' ') { ++i; spaces_present = 1; } /* Spaces at end of buffer are OK */ if (i == slen) { break; } if ((slen - i) >= 2 && src[i] == '\r' && src[i + 1] == '\n') { continue; } if (src[i] == '\n') { continue; } /* Space inside a line is an error */ if (spaces_present) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } if (src[i] > 127) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } if (src[i] == '=') { if (++equals > 2) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } } else { if (equals != 0) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } if (mbedtls_ct_base64_dec_value(src[i]) < 0) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } } n++; } if (n == 0) { *olen = 0; return 0; } /* The following expression is to calculate the following formula without * risk of integer overflow in n: * n = ( ( n * 6 ) + 7 ) >> 3; */ n = (6 * (n >> 3)) + ((6 * (n & 0x7) + 7) >> 3); n -= equals; if (dst == NULL || dlen < n) { *olen = n; return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; } equals = 0; for (x = 0, p = dst; i > 0; i--, src++) { if (*src == '\r' || *src == '\n' || *src == ' ') { continue; } x = x << 6; if (*src == '=') { ++equals; } else { x |= mbedtls_ct_base64_dec_value(*src); } if (++accumulated_digits == 4) { accumulated_digits = 0; *p++ = MBEDTLS_BYTE_2(x); if (equals <= 1) { *p++ = MBEDTLS_BYTE_1(x); } if (equals <= 0) { *p++ = MBEDTLS_BYTE_0(x); } } } *olen = (size_t) (p - dst); return 0; } #if defined(MBEDTLS_SELF_TEST) static const unsigned char base64_test_dec[64] = { 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 }; static const unsigned char base64_test_enc[] = "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; /* * Checkup routine */ int mbedtls_base64_self_test(int verbose) { size_t len; const unsigned char *src; unsigned char buffer[128]; if (verbose != 0) { mbedtls_printf(" Base64 encoding test: "); } src = base64_test_dec; if (mbedtls_base64_encode(buffer, sizeof(buffer), &len, src, 64) != 0 || memcmp(base64_test_enc, buffer, 88) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } if (verbose != 0) { mbedtls_printf("passed\n Base64 decoding test: "); } src = base64_test_enc; if (mbedtls_base64_decode(buffer, sizeof(buffer), &len, src, 88) != 0 || memcmp(base64_test_dec, buffer, 64) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } if (verbose != 0) { mbedtls_printf("passed\n\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_BASE64_C */ webfakes/src/mbedtls/library/cipher.c0000644000176200001440000016406614740737024017371 0ustar liggesusers/** * \file cipher.c * * \brief Generic cipher wrapper for Mbed TLS * * \author Adriaan de Jong * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #include "cipher_wrap.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #include "constant_time_internal.h" #include #include #if defined(MBEDTLS_CHACHAPOLY_C) #include "mbedtls/chachapoly.h" #endif #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" #endif #if defined(MBEDTLS_CHACHA20_C) #include "mbedtls/chacha20.h" #endif #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) #include "psa/crypto.h" #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_NIST_KW_C) #include "mbedtls/nist_kw.h" #endif #include "mbedtls/platform.h" static int supported_init = 0; static inline const mbedtls_cipher_base_t *mbedtls_cipher_get_base( const mbedtls_cipher_info_t *info) { return mbedtls_cipher_base_lookup_table[info->base_idx]; } const int *mbedtls_cipher_list(void) { const mbedtls_cipher_definition_t *def; int *type; if (!supported_init) { def = mbedtls_cipher_definitions; type = mbedtls_cipher_supported; while (def->type != 0) { *type++ = (*def++).type; } *type = 0; supported_init = 1; } return mbedtls_cipher_supported; } const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type) { const mbedtls_cipher_definition_t *def; for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { if (def->type == cipher_type) { return def->info; } } return NULL; } const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name) { const mbedtls_cipher_definition_t *def; if (NULL == cipher_name) { return NULL; } for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { if (!strcmp(def->info->name, cipher_name)) { return def->info; } } return NULL; } const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, int key_bitlen, const mbedtls_cipher_mode_t mode) { const mbedtls_cipher_definition_t *def; for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { if (mbedtls_cipher_get_base(def->info)->cipher == cipher_id && mbedtls_cipher_info_get_key_bitlen(def->info) == (unsigned) key_bitlen && def->info->mode == mode) { return def->info; } } return NULL; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) static inline psa_key_type_t mbedtls_psa_translate_cipher_type( mbedtls_cipher_type_t cipher) { switch (cipher) { case MBEDTLS_CIPHER_AES_128_CCM: case MBEDTLS_CIPHER_AES_192_CCM: case MBEDTLS_CIPHER_AES_256_CCM: case MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_AES_128_GCM: case MBEDTLS_CIPHER_AES_192_GCM: case MBEDTLS_CIPHER_AES_256_GCM: case MBEDTLS_CIPHER_AES_128_CBC: case MBEDTLS_CIPHER_AES_192_CBC: case MBEDTLS_CIPHER_AES_256_CBC: case MBEDTLS_CIPHER_AES_128_ECB: case MBEDTLS_CIPHER_AES_192_ECB: case MBEDTLS_CIPHER_AES_256_ECB: return PSA_KEY_TYPE_AES; /* ARIA not yet supported in PSA. */ /* case MBEDTLS_CIPHER_ARIA_128_CCM: case MBEDTLS_CIPHER_ARIA_192_CCM: case MBEDTLS_CIPHER_ARIA_256_CCM: case MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_ARIA_128_GCM: case MBEDTLS_CIPHER_ARIA_192_GCM: case MBEDTLS_CIPHER_ARIA_256_GCM: case MBEDTLS_CIPHER_ARIA_128_CBC: case MBEDTLS_CIPHER_ARIA_192_CBC: case MBEDTLS_CIPHER_ARIA_256_CBC: return( PSA_KEY_TYPE_ARIA ); */ default: return 0; } } static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode( mbedtls_cipher_mode_t mode, size_t taglen) { switch (mode) { case MBEDTLS_MODE_ECB: return PSA_ALG_ECB_NO_PADDING; case MBEDTLS_MODE_GCM: return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, taglen); case MBEDTLS_MODE_CCM: return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen); case MBEDTLS_MODE_CCM_STAR_NO_TAG: return PSA_ALG_CCM_STAR_NO_TAG; case MBEDTLS_MODE_CBC: if (taglen == 0) { return PSA_ALG_CBC_NO_PADDING; } else { return 0; } default: return 0; } } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx) { memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); } void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { if (ctx->cipher_ctx != NULL) { mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; if (cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED) { /* xxx_free() doesn't allow to return failures. */ (void) psa_destroy_key(cipher_psa->slot); } mbedtls_zeroize_and_free(cipher_psa, sizeof(*cipher_psa)); } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t)); return; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_CMAC_C) if (ctx->cmac_ctx) { mbedtls_zeroize_and_free(ctx->cmac_ctx, sizeof(mbedtls_cmac_context_t)); } #endif if (ctx->cipher_ctx) { mbedtls_cipher_get_base(ctx->cipher_info)->ctx_free_func(ctx->cipher_ctx); } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t)); } int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info) { if (cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); if (mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func != NULL) { ctx->cipher_ctx = mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func(); if (ctx->cipher_ctx == NULL) { return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; } } ctx->cipher_info = cipher_info; return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info, size_t taglen) { psa_algorithm_t alg; mbedtls_cipher_context_psa *cipher_psa; if (NULL == cipher_info || NULL == ctx) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* Check that the underlying cipher mode and cipher type are * supported by the underlying PSA Crypto implementation. */ alg = mbedtls_psa_translate_cipher_mode(((mbedtls_cipher_mode_t) cipher_info->mode), taglen); if (alg == 0) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } if (mbedtls_psa_translate_cipher_type(((mbedtls_cipher_type_t) cipher_info->type)) == 0) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); cipher_psa = mbedtls_calloc(1, sizeof(mbedtls_cipher_context_psa)); if (cipher_psa == NULL) { return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; } cipher_psa->alg = alg; ctx->cipher_ctx = cipher_psa; ctx->cipher_info = cipher_info; ctx->psa_enabled = 1; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *key, int key_bitlen, const mbedtls_operation_t operation) { if (operation != MBEDTLS_ENCRYPT && operation != MBEDTLS_DECRYPT) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) && MBEDTLS_DECRYPT == operation) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; size_t const key_bytelen = ((size_t) key_bitlen + 7) / 8; psa_status_t status; psa_key_type_t key_type; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; /* PSA Crypto API only accepts byte-aligned keys. */ if (key_bitlen % 8 != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* Don't allow keys to be set multiple times. */ if (cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } key_type = mbedtls_psa_translate_cipher_type( ((mbedtls_cipher_type_t) ctx->cipher_info->type)); if (key_type == 0) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } psa_set_key_type(&attributes, key_type); /* Mbed TLS' cipher layer doesn't enforce the mode of operation * (encrypt vs. decrypt): it is possible to setup a key for encryption * and use it for AEAD decryption. Until tests relying on this * are changed, allow any usage in PSA. */ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, cipher_psa->alg); status = psa_import_key(&attributes, key, key_bytelen, &cipher_psa->slot); switch (status) { case PSA_SUCCESS: break; case PSA_ERROR_INSUFFICIENT_MEMORY: return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; default: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } /* Indicate that we own the key slot and need to * destroy it in mbedtls_cipher_free(). */ cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED; ctx->key_bitlen = key_bitlen; ctx->operation = operation; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN) == 0 && (int) mbedtls_cipher_info_get_key_bitlen(ctx->cipher_info) != key_bitlen) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } ctx->key_bitlen = key_bitlen; ctx->operation = operation; #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /* * For OFB, CFB and CTR mode always use the encryption key schedule */ if (MBEDTLS_ENCRYPT == operation || MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key, ctx->key_bitlen); } if (MBEDTLS_DECRYPT == operation) { return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_dec_func(ctx->cipher_ctx, key, ctx->key_bitlen); } #else if (operation == MBEDTLS_ENCRYPT || operation == MBEDTLS_DECRYPT) { return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key, ctx->key_bitlen); } #endif return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len) { size_t actual_iv_size; if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ /* avoid buffer overflow in ctx->iv */ if (iv_len > MBEDTLS_MAX_IV_LENGTH) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN) != 0) { actual_iv_size = iv_len; } else { actual_iv_size = mbedtls_cipher_info_get_iv_size(ctx->cipher_info); /* avoid reading past the end of input buffer */ if (actual_iv_size > iv_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } } #if defined(MBEDTLS_CHACHA20_C) if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20) { /* Even though the actual_iv_size is overwritten with a correct value * of 12 from the cipher info, return an error to indicate that * the input iv_len is wrong. */ if (iv_len != 12) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (0 != mbedtls_chacha20_starts((mbedtls_chacha20_context *) ctx->cipher_ctx, iv, 0U)) { /* Initial counter value */ return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } } #if defined(MBEDTLS_CHACHAPOLY_C) if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305 && iv_len != 12) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #endif #endif #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, iv, iv_len); } #endif #if defined(MBEDTLS_CCM_C) if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int set_lengths_result; int ccm_star_mode; set_lengths_result = mbedtls_ccm_set_lengths( (mbedtls_ccm_context *) ctx->cipher_ctx, 0, 0, 0); if (set_lengths_result != 0) { return set_lengths_result; } if (ctx->operation == MBEDTLS_DECRYPT) { ccm_star_mode = MBEDTLS_CCM_STAR_DECRYPT; } else if (ctx->operation == MBEDTLS_ENCRYPT) { ccm_star_mode = MBEDTLS_CCM_STAR_ENCRYPT; } else { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return mbedtls_ccm_starts((mbedtls_ccm_context *) ctx->cipher_ctx, ccm_star_mode, iv, iv_len); } #endif if (actual_iv_size != 0) { memcpy(ctx->iv, iv, actual_iv_size); ctx->iv_size = actual_iv_size; } return 0; } int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx) { if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* We don't support resetting PSA-based * cipher contexts, yet. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ ctx->unprocessed_len = 0; return 0; } #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len) { if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return mbedtls_gcm_update_ad((mbedtls_gcm_context *) ctx->cipher_ctx, ad, ad_len); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { int result; mbedtls_chachapoly_mode_t mode; mode = (ctx->operation == MBEDTLS_ENCRYPT) ? MBEDTLS_CHACHAPOLY_ENCRYPT : MBEDTLS_CHACHAPOLY_DECRYPT; result = mbedtls_chachapoly_starts((mbedtls_chachapoly_context *) ctx->cipher_ctx, ctx->iv, mode); if (result != 0) { return result; } return mbedtls_chachapoly_update_aad((mbedtls_chachapoly_context *) ctx->cipher_ctx, ad, ad_len); } #endif return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t block_size; if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ *olen = 0; block_size = mbedtls_cipher_get_block_size(ctx); if (0 == block_size) { return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; } if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_ECB) { if (ilen != block_size) { return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } *olen = ilen; if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ecb_func(ctx->cipher_ctx, ctx->operation, input, output))) { return ret; } return 0; } #if defined(MBEDTLS_GCM_C) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_GCM) { return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx, input, ilen, output, ilen, olen); } #endif #if defined(MBEDTLS_CCM_C) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CCM_STAR_NO_TAG) { return mbedtls_ccm_update((mbedtls_ccm_context *) ctx->cipher_ctx, input, ilen, output, ilen, olen); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305) { *olen = ilen; return mbedtls_chachapoly_update((mbedtls_chachapoly_context *) ctx->cipher_ctx, ilen, input, output); } #endif if (input == output && (ctx->unprocessed_len != 0 || ilen % block_size)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_CIPHER_MODE_CBC) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CBC) { size_t copy_len = 0; /* * If there is not enough data for a full block, cache it. */ if ((ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && ilen <= block_size - ctx->unprocessed_len) || (ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && ilen < block_size - ctx->unprocessed_len) || (ctx->operation == MBEDTLS_ENCRYPT && ilen < block_size - ctx->unprocessed_len)) { memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, ilen); ctx->unprocessed_len += ilen; return 0; } /* * Process cached data first */ if (0 != ctx->unprocessed_len) { copy_len = block_size - ctx->unprocessed_len; memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, copy_len); if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx, ctx->operation, block_size, ctx->iv, ctx-> unprocessed_data, output))) { return ret; } *olen += block_size; output += block_size; ctx->unprocessed_len = 0; input += copy_len; ilen -= copy_len; } /* * Cache final, incomplete block */ if (0 != ilen) { /* Encryption: only cache partial blocks * Decryption w/ padding: always keep at least one whole block * Decryption w/o padding: only cache partial blocks */ copy_len = ilen % block_size; if (copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding) { copy_len = block_size; } memcpy(ctx->unprocessed_data, &(input[ilen - copy_len]), copy_len); ctx->unprocessed_len += copy_len; ilen -= copy_len; } /* * Process remaining full blocks */ if (ilen) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output))) { return ret; } *olen += ilen; } return 0; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CFB) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cfb_func(ctx->cipher_ctx, ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, input, output))) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_OFB) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ofb_func(ctx->cipher_ctx, ilen, &ctx->unprocessed_len, ctx->iv, input, output))) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CTR) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ctr_func(ctx->cipher_ctx, ilen, &ctx->unprocessed_len, ctx->iv, ctx->unprocessed_data, input, output))) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_XTS) { if (ctx->unprocessed_len > 0) { /* We can only process an entire data unit at a time. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } ret = mbedtls_cipher_get_base(ctx->cipher_info)->xts_func(ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output); if (ret != 0) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_MODE_STREAM) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_STREAM) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->stream_func(ctx->cipher_ctx, ilen, input, output))) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_STREAM */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) /* * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len */ static void add_pkcs_padding(unsigned char *output, size_t output_len, size_t data_len) { size_t padding_len = output_len - data_len; unsigned char i; for (i = 0; i < padding_len; i++) { output[data_len + i] = (unsigned char) padding_len; } } static int get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i, pad_idx; unsigned char padding_len; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } padding_len = input[input_len - 1]; if (padding_len == 0 || padding_len > input_len) { return MBEDTLS_ERR_CIPHER_INVALID_PADDING; } *data_len = input_len - padding_len; mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len); bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0)); /* The number of bytes checked must be independent of padding_len, * so pick input_len, which is usually 8 or 16 (one block) */ pad_idx = input_len - padding_len; for (i = 0; i < input_len; i++) { mbedtls_ct_condition_t in_padding = mbedtls_ct_uint_ge(i, pad_idx); mbedtls_ct_condition_t different = mbedtls_ct_uint_ne(input[i], padding_len); bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) /* * One and zeros padding: fill with 80 00 ... 00 */ static void add_one_and_zeros_padding(unsigned char *output, size_t output_len, size_t data_len) { size_t padding_len = output_len - data_len; unsigned char i = 0; output[data_len] = 0x80; for (i = 1; i < padding_len; i++) { output[data_len + i] = 0x00; } } static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, size_t *data_len) { if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } mbedtls_ct_condition_t in_padding = MBEDTLS_CT_TRUE; mbedtls_ct_condition_t bad = MBEDTLS_CT_TRUE; *data_len = 0; for (ptrdiff_t i = (ptrdiff_t) (input_len) - 1; i >= 0; i--) { mbedtls_ct_condition_t is_nonzero = mbedtls_ct_bool(input[i]); mbedtls_ct_condition_t hit_first_nonzero = mbedtls_ct_bool_and(is_nonzero, in_padding); *data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len); bad = mbedtls_ct_bool_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad); in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) /* * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length */ static void add_zeros_and_len_padding(unsigned char *output, size_t output_len, size_t data_len) { size_t padding_len = output_len - data_len; unsigned char i = 0; for (i = 1; i < padding_len; i++) { output[data_len + i - 1] = 0x00; } output[output_len - 1] = (unsigned char) padding_len; } static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i, pad_idx; unsigned char padding_len; mbedtls_ct_condition_t bad; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } padding_len = input[input_len - 1]; *data_len = input_len - padding_len; /* Avoid logical || since it results in a branch */ bad = mbedtls_ct_uint_gt(padding_len, input_len); bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0)); /* The number of bytes checked must be independent of padding_len */ pad_idx = input_len - padding_len; for (i = 0; i < input_len - 1; i++) { mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx); mbedtls_ct_condition_t nonzero_pad_byte; nonzero_pad_byte = mbedtls_ct_bool_if_else_0(is_padding, mbedtls_ct_bool(input[i])); bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) /* * Zero padding: fill with 00 ... 00 */ static void add_zeros_padding(unsigned char *output, size_t output_len, size_t data_len) { memset(output + data_len, 0, output_len - data_len); } static int get_zeros_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i; mbedtls_ct_condition_t done = MBEDTLS_CT_FALSE, prev_done; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } *data_len = 0; for (i = input_len; i > 0; i--) { prev_done = done; done = mbedtls_ct_bool_or(done, mbedtls_ct_uint_ne(input[i-1], 0)); *data_len = mbedtls_ct_size_if(mbedtls_ct_bool_ne(done, prev_done), i, *data_len); } return 0; } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ /* * No padding: don't pad :) * * There is no add_padding function (check for NULL in mbedtls_cipher_finish) * but a trivial get_padding function */ static int get_no_padding(unsigned char *input, size_t input_len, size_t *data_len) { if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } *data_len = input_len; return 0; } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen) { if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ *olen = 0; #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /* CBC mode requires padding so we make sure a call to * mbedtls_cipher_set_padding_mode has been done successfully. */ if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { if (ctx->get_padding == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } } #endif if (MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_XTS == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_STREAM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return 0; } if ((MBEDTLS_CIPHER_CHACHA20 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) || (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type))) { return 0; } if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { if (ctx->unprocessed_len != 0) { return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } return 0; } #if defined(MBEDTLS_CIPHER_MODE_CBC) if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int ret = 0; if (MBEDTLS_ENCRYPT == ctx->operation) { /* check for 'no padding' mode */ if (NULL == ctx->add_padding) { if (0 != ctx->unprocessed_len) { return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } return 0; } ctx->add_padding(ctx->unprocessed_data, mbedtls_cipher_get_iv_size(ctx), ctx->unprocessed_len); } else if (mbedtls_cipher_get_block_size(ctx) != ctx->unprocessed_len) { /* * For decrypt operations, expect a full block, * or an empty block if no padding */ if (NULL == ctx->add_padding && 0 == ctx->unprocessed_len) { return 0; } return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } /* cipher block */ if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx, ctx->operation, mbedtls_cipher_get_block_size( ctx), ctx->iv, ctx->unprocessed_data, output))) { return ret; } /* Set output size for decryption */ if (MBEDTLS_DECRYPT == ctx->operation) { return ctx->get_padding(output, mbedtls_cipher_get_block_size(ctx), olen); } /* Set output size for encryption */ *olen = mbedtls_cipher_get_block_size(ctx); return 0; } #else ((void) output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode) { if (NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto knows about CBC padding * schemes, we currently don't make them * accessible through the cipher layer. */ if (mode != MBEDTLS_PADDING_NONE) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ switch (mode) { #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) case MBEDTLS_PADDING_PKCS7: ctx->add_padding = add_pkcs_padding; ctx->get_padding = get_pkcs_padding; break; #endif #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) case MBEDTLS_PADDING_ONE_AND_ZEROS: ctx->add_padding = add_one_and_zeros_padding; ctx->get_padding = get_one_and_zeros_padding; break; #endif #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) case MBEDTLS_PADDING_ZEROS_AND_LEN: ctx->add_padding = add_zeros_and_len_padding; ctx->get_padding = get_zeros_and_len_padding; break; #endif #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) case MBEDTLS_PADDING_ZEROS: ctx->add_padding = add_zeros_padding; ctx->get_padding = get_zeros_padding; break; #endif case MBEDTLS_PADDING_NONE: ctx->add_padding = NULL; ctx->get_padding = get_no_padding; break; default: return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } return 0; } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len) { if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (MBEDTLS_ENCRYPT != ctx->operation) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { size_t output_length; /* The code here doesn't yet support alternative implementations * that can delay up to a block of output. */ return mbedtls_gcm_finish((mbedtls_gcm_context *) ctx->cipher_ctx, NULL, 0, &output_length, tag, tag_len); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { /* Don't allow truncated MAC for Poly1305 */ if (tag_len != 16U) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context *) ctx->cipher_ctx, tag); } #endif return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len) { unsigned char check_tag[16]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (MBEDTLS_DECRYPT != ctx->operation) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ /* Status to return on a non-authenticated algorithm. */ ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { size_t output_length; /* The code here doesn't yet support alternative implementations * that can delay up to a block of output. */ if (tag_len > sizeof(check_tag)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (0 != (ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, NULL, 0, &output_length, check_tag, tag_len))) { return ret; } /* Check the tag in "constant-time" */ if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; goto exit; } } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { /* Don't allow truncated MAC for Poly1305 */ if (tag_len != sizeof(check_tag)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context *) ctx->cipher_ctx, check_tag); if (ret != 0) { return ret; } /* Check the tag in "constant-time" */ if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; goto exit; } } #endif /* MBEDTLS_CHACHAPOLY_C */ exit: mbedtls_platform_zeroize(check_tag, tag_len); return ret; } #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /* * Packet-oriented wrapper for non-AEAD modes */ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t finish_olen; #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* As in the non-PSA case, we don't check that * a key has been set. If not, the key slot will * still be in its default state of 0, which is * guaranteed to be invalid, hence the PSA-call * below will gracefully fail. */ mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; psa_status_t status; psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; size_t part_len; if (ctx->operation == MBEDTLS_DECRYPT) { status = psa_cipher_decrypt_setup(&cipher_op, cipher_psa->slot, cipher_psa->alg); } else if (ctx->operation == MBEDTLS_ENCRYPT) { status = psa_cipher_encrypt_setup(&cipher_op, cipher_psa->slot, cipher_psa->alg); } else { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* In the following, we can immediately return on an error, * because the PSA Crypto API guarantees that cipher operations * are terminated by unsuccessful calls to psa_cipher_update(), * and by any call to psa_cipher_finish(). */ if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) != MBEDTLS_MODE_ECB) { status = psa_cipher_set_iv(&cipher_op, iv, iv_len); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } } status = psa_cipher_update(&cipher_op, input, ilen, output, ilen, olen); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } status = psa_cipher_finish(&cipher_op, output + *olen, ilen - *olen, &part_len); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } *olen += part_len; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ if ((ret = mbedtls_cipher_set_iv(ctx, iv, iv_len)) != 0) { return ret; } if ((ret = mbedtls_cipher_reset(ctx)) != 0) { return ret; } if ((ret = mbedtls_cipher_update(ctx, input, ilen, output, olen)) != 0) { return ret; } if ((ret = mbedtls_cipher_finish(ctx, output + *olen, &finish_olen)) != 0) { return ret; } *olen += finish_olen; return 0; } #if defined(MBEDTLS_CIPHER_MODE_AEAD) /* * Packet-oriented encryption for AEAD modes: internal function used by * mbedtls_cipher_auth_encrypt_ext(). */ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, unsigned char *tag, size_t tag_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* As in the non-PSA case, we don't check that * a key has been set. If not, the key slot will * still be in its default state of 0, which is * guaranteed to be invalid, hence the PSA-call * below will gracefully fail. */ mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; psa_status_t status; /* PSA Crypto API always writes the authentication tag * at the end of the encrypted message. */ if (output == NULL || tag != output + ilen) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } status = psa_aead_encrypt(cipher_psa->slot, cipher_psa->alg, iv, iv_len, ad, ad_len, input, ilen, output, ilen + tag_len, olen); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } *olen -= tag_len; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { *olen = ilen; return mbedtls_gcm_crypt_and_tag(ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, iv, iv_len, ad, ad_len, input, output, tag_len, tag); } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { *olen = ilen; return mbedtls_ccm_encrypt_and_tag(ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, input, output, tag, tag_len); } #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { /* ChachaPoly has fixed length nonce and MAC (tag) */ if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) || (tag_len != 16U)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } *olen = ilen; return mbedtls_chachapoly_encrypt_and_tag(ctx->cipher_ctx, ilen, iv, ad, ad_len, input, output, tag); } #endif /* MBEDTLS_CHACHAPOLY_C */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } /* * Packet-oriented encryption for AEAD modes: internal function used by * mbedtls_cipher_auth_encrypt_ext(). */ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, const unsigned char *tag, size_t tag_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* As in the non-PSA case, we don't check that * a key has been set. If not, the key slot will * still be in its default state of 0, which is * guaranteed to be invalid, hence the PSA-call * below will gracefully fail. */ mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; psa_status_t status; /* PSA Crypto API always writes the authentication tag * at the end of the encrypted message. */ if (input == NULL || tag != input + ilen) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } status = psa_aead_decrypt(cipher_psa->slot, cipher_psa->alg, iv, iv_len, ad, ad_len, input, ilen + tag_len, output, ilen, olen); if (status == PSA_ERROR_INVALID_SIGNATURE) { return MBEDTLS_ERR_CIPHER_AUTH_FAILED; } else if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; *olen = ilen; ret = mbedtls_gcm_auth_decrypt(ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, tag, tag_len, input, output); if (ret == MBEDTLS_ERR_GCM_AUTH_FAILED) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } return ret; } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; *olen = ilen; ret = mbedtls_ccm_auth_decrypt(ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, input, output, tag, tag_len); if (ret == MBEDTLS_ERR_CCM_AUTH_FAILED) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } return ret; } #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* ChachaPoly has fixed length nonce and MAC (tag) */ if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) || (tag_len != 16U)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } *olen = ilen; ret = mbedtls_chachapoly_auth_decrypt(ctx->cipher_ctx, ilen, iv, ad, ad_len, tag, input, output); if (ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } return ret; } #endif /* MBEDTLS_CHACHAPOLY_C */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_CIPHER_MODE_AEAD */ #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) /* * Packet-oriented encryption for AEAD/NIST_KW: public function. */ int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len) { #if defined(MBEDTLS_NIST_KW_C) if ( #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) ctx->psa_enabled == 0 && #endif (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) { mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ? MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; /* There is no iv, tag or ad associated with KW and KWP, * so these length should be 0 as documented. */ if (iv_len != 0 || tag_len != 0 || ad_len != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } (void) iv; (void) ad; return mbedtls_nist_kw_wrap(ctx->cipher_ctx, mode, input, ilen, output, olen, output_len); } #endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_CIPHER_MODE_AEAD) /* AEAD case: check length before passing on to shared function */ if (output_len < ilen + tag_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } int ret = mbedtls_cipher_aead_encrypt(ctx, iv, iv_len, ad, ad_len, input, ilen, output, olen, output + ilen, tag_len); *olen += tag_len; return ret; #else return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_CIPHER_MODE_AEAD */ } /* * Packet-oriented decryption for AEAD/NIST_KW: public function. */ int mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len) { #if defined(MBEDTLS_NIST_KW_C) if ( #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) ctx->psa_enabled == 0 && #endif (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) { mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ? MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; /* There is no iv, tag or ad associated with KW and KWP, * so these length should be 0 as documented. */ if (iv_len != 0 || tag_len != 0 || ad_len != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } (void) iv; (void) ad; return mbedtls_nist_kw_unwrap(ctx->cipher_ctx, mode, input, ilen, output, olen, output_len); } #endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_CIPHER_MODE_AEAD) /* AEAD case: check length before passing on to shared function */ if (ilen < tag_len || output_len < ilen - tag_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return mbedtls_cipher_aead_decrypt(ctx, iv, iv_len, ad, ad_len, input, ilen - tag_len, output, olen, input + ilen - tag_len, tag_len); #else return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_CIPHER_MODE_AEAD */ } #endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ #endif /* MBEDTLS_CIPHER_C */ webfakes/src/cleancall.c0000644000176200001440000001017214323222672014716 0ustar liggesusers#define R_NO_REMAP #include #include "cleancall.h" #if (defined(R_VERSION) && R_VERSION < R_Version(3, 4, 0)) SEXP R_MakeExternalPtrFn(DL_FUNC p, SEXP tag, SEXP prot) { fn_ptr ptr; ptr.fn = p; return R_MakeExternalPtr(ptr.p, tag, prot); } DL_FUNC R_ExternalPtrAddrFn(SEXP s) { fn_ptr ptr; ptr.p = R_ExternalPtrAddr(s); return ptr.fn; } #endif // The R API does not have a setter for function pointers SEXP cleancall_MakeExternalPtrFn(DL_FUNC p, SEXP tag, SEXP prot) { fn_ptr tmp; tmp.fn = p; return R_MakeExternalPtr(tmp.p, tag, prot); } void cleancall_SetExternalPtrAddrFn(SEXP s, DL_FUNC p) { fn_ptr ptr; ptr.fn = p; R_SetExternalPtrAddr(s, ptr.p); } // Initialised at load time with the `.Call` primitive SEXP cleancall_fns_dot_call = NULL; void cleancall_init(void) { cleancall_fns_dot_call = Rf_findVar(Rf_install(".Call"), R_BaseEnv); } struct eval_args { SEXP call; SEXP env; }; static SEXP eval_wrap(void* data) { struct eval_args* args = (struct eval_args*) data; return Rf_eval(args->call, args->env); } SEXP cleancall_call(SEXP args, SEXP env) { SEXP call = PROTECT(Rf_lcons(cleancall_fns_dot_call, args)); struct eval_args data = { call, env }; SEXP out = r_with_cleanup_context(&eval_wrap, &data); UNPROTECT(1); return out; } static SEXP callbacks = NULL; // Preallocate a callback static void push_callback(SEXP stack) { SEXP top = CDR(stack); SEXP early_handler = PROTECT(Rf_allocVector(LGLSXP, 1)); SEXP fn_extptr = PROTECT(cleancall_MakeExternalPtrFn(NULL, R_NilValue, R_NilValue)); SEXP data_extptr = PROTECT(R_MakeExternalPtr(NULL, early_handler, R_NilValue)); SEXP cb = Rf_cons(Rf_cons(fn_extptr, data_extptr), top); SETCDR(stack, cb); UNPROTECT(3); } struct data_wrapper { SEXP (*fn)(void* data); void *data; SEXP callbacks; int success; }; static void call_exits(void* data) { // Remove protecting node. Don't remove the preallocated callback on // the top as it might contain a handler when something went wrong. SEXP top = CDR(callbacks); // Restore old stack struct data_wrapper* state = data; callbacks = (SEXP) state->callbacks; // Handlers should not jump while (top != R_NilValue) { SEXP cb = CAR(top); top = CDR(top); void (*fn)(void*) = (void (*)(void*)) R_ExternalPtrAddrFn(CAR(cb)); void *data = (void*) R_ExternalPtrAddr(CDR(cb)); int early_handler = LOGICAL(R_ExternalPtrTag(CDR(cb)))[0]; // Check for empty pointer in preallocated callbacks if (fn) { if (!early_handler || !state->success) fn(data); } } } static SEXP with_cleanup_context_wrap(void *data) { struct data_wrapper* cdata = data; SEXP ret = cdata->fn(cdata->data); cdata->success = 1; return ret; } SEXP r_with_cleanup_context(SEXP (*fn)(void* data), void* data) { // Preallocate new stack before changing `callbacks` to avoid // leaving the global variable in a bad state if alloc fails SEXP new = PROTECT(Rf_cons(R_NilValue, R_NilValue)); push_callback(new); if (!callbacks) callbacks = R_NilValue; SEXP old = callbacks; callbacks = new; struct data_wrapper state = { fn, data, old, 0 }; SEXP out = R_ExecWithCleanup(with_cleanup_context_wrap, &state, &call_exits, &state); UNPROTECT(1); return out; } static void call_save_handler(void (*fn)(void *data), void* data, int early) { if (!callbacks) { fn(data); Rf_error("Internal error: Exit handler pushed outside " "of an exit context"); } SEXP cb = CADR(callbacks); // Update pointers cleancall_SetExternalPtrAddrFn(CAR(cb), (DL_FUNC) fn); R_SetExternalPtrAddr(CDR(cb), data); LOGICAL(R_ExternalPtrTag(CDR(cb)))[0] = early; // Preallocate the next callback in case the allocator jumps push_callback(callbacks); } void r_call_on_exit(void (*fn)(void* data), void* data) { call_save_handler(fn, data, /* early = */ 0); } void r_call_on_early_exit(void (*fn)(void* data), void* data) { call_save_handler(fn, data, /* early = */ 1); } webfakes/NAMESPACE0000644000176200001440000000164214740243712013267 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(format,webfakes_app) S3method(format,webfakes_app_process) S3method(format,webfakes_regexp) S3method(format,webfakes_request) S3method(format,webfakes_response) S3method(print,webfakes_app) S3method(print,webfakes_app_process) S3method(print,webfakes_regexp) S3method(print,webfakes_request) S3method(print,webfakes_response) export(git_app) export(http_time_stamp) export(httpbin_app) export(local_app_process) export(mw_cgi) export(mw_cookie_parser) export(mw_etag) export(mw_json) export(mw_log) export(mw_multipart) export(mw_range_parser) export(mw_raw) export(mw_static) export(mw_text) export(mw_urlencoded) export(new_app) export(new_app_process) export(new_regexp) export(oauth2_httr_login) export(oauth2_login) export(oauth2_resource_app) export(oauth2_third_party_app) export(server_opts) export(tmpl_glue) useDynLib(webfakes, .registration = TRUE, .fixes = "c_") webfakes/LICENSE0000644000176200001440000000005615026556433013060 0ustar liggesusersYEAR: 2025 COPYRIGHT HOLDER: webfakes authors webfakes/NEWS.md0000644000176200001440000000504615026562777013165 0ustar liggesusers# webfakes 1.4.0 * webfakes now supports HTTPS (#110). * The cleanup of a `new_app_process()` (and thus `local_app_process()`) is now faster. Instead of sending an interrupt first and waiting for the subprocess to quite, it is killed instantly. # webfakes 1.3.2 * New server option: `decode_url`. If set to `FALSE`, then the web server will not URL-decode the URL (#106). # webfakes 1.3.1 No changes. # webfakes 1.3.0 * New `git_app()` app to fake a git HTTP server. See the webfakes test cases for examples. * New `mw_cgi()` middleware to call CGI scripts. See the new `git_app()` for an example. # webfakes 1.2.1 * `tmpl_glue()` now works correctly on platforms with an issue in `readChar(..., useBytes = TRUE)`, e.g. on macOS 14.x Sonoma: . # webfakes 1.2.0 * The httpbin app now implements the `/brotli`, `/deflate`, `/digest-auth` `/forms/post`, `/hidden-basic-auth`, `/range/:n`, `/stream/:n`, `/cache` and `/cache/:value` endpoints. With these, it implements all endpoint of the original Python httpbin app (#3). * New middleware `mw_cookie_parser()` to parse a `Cookie` header. Relatedly, new `response$add_cookie()` and `response$clear_cookie()` methods to add a cookie to a response and to add a header that clears a cookie (#2). * Parsing query parametes without a value now does not fail. * New utility function `http_time_stamp()` to format a time stamp for HTTP. * The httpbin app now implements the endpoints related to cookies (#3). * The httpbin app now sends the `Date` header in the correct format. * The `offset` parameter is now optional in the `/links` endpoint of the httpbin app. * `mw_etag()` now does not add an `ETag` header to the response, if there is one already. (The comparision is case sensitive.) * New middleware: `mw_range_parser()` to parse `Range` headers. # webfakes 1.1.7 * No user visible changes. # webfakes 1.1.6 * `response$send_file()` now handles `root = "/"` and absolute paths better on Windows. * `new_app_process()` and `local_app_process()` are now faster, because the app object they need to copy to the subprocess is smaller. # webfakes 1.1.5 * `mw_etag()` now handles the `If-None-Match` header properly, and sets the status code of the response to 304, and removes the response body. # webfakes 1.1.4 * No user visible changes. # webfakes 1.1.3 * webfakes now compiles on older macOS versions, hopefully really. # webfakes 1.1.2 * webfakes now compiles on older macOS versions (before 10.12). # 1.1.1 First release on CRAN webfakes/inst/0000755000176200001440000000000014740737023013025 5ustar liggesuserswebfakes/inst/views/0000755000176200001440000000000014172041777014165 5ustar liggesuserswebfakes/inst/views/authorize.html0000644000176200001440000000072314172041777017067 0ustar liggesusers Webfakes OAuth 2.0 resource server

Would you authorize "{app}" to access your account?

webfakes/inst/credits/0000755000176200001440000000000014172041777014465 5ustar liggesuserswebfakes/inst/credits/ciwetweb.md0000644000176200001440000000750214172041777016624 0ustar liggesusers This is from https://github.com/civetweb/civetweb/blob/master/CREDITS.md # Civetweb Contributors * Abhishek Lekshmanan * Abramo Bagnara * Adam Bailey * Alan Somers * Alberto Bignotti * Alex Kozlov * AndreyArsov * Anton Te * beaver * bel2125 * Ben M. Ward * Bernhard Lehner * BigJoe * Bjoern Petri * Braedy Kuzma * Breno Ramalho Lemes * brett * Brian Lambert * Brian Spratke * cdbishop * celeron55 * Charles Olivi * Chris Han * Chris Jones * Chris Rehn * Christian Mauderer * Christopher Galas * cjh * Colden Cullen * Colm Sloan * Cortronic * Daniel Oaks * Daniel Rempel * Danny Al-Gaaf * Dave Brower * daveelton * David Arnold * David Loffredo * Dialga * Domenico Di Iorio * Drew Wells * duong2179 * ehlertjd * eugene * Eric Tsau * Erick Vieyra * Erik Beran * Erik Partridge * extergnoto * F-Secure Corporation * Fabrice Fontaine * feneuilflo * Fernando G. Aranda * Frank Hilliger * Grahack * Gregor Jasny * grenclave * grunk * guangqing.chen * Guilherme Amadio * hansipie * HariKamath Kamath * Henry Chang * Herumb Shandilya * Herve Codina * Iain Morton * ImgBotApp * Ivan Dlugos * Jack * Jacob Repp * Jacob Skillin * Jan Kowalewski * Jan Willem Janssen * Jeremy Lin * Jesse Williamson * Jim Evans * jmc- * Joakim L. Gilje * Jochen Scheib * Joe Mucchiello * Joel Gallant * Johan De Taeye * John Faith * Jordan * Jordan Shelley * Joshua Boyd * Joshua D. Boyd * k-mds * kakwa * kalphamon * Karol Mroz * Keith Holman * Keith Kyzivat * Ken Walters * Kevin Branigan * Kevin Wojniak * Khem Raj * Kimmo Mustonen * Krzysztof Kozlowski * Lammert Bies * Lars Immisch * Lawrence * Li Peng * Lianghui * Luka Rahne * Lukas Martanovic * Maarten Fremouw * makrsmark * marco * Mark Lakata * Martin Gaida * Mateusz Gralka * Matt Clarkson * Mellnik * Mike Crowe * mingodad * Morgan McGuire * mrdvlpr.xnu * Nat! * Neil Jensen * newsoft * nfrmtkr * Nick Hildebrant * Nigel Stewart * nihildeb * No Face Press * palortoff * Patrick Drechsler * Patrick Trinkle * Paul Sokolovsky * Paulo Brizolara * pavel.pimenov * PavelVozenilek * Perttu Ahola * Peter Foerster * Philipp Friedenberger * Philipp Hasper * Piotr Zierhoffer * pkvamme * Radoslaw Zarzynski * Red54 * Retallack Mark mark.retallack * Richard Screene * Rimas Misevi-ìius * Rinat Dobrokhotov * ryankopf * Sage Weil * Sangwhan Moon * Saumitra Vikram * Scott Nations * Sebastien Jodogne * Sergey Linev * sgmesservey * shantanugadgil * Sherwyn Sen * shreyajaggi8 * Simon Hailes * slidertom * SpaceLord * sunfch * suzukibitman * Símal Rasmussen * Tamotsu Kanoh * thewaterymoon * Thiago Macedo * THILMANT, Bernard * Thomas Davis * Thomas Klausner * Thorsten Horstmann * tnoho * Tom Deblauwe * Tomas Andrle * Tomasz Gorochowik * Toni Wilk * Torben Jonas * Uilian Ries * Ulrich Hertlein * Walt Steverson * wangli28 * webxer * William Greathouse * xeoshow * xtne6f * Yehuda Sadeh * Yury Z * zhen.wang and others. # Mongoose Contributors CivetWeb is based on the Mongoose code. The following users contributed to the original Mongoose release between 2010 and 2013. This list was generated from the Mongoose GIT logs. It does not contain contributions from the Mongoose mailing list. There is no record for contributors prior to 2010. * Sergey Lyubka * Arnout Vandecappelle (Essensium/Mind) * Benoît Amiaux * Cody Hanson * Colin Leitner * Daniel Oaks * Eric Bakan * Erik Oomen * Filipp Kovalev * Ger Hobbelt * Hendrik Polczynski * Henrique Mendonça * Igor Okulist * Jay * Joe Mucchiello * John Safranek * Joseph Mainwaring * José Miguel Gonçalves * KIU Shueng Chuan * Katerina Blinova * Konstantin Sorokin * Marin Atanasov Nikolov * Matt Healy * Miguel Morales * Mikhail Nikalyukin * MikieMorales * Mitch Hendrickson * Nigel Stewart * Pavel * Pavel Khlebovich * Rogerz Zhang * Sebastian Reinhard * Stefan Doehla * Thileepan * abadc0de * arvidn * bick * ff.feng * jmucchiello * jwang * lsm * migal * mlamb * nullable.type * shantanugadgil * tayS * test * valenok webfakes/inst/credits/redoc.md0000644000176200001440000001333414172041777016107 0ustar liggesusers See https://github.com/Redocly/redoc#readme for Redoc. Redoc authors: * Roman Hotsiy * Cesar * Dimitar Nanov * Ivan Goncharov * Anya Stasiuk * Bohdan Khorolets * Brendan Abbott * Ben Firshman * brushmate * Adam Altman * Jérémy Derussé * Matthias Mohr * Mike Stead * kedashoe * leoliu * amanganiello * Patrick Elam <40776618+patrickelam@users.noreply.github.com> * Mohamed Zenadi * Sergey Dubovyk * Zakary Kamal Ismail * Jon Nicholson * Alex * TATSUNO Yasuhiro * Oleksiy Kachynskyy * Mike Ralphson * Phil Sturgeon * Dimitar Nanov * Faheem Abrar * Fredrik Lengstrand <10126466+fredriklengstrand@users.noreply.github.com> * Gaurav Jain * George Wilson * GreenHedgehog * Homa Wong * Ingo Claro * Jacob Baskin * Jean-Daniel * Joe Honzawa * Josh Price * Julian <2564520+julmuell@users.noreply.github.com> * Julian Kühnel * Julien Feltesse * Khoa Tran * Kris Kalavantavanich * Kryštof Korb * LeFnord * Leonard Ehrenfried * Lev Pachmanov <31389480+levpachmanov@users.noreply.github.com> * Luciano Jr * Luigi Pinca * Making GitHub Delicious * Marius Rumpf * Mason Malone * Mathias Schreck * Melvyn Sopacua <40824897+mes3yd@users.noreply.github.com> * Melvyn Sopacua * Michael Huynh <43751307+miqh@users.noreply.github.com> * Morgan Terry * Nan Yan <625518543@qq.com> * Nick Oliver * Oleg Vaskevich * Patrick Niklaus * Patrick Rodacker * Pete Nykänen * Peter Golm * Peter Wessels * Petr Flaks * Primož Pincolič * Quinn Blenkinsop * Robert DeRose * Sander van de Graaf * Sebastián Ramírez * Sergio Regueira * SeungWoon Maz Lee * Sheila Kelly <36901025+viralanomaly@users.noreply.github.com> * Siarhei Bautrukevich * Skyler Lewis * SoftBrix * Sérgio Ramos * Tim Hordern * Vincent Giersch * Vladimir L * William Boman * Zach Pomerantz * bwjohnson-ss <41123899+bwjohnson-ss@users.noreply.github.com> * davchen51 <46250804+davchen51@users.noreply.github.com> * duxiaofeng * fritz-c * jsmartfo * kmbenitez * lrobledo * lscholten * mknoszlig * neumond * pengfluf * russellrobinson * tomjankes * torbenw * travis@localhost * unarist * zhzxang * Adam Altman * Adam DuVander * Adrien Gallou * Aleksandr Karo * Alex Scammon * Anastasiya Mashoshyna * Andrew Berry * Andrew Zhukevych <34597767+Hollister009@users.noreply.github.com> * Andrii Tykhan * Antherkiv * Anthony Porthouse * Anto * Anton Komarev <1849174+antonkomarev@users.noreply.github.com> * Benny Neugebauer * Blake Erickson * Brendan Abbott * Cesar Landeros Delgado * Cesar Level * Chris Faulkner * Cédric Bertolini <41571181+wizacedric@users.noreply.github.com> * Cédric Fabianski * Daniel Chao * Dave Oram * David Beacham * David Cumps * David J. Felix * David Revay * DeBr0glie The authors were extracted from the git history: ```sh git clone https://github.com/Redocly/redoc.git cd redoc git shortlog --summary --numbered --email --all | cut -f2 | sed 's/^/* /' ``` webfakes/inst/examples/0000755000176200001440000000000014172041777014646 5ustar liggesuserswebfakes/inst/examples/hello/0000755000176200001440000000000015026556433015750 5ustar liggesuserswebfakes/inst/examples/hello/views/0000755000176200001440000000000014172041777017106 5ustar liggesuserswebfakes/inst/examples/hello/views/test.txt0000644000176200001440000000003114172041777020620 0ustar liggesusersThis is {2-1} glue test! webfakes/inst/examples/hello/app.R0000644000176200001440000000067215026556433016660 0ustar liggesuserslibrary(webfakes) app <- new_app() app$engine("txt", tmpl_glue()) app$use(mw_log()) app$get("/hello", function(req, res) { res$send("Hello there!") }) app$get(new_regexp("^/hi(/.*)?$"), function(req, res) { res$send("Hi indeed!") }) app$post("/hello", function(req, res) { res$send("Got it, thanks!") }) app$get("/view", function(req, res) { txt <- res$render("test") res$set_type("text/plain")$send(txt) }) app$listen(3000L) webfakes/inst/examples/httpbin/0000755000176200001440000000000015026556433016315 5ustar liggesuserswebfakes/inst/examples/httpbin/assets/0000755000176200001440000000000014740243712017612 5ustar liggesuserswebfakes/inst/examples/httpbin/assets/httpbin.html0000644000176200001440000127130614740243712022162 0ustar liggesusers webfakes::httpbin_app() API

webfakes::httpbin_app() API (1.0.0)

Download OpenAPI specification:Download

This is a webfakes web app for HTTP testing in R packages. It implements the https://httpbin.org API

HTTP methods

GET request

An endpoint to make a GET request agains. It returns the request's parameters and the request headers, in JSON.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "headers": { },
  • "origin": "string",
  • "path": "string",
  • "url": "string"
}

DELETE request

Endpoint to make DELETE requests againts.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

PATCH request

Endpoint to make PATCH requests against.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

POST request

Endpoints to make a POST request against.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

PUT request

Endpoints to make a PUT request against.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

Auth

Basic authentication.

Basic authentication with specified user and password

path Parameters
user
required
string

User name.

password
required
string

Password.

header Parameters
Authorization
string

Base64 encoded user name and password. See https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side for the protocol.

Responses

Response samples

Content type
application/json
{
  • "authenticated": true,
  • "user": "Aladdin"
}

Hidden basic authentication.

Basic authentication with specified user and password. This is the same as /basic-auth, but it returns a 404 if no authentication is supplied or the authentication fails.

path Parameters
user
required
string

User name.

password
required
string

Password.

header Parameters
Authorization
string

Base64 encoded user name and password. See https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side for the protocol.

Responses

Response samples

Content type
application/json
{
  • "authenticated": true,
  • "user": "Aladdin"
}

Digest authentication.

Digest authentication with specified user and password

path Parameters
qop
required
string

Quality of protection, possible values are auth and auth-int.

user
required
string

User name.

passwd
required
string

Password.

query Parameters
require_cookie
any

Whether to require cookie handling for a successful authentication. Set to 1, 'tortrue` to require cookies.

header Parameters
Authorization
string

Digest authentication header. See https://en.wikipedia.org/wiki/Digest_access_authentication for the details.

Responses

Response samples

Content type
application/json
{
  • "authenticated": true,
  • "user": "Aladdin"
}

Digest authentication algorithms.

Digest authentication with specified user and password, and algorithm.

path Parameters
qop
required
string

Quality of protection, possible values are auth and auth-int.

user
required
string

User name.

passwd
required
string

Password.

algorithm
required
string

Hashing algorithm to use: MD5, SHA-256 or SHA-512.

query Parameters
require_cookie
any

Whether to require cookie handling for a successful authentication. Set to 1, 'tortrue` to require cookies.

header Parameters
Authorization
string

Digest authentication header. See https://en.wikipedia.org/wiki/Digest_access_authentication for the details.

Responses

Response samples

Content type
application/json
{
  • "authenticated": true,
  • "user": "Aladdin"
}

Digest authentication, stale after.

Digest authentication with specified user, password and algorithm, with a stale_after value.

path Parameters
qop
required
string

Quality of protection, possible values are auth and auth-int.

user
required
string

User name.

passwd
required
string

Password.

algorithm
required
string

Hashing algorithm to use: MD5, SHA-256 or SHA-512.

stale_after
required
string

How many requests are allowed. This is stored in a cookie.

query Parameters
require_cookie
any

Whether to require cookie handling for a successful authentication. Set to 1, 'tortrue` to require cookies.

header Parameters
Authorization
string

Digest authentication header. See https://en.wikipedia.org/wiki/Digest_access_authentication for the details.

Responses

Response samples

Content type
application/json
{
  • "authenticated": true,
  • "user": "Aladdin"
}

Bearer authentication.

Checks is that a token is supplied in the Authorization header.

header Parameters
Authorization
string^Bearer

Responses

Response samples

Content type
application/json
{
  • "authenticated": true,
  • "token": "string"
}

Status codes

Return the specified HTTP status code, works for all HTTP verbs.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT. See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes for more about status codes.

path Parameters
status
required
integer

Status code.

Responses

Return the specified HTTP status code, works for all HTTP verbs.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT. See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes for more about status codes.

path Parameters
status
required
integer

Status code.

Responses

Return the specified HTTP status code, works for all HTTP verbs.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT. See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes for more about status codes.

path Parameters
status
required
integer

Status code.

Responses

Return the specified HTTP status code, works for all HTTP verbs.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT. See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes for more about status codes.

path Parameters
status
required
integer

Status code.

Responses

Return the specified HTTP status code, works for all HTTP verbs.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT. See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes for more about status codes.

path Parameters
status
required
integer

Status code.

Responses

Request inspection

HTTP request headers.

Responses

Response samples

Content type
application/json
{
  • "headers": { }
}

IP address of the client.

Responses

Response samples

Content type
application/json
{
  • "origin": "string"
}

The client's user agent.

Responses

Response samples

Content type
application/json
{
  • "user-agent": "string"
}

Response inspection

Caching

Returns a 304 if an If-Modified-Since header or If-None-Match is present. Returns the same as a GET otherwise.

header Parameters
If-Modified-Since
any
If-None-Match
any

Responses

Cache control.

Sets a Cache-Control header for n seconds.

path Parameters
value
integer

Responses

Work with ETags.

Assumes the specified etag parameter as the ETag header.

  • If a matching tag is supplied in the If-None-Match header, then it returns with HTTP status code 304.
  • If a non-matching If-Match header is supplied, then it return with HTTP status code 412.
  • Otherwise it returns with a JSON body and status 200.

See https://en.wikipedia.org/wiki/HTTP_ETag for more about ETag headers.

path Parameters
etag
required
string

Assumed ETag value.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "headers": { },
  • "origin": "string",
  • "path": "string",
  • "url": "string"
}

Set response headers.

Set response headers from the passed query parameters. The same parameter migth be specified multiple times to create the same HTTP header multiple times.

query Parameters
object

Responses

Response samples

Content type
application/json
{ }

Set response headers.

Set response headers from the passed query parameters. The same parameter migth be specified multiple times to create the same HTTP header multiple times.

query Parameters
object

Responses

Response samples

Content type
application/json
{ }

Response formats

A simple page that is denied for robots.

This exists in conjunction with /robots.txt which disallows this page.

Responses

Send gzip encoded data.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

Deflated data.

Returns Deflate-encoded data. This needs the zip R package.

brotli compression

Returns brotli-encoded data. This needs the brotli R package.

Send UTF-8 enconded data.

Responses

Send an HTML page.

Responses

Send a JSON document.

Responses

Response samples

Content type
application/json
{ }

Send example `robots.txt` rules.

It will not allow the /deny endpoint.

Responses

Send an XML document.

Responses

Dynamic data

Base64 decoder

Base64 decode the supplied value and echo it back.

path Parameters
value
required
string

Assumed ETag value.

Responses

Random bytes.

path Parameters
n
required
integer

Number of bytes, maximum 10000.

Responses

Delayed response.

Wait for the specified number of seconds before sending the response.

path Parameters
secs
required
number

Number of seconds, fractions are supported.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

Drip bytes

Drip the specified number of bytes over the specified number of seconds, potentially after some initial delay.

query Parameters
duration
number
Default: 2

Number of seconds for the whole response.

numbytes
integer
Default: 10

Number of bytes to return.

code
integer
Default: 200

HTTP status code to return with.

delay
number
Default: 0

Initial delay, in seconds. Zero means no delay.

Responses

Links

Generate a page containing n links to other pages which do the same.

path Parameters
n
required
integer

Number of links.

offset
integer

Id of the page to return, out of n.

Responses

Stream JSON chunks.

Stream n JSON responses, each terminated by a newline character.

path Parameters
n
required
integer

Number of JSON chunks to send.

Responses

Stream in chunks.

Streams n random bytes generated with given seed, at given chunk size per packet.

path Parameters
n
required
integer

Number of bytes, maximum 102400.

query Parameters
seed
number
Default: 42

Random seed.

chunk-size
integer
Default: 10240

Size of a chunked for the chunked encoding. The last chunk migh be shorter than his.

Responses

Range requests.

Send only part of the response, after a Range header.

path Parameters
n
required
integer

Number of bytes, maximum 102400.

query Parameters
chunk_size
number
Default: 10240

Chunk size, if duration is not 0.

duration
number
Default: 0

Duration for the total response. It applies to the full response size without ranges.

Responses

Range requests..

path Parameters
n
required
integer

Number of bytes, maximum 102400.

query Parameters
chunk_size
number
Default: 10240

Chunk size, if duration is not 0.

duration
number
Default: 0

Duration for the total response. It applies to the full response size without ranges.

Responses

Random UUID.

It is pseudo-random, and not secure.

Responses

Response samples

Content type
application/json
{
  • "uuid": "ee4610df-3b7b-4624-8ce9-da6975b3e9f1"
}

Cookies

Cookie data.

Returns cookie data.

Responses

Response samples

Content type
application/json
{
  • "cookies": { }
}

Delete cookies.

Deletes cookie(s) as provided by the query string and redirects to cookie list.

query Parameters
freeform
any

Responses

Set cookies.

Sets cookie(s) as provided by the query string and redirects to cookie list.

query Parameters
freeform
any

Responses

Set one cookie.

Sets a cookie and redirects to cookie list.

path Parameters
name
string

Cookie name.

value
string

Cookie value.

Responses

Images

Return an image.

It selects the format according to the Accept request header. Supported formats: image/jpeg, image/png, image/svg+xml, image/webp, image/*.

header Parameters
Accept
string

Accepted image content type.

Responses

Response samples

Content type
application/json
{
  • "message": "Client did not request a supported media type.",
  • "accept": [
    ]
}

Return an image of the specified format.

path Parameters
format
required
string

Image format. May be jpeg, png, svg or webp.

Responses

Redirects

Redirect to an absolute URL, n times.

path Parameters
n
required
integer

Number of times to redirect. Maximum is five.

Responses

Redirect to a relative URL, n times.

path Parameters
n
required
integer

Number of times to redirect. Maximum is five.

Responses

Redirect to an URL.

See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection for details. This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

query Parameters
url
string

URL to redirect to.

status_code
integer
Default: 302

HTTP status code to use for the redirection.

Responses

Redirect to an URL.

See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection for details. This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

query Parameters
url
string

URL to redirect to.

status_code
integer
Default: 302

HTTP status code to use for the redirection.

Responses

Redirect to an URL.

See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection for details. This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

query Parameters
url
string

URL to redirect to.

status_code
integer
Default: 302

HTTP status code to use for the redirection.

Responses

Redirect to an URL.

See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection for details. This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

query Parameters
url
string

URL to redirect to.

status_code
integer
Default: 302

HTTP status code to use for the redirection.

Responses

Redirect to an URL.

See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection for details. This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

query Parameters
url
string

URL to redirect to.

status_code
integer
Default: 302

HTTP status code to use for the redirection.

Responses

Anything

Returns anything passed in request data.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

Returns anything passed in request data.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

Returns anything passed in request data.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

Returns anything passed in request data.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}

Returns anything passed in request data.

This endpoint works for these other HTTP verbs as well, the same way as for GET: CONNECT, DELETE, HEAD, MKCOL, OPTIONS, PATCH, POST, PROPFIND, PUT, REPORT.

Responses

Response samples

Content type
application/json
{
  • "args": { },
  • "data": { },
  • "files": { },
  • "form": { },
  • "headers": { },
  • "json": { },
  • "method": "string",
  • "path": "string",
  • "origin": "string",
  • "url": "string"
}
webfakes/inst/examples/httpbin/assets/forms-post.html0000644000176200001440000000256614740243712022622 0ustar liggesusers

Pizza Size

Pizza Toppings

webfakes/inst/examples/httpbin/openapi.yaml0000644000176200001440000012330514740243712020633 0ustar liggesusersopenapi: 3.0.0 info: title: webfakes::httpbin_app() API version: 1.0.0 contact: email: csardi.gabor@gmail.com license: name: The MIT License url: 'https://opensource.org/licenses/MIT' description: | This is a webfakes web app for HTTP testing in R packages. It implements the https://httpbin.org API paths: /get: get: tags: - HTTP methods summary: GET request description: | An endpoint to make a GET request agains. It returns the request's parameters and the request headers, in JSON. responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/get' /delete: delete: tags: - HTTP methods summary: DELETE request description: | Endpoint to make DELETE requests againts. responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/common' /patch: patch: tags: - HTTP methods summary: PATCH request description: | Endpoint to make PATCH requests against. responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/common' /post: post: tags: - HTTP methods summary: POST request description: | Endpoints to make a POST request against. responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/common' /put: put: tags: - HTTP methods summary: PUT request description: | Endpoints to make a PUT request against. responses: '200': description: Success. content: application/json: schema: $ref: '#/components/schemas/common' '/basic-auth/:user/:password': parameters: - name: user in: path required: true description: User name. schema: type: string - name: password in: path required: true description: Password. schema: type: string - name: Authorization in: header schema: type: string description: | Base64 encoded user name and password. See for the protocol. get: tags: - Auth summary: Basic authentication. description: | Basic authentication with specified user and password responses: '200': description: Success. content: application/json: schema: type: object properties: authenticated: type: boolean user: type: string example: "Aladdin" '401': description: Failed authentication. headers: WWW-Authenticate: description: Contains the authentication realm. schema: type: string pattern: '^Basic realm=".*"' '/hidden-basic-auth/:user/:password': parameters: - name: user in: path required: true description: User name. schema: type: string - name: password in: path required: true description: Password. schema: type: string - name: Authorization in: header schema: type: string description: | Base64 encoded user name and password. See for the protocol. get: tags: - Auth summary: Hidden basic authentication. description: | Basic authentication with specified user and password. This is the same as `/basic-auth`, but it returns a 404 if no authentication is supplied or the authentication fails. responses: '200': description: Success. content: application/json: schema: type: object properties: authenticated: type: boolean user: type: string example: "Aladdin" '404': description: Failed authentication. '/digest-auth/:qop/:user/:passwd': parameters: - name: qop in: path required: true description: Quality of protection, possible values are `auth` and `auth-int`. schema: type: string - name: user in: path required: true description: User name. schema: type: string - name: passwd in: path required: true description: Password. schema: type: string - name: require_cookie in: query required: false description: | Whether to require cookie handling for a successful authentication. Set to `1`, 't` or `true` to require cookies. scheme: type: string - name: Authorization in: header schema: type: string description: | Digest authentication header. See https://en.wikipedia.org/wiki/Digest_access_authentication for the details. get: tags: - Auth summary: Digest authentication. description: | Digest authentication with specified user and password responses: '200': description: Success. content: application/json: schema: type: object properties: authenticated: type: boolean user: type: string example: "Aladdin" '401': description: Failed authentication. '/digest-auth/:qop/:user/:passwd/:algorithm': parameters: - name: qop in: path required: true description: Quality of protection, possible values are `auth` and `auth-int`. schema: type: string - name: user in: path required: true description: User name. schema: type: string - name: passwd in: path required: true description: Password. schema: type: string - name: algorithm in: path required: true description: | Hashing algorithm to use: `MD5`, `SHA-256` or `SHA-512`. schema: type: string default: MD5 - name: require_cookie in: query required: false description: | Whether to require cookie handling for a successful authentication. Set to `1`, 't` or `true` to require cookies. scheme: type: string - name: Authorization in: header schema: type: string description: | Digest authentication header. See https://en.wikipedia.org/wiki/Digest_access_authentication for the details. get: tags: - Auth summary: Digest authentication algorithms. description: | Digest authentication with specified user and password, and algorithm. responses: '200': description: Success. content: application/json: schema: type: object properties: authenticated: type: boolean user: type: string example: "Aladdin" '401': description: Failed authentication. '/digest-auth/:qop/:user/:passwd/:algorithm/:stale_after': parameters: - name: qop in: path required: true description: Quality of protection, possible values are `auth` and `auth-int`. schema: type: string - name: user in: path required: true description: User name. schema: type: string - name: passwd in: path required: true description: Password. schema: type: string - name: algorithm in: path required: true description: | Hashing algorithm to use: `MD5`, `SHA-256` or `SHA-512`. schema: type: string default: MD5 - name: stale_after in: path required: true description: | How many requests are allowed. This is stored in a cookie. schema: type: string default: 'never' - name: require_cookie in: query required: false description: | Whether to require cookie handling for a successful authentication. Set to `1`, 't` or `true` to require cookies. scheme: type: string - name: Authorization in: header schema: type: string description: | Digest authentication header. See https://en.wikipedia.org/wiki/Digest_access_authentication for the details. get: tags: - Auth summary: Digest authentication, stale after. description: | Digest authentication with specified user, password and algorithm, with a stale_after value. responses: '200': description: Success. content: application/json: schema: type: object properties: authenticated: type: boolean user: type: string example: "Aladdin" '401': description: Failed authentication. '/bearer': parameters: - name: Authorization in: header schema: type: string pattern: '^Bearer ' get: tags: - Auth summary: Bearer authentication. description: | Checks is that a token is supplied in the `Authorization` header. responses: '200': description: Success. content: application/json: schema: type: object properties: authenticated: type: boolean token: type: string '401': description: Failed authentication. headers: WWW-Authenticate: description: Contains the authentication realm. schema: type: string pattern: '^bearer$' '/status/:status': parameters: - $ref: '#/components/parameters/status' delete: tags: - Status codes summary: Return the specified HTTP status code, works for all HTTP verbs. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. See for more about status codes. responses: '100': description: Informational responses. '200': description: Success. '300': description: Redirection. '400': description: Client errors. '500': description: Server errors. get: tags: - Status codes summary: Return the specified HTTP status code, works for all HTTP verbs. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. See for more about status codes. responses: '100': description: Informational responses. '200': description: Success. '300': description: Redirection. '400': description: Client errors. '500': description: Server errors. patch: tags: - Status codes summary: Return the specified HTTP status code, works for all HTTP verbs. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. See for more about status codes. responses: '100': description: Informational responses. '200': description: Success. '300': description: Redirection. '400': description: Client errors. '500': description: Server errors. post: tags: - Status codes summary: Return the specified HTTP status code, works for all HTTP verbs. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. See for more about status codes. responses: '100': description: Informational responses. '200': description: Success. '300': description: Redirection. '400': description: Client errors. '500': description: Server errors. put: tags: - Status codes summary: Return the specified HTTP status code, works for all HTTP verbs. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. See for more about status codes. responses: '100': description: Informational responses. '200': description: Success. '300': description: Redirection. '400': description: Client errors. '500': description: Server errors. '/headers': get: tags: - Request inspection summary: HTTP request headers. responses: '200': description: The requests's HTTP headers. content: application/json: schema: type: object properties: headers: type: object '/ip': get: tags: - Request inspection summary: IP address of the client. responses: '200': description: | The IP address of the client, usually `127.0.0.1`, as the webfakes server runs on the localhost. content: application/json: schema: type: object properties: origin: type: string '/user-agent': get: tags: - Request inspection summary: The client's user agent. responses: '200': description: The content of the `User-Agent` HTTP request header. content: application/json: schema: type: object properties: 'user-agent': type: string '/cache': parameters: - name: If-Modified-Since in: header - name: If-None-Match in: header get: tags: - Response inspection summary: Caching description: | Returns a 304 if an `If-Modified-Since` header or `If-None-Match` is present. Returns the same as a GET otherwise. responses: '200': description: Cached response. content: application/json: $ref: '#/components/schemas/get' '304': description: Modified. '/cache/:value': parameters: - name: value in: path schema: type: integer get: tags: - Response inspection summary: Cache control. description: | Sets a `Cache-Control` header for n seconds. responses: '200': description: Cache control set. content: application/json: $ref: '#/components/schemas/get' '/etag/:etag': parameters: - name: etag in: path required: true description: Assumed ETag value. schema: type: string get: tags: - Response inspection summary: Work with ETags. description: | Assumes the specified `etag` parameter as the `ETag` header. * If a matching tag is supplied in the `If-None-Match` header, then it returns with HTTP status code 304. * If a non-matching `If-Match` header is supplied, then it return with HTTP status code 412. * Otherwise it returns with a JSON body and status 200. See for more about `ETag` headers. responses: '200': description: | Non-matching `If-Non-Match` or matching `If-Match`, or no such headers at all. content: application/json: schema: $ref: '#/components/schemas/get' headers: ETag: description: The supplied `etag` value. schema: type: string '304': description: | Matching `If-Non-Match` header. '412': description: | Non-matchinf `If-Match` header. '/response-headers': parameters: - in: query name: params schema: type: object additionalProperties: type: string get: tags: - Response inspection summary: Set response headers. description: | Set response headers from the passed query parameters. The same parameter migth be specified multiple times to create the same HTTP header multiple times. responses: '200': description: | The passed query parameters are also returned as a JSON response. content: application/json: schema: type: object post: tags: - Response inspection summary: Set response headers. description: | Set response headers from the passed query parameters. The same parameter migth be specified multiple times to create the same HTTP header multiple times. responses: '200': description: | The passed query parameters are also returned as a JSON response. content: application/json: schema: type: object '/deny': get: tags: - Response formats summary: A simple page that is denied for robots. description: | This exists in conjunction with `/robots.txt` which disallows this page. responses: '200': description: A simple page. content: text/plain: schema: type: string example: 'Example content.' '/gzip': get: tags: - Response formats summary: Send gzip encoded data. responses: '200': description: Some gzipped JSON. content: application/json: schema: $ref: '#/components/schemas/common' headers: 'Content-Encoding': description: Set to `gzip`. schema: type: string pattern: '^gzip$' '/deflate': get: tags: - Response formats summary: Deflated data. description: | Returns Deflate-encoded data. This needs the zip R package. content: application/json: schema: $ref: '#/components/schemas/common' headers: 'Content-Encoding': description: Set to `deflate`. schema: type: string pattern: '^deflate$' '/brotli': get: tags: - Response formats summary: brotli compression description: | Returns brotli-encoded data. This needs the brotli R package. content: application/json: schema: $ref: '#/components/schemas/common' headers: 'Content-Encoding': description: Set to `brotli`. schema: type: string pattern: '^brotli' '/encoding/utf8': get: tags: - Response formats summary: Send UTF-8 enconded data. responses: '200': description: HTML with a lot of UTF-8. content: text/html: schema: type: string headers: 'Content-Type': description: Set to `text/html; charset=utf-8`. schema: type: string '/html': get: tags: - Response formats summary: Send an HTML page. responses: '200': description: An example HTML page. content: text/html: schema: type: string '/json': get: tags: - Response formats summary: Send a JSON document. responses: '200': description: An example JSON document. content: application/json: schema: type: object '/robots.txt': get: tags: - Response formats summary: Send example `robots.txt` rules. description: It will not allow the `/deny` endpoint. responses: '200': description: An example `robots.txt` file. content: text/plain: schema: type: string '/xml': get: tags: - Response formats summary: Send an XML document. responses: '200': description: An example XML document. content: application/xml: schema: type: string '/base64/:value': parameters: - name: value in: path required: true description: Assumed ETag value. schema: type: string get: tags: - Dynamic data summary: Base64 decoder description: Base64 decode the supplied value and echo it back. responses: '200': description: Decoded base64. content: application/octet-stream: schema: type: string '/bytes/:n': parameters: - name: n in: path required: true description: Number of bytes, maximum 10000. schema: type: integer get: tags: - Dynamic data summary: Random bytes. responses: '200': description: Random bytes. content: application/octest-stream: schema: type: string '/delay/:secs': parameters: - name: secs in: path required: true description: Number of seconds, fractions are supported. schema: type: number get: tags: - Dynamic data summary: Delayed response. description: | Wait for the specified number of seconds before sending the response. responses: '200': description: JSON response. content: application/json: schema: $ref: '#/components/schemas/common' '/drip': parameters: - name: duration in: query description: Number of seconds for the whole response. schema: type: number default: 2 - name: numbytes in: query description: Number of bytes to return. schema: type: integer default: 10 - name: code in: query description: HTTP status code to return with. schema: type: integer default: 200 - name: delay in: query description: Initial delay, in seconds. Zero means no delay. schema: type: number default: 0 get: tags: - Dynamic data summary: Drip bytes description: | Drip the specified number of bytes over the specified number of seconds, potentially after some initial delay. responses: '200': description: | Data of the specified length. The status code is not neccesarily 200, but the one specified in the `code` query parameter. content: application/octet-stream: schema: type: string '/links/:n/:offset': parameters: - name: n in: path required: true description: Number of links. schema: type: integer - name: offset in: path required: false description: Id of the page to return, out of `n`. schema: type: integer get: tags: - Dynamic data summary: Links description: | Generate a page containing n links to other pages which do the same. responses: '200': description: | HTML links. content: text/html '/stream/:n': parameters: - name: n in: path required: true description: Number of JSON chunks to send. schema: type: integer get: tags: - Dynamic data summary: Stream JSON chunks. description: | Stream `n` JSON responses, each terminated by a newline character. responses: '200': description: | Streamed JSON responses. Each JSON chunk contains an `id` field, from zero, up to `n-1`. content: application/json '/stream-bytes/:n': parameters: - name: n in: path required: true description: Number of bytes, maximum 102400. schema: type: integer - name: seed in: query description: Random seed. schema: type: number default: 42 - name: chunk-size in: query description: | Size of a chunked for the chunked encoding. The last chunk migh be shorter than his. schema: type: integer default: 10240 get: tags: - Dynamic data summary: Stream in chunks. description: | Streams n random bytes generated with given seed, at given chunk size per packet. responses: '200': description: Random bytes. content: application/octest-stream: schema: type: string '/range/:n': parameters: - name: n in: path required: true description: Number of bytes, maximum 102400. schema: type: integer - name: chunk_size in: query required: false description: Chunk size, if `duration` is not 0. schema: type: number default: 10240 - name: duration in: query required: false description: | Duration for the total response. It applies to the full response size without ranges. schema: type: number default: 0 get: tags: - Dynamic data summary: Range requests. description: | Send only part of the response, after a `Range` header. responses: '200': description: | Full response, if there was no `Range` header, or the `Range` header was invalid. content: text/plain '206': description: | Partial response, containing the requested range. head: tags: - Dynamic data summary: Range requests.. desciption: | HEAD request to an endpoint that supports ranges. responses: '200': description: | Response with an `Accept-Ranges: bytes` header. '/uuid': get: tags: - Dynamic data summary: Random UUID. description: It is pseudo-random, and not secure. responses: '200': description: Random UUID v4 in JSON. content: application/json: schema: type: object properties: uuid: type: string example: "ee4610df-3b7b-4624-8ce9-da6975b3e9f1" '/cookies': get: tags: - Cookies summary: Cookie data. description: Returns cookie data. responses: '200': description: Set cookies. content: application/json: schema: type: object properties: cookies: type: object '/cookies/delete': parameters: - name: freeform in: query style: "form" get: tags: - Cookies summary: Delete cookies. description: | Deletes cookie(s) as provided by the query string and redirects to cookie list. responses: '302': description: Redirect to the cookie list. '/cookies/set': parameters: - name: freeform in: query style: "form" get: tags: - Cookies summary: Set cookies. description: | Sets cookie(s) as provided by the query string and redirects to cookie list. responses: '302': description: Redirect to the cookie list. '/cookies/set/:name/:value': parameters: - name: name in: path description: Cookie name. schema: type: string - name: value in: path description: Cookie value. schema: type: string get: tags: - Cookies summary: Set one cookie. description: | Sets a cookie and redirects to cookie list. responses: '302': description: Redirect to the cookie list. '/image': parameters: - name: Accept in: header description: Accepted image content type. schema: type: string get: tags: - Images summary: Return an image. description: | It selects the format according to the `Accept` request header. Supported formats: `image/jpeg`, `image/png`, `image/svg+xml`, `image/webp`, `image/*`. responses: '200': description: Image file. content: image/jpeg: schema: type: string format: binary image/png: schema: type: string format: binary image/svg+xml: schema: type: string format: binary image/webp: schema: type: string format: binary '406': description: The client did not request a supported media type. content: application/json: schema: type: object properties: message: type: string example: "Client did not request a supported media type." accept: type: array items: type: string example: - "image/jpeg" - "image/png" - "image/svg+xml" - "image/webp" '/image/:format': parameters: - name: format description: Image format. May be `jpeg`, `png`, `svg` or `webp`. in: path schema: type: string required: true get: tags: - Images summary: Return an image of the specified format. responses: '200': description: Image file. content: image/jpeg: schema: type: string format: binary image/png: schema: type: string format: binary image/svg+xml: schema: type: string format: binary image/webp: schema: type: string format: binary '/absolute-redirect/:n': parameters: - name: n in: path required: true description: Number of times to redirect. Maximum is five. schema: type: integer get: tags: - Redirects summary: Redirect to an absolute URL, n times. responses: '302': description: Redirect. '/relative-redirect/:n': parameters: - name: n in: path description: Number of times to redirect. Maximum is five. schema: type: integer required: true get: tags: - Redirects summary: Redirect to a relative URL, n times. responses: '302': description: Redirect. '/redirect-to': parameters: - name: url in: query description: URL to redirect to. schema: type: string - name: status_code in: query description: HTTP status code to use for the redirection. schema: type: integer default: 302 delete: tags: - Redirects summary: Redirect to an URL. description: | See for details. This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '300': description: Multiple Choices. '301': description: Moved Permanently. '302': description: Found (Previously "Moved temporarily") '303': description: See Other (since HTTP/1.1) '304': description: Not Modified (RFC 7232) '305': description: Use Proxy (since HTTP/1.1) '306': description: Switch Proxy '307': description: Temporary Redirect (since HTTP/1.1) '308': description: Permanent Redirect (RFC 7538) get: tags: - Redirects summary: Redirect to an URL. description: | See for details. This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '300': description: Multiple Choices. '301': description: Moved Permanently. '302': description: Found (Previously "Moved temporarily") '303': description: See Other (since HTTP/1.1) '304': description: Not Modified (RFC 7232) '305': description: Use Proxy (since HTTP/1.1) '306': description: Switch Proxy '307': description: Temporary Redirect (since HTTP/1.1) '308': description: Permanent Redirect (RFC 7538) patch: tags: - Redirects summary: Redirect to an URL. description: | See for details. This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '300': description: Multiple Choices. '301': description: Moved Permanently. '302': description: Found (Previously "Moved temporarily") '303': description: See Other (since HTTP/1.1) '304': description: Not Modified (RFC 7232) '305': description: Use Proxy (since HTTP/1.1) '306': description: Switch Proxy '307': description: Temporary Redirect (since HTTP/1.1) '308': description: Permanent Redirect (RFC 7538) post: tags: - Redirects summary: Redirect to an URL. description: | See for details. This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '300': description: Multiple Choices. '301': description: Moved Permanently. '302': description: Found (Previously "Moved temporarily") '303': description: See Other (since HTTP/1.1) '304': description: Not Modified (RFC 7232) '305': description: Use Proxy (since HTTP/1.1) '306': description: Switch Proxy '307': description: Temporary Redirect (since HTTP/1.1) '308': description: Permanent Redirect (RFC 7538) put: tags: - Redirects summary: Redirect to an URL. description: | See for details. This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '300': description: Multiple Choices. '301': description: Moved Permanently. '302': description: Found (Previously "Moved temporarily") '303': description: See Other (since HTTP/1.1) '304': description: Not Modified (RFC 7232) '305': description: Use Proxy (since HTTP/1.1) '306': description: Switch Proxy '307': description: Temporary Redirect (since HTTP/1.1) '308': description: Permanent Redirect (RFC 7538) '/anything': delete: tags: - Anything summary: Returns anything passed in request data. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '200': description: The request data. content: application/json: schema: $ref: '#/components/schemas/common' get: tags: - Anything summary: Returns anything passed in request data. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '200': description: The request data. content: application/json: schema: $ref: '#/components/schemas/common' patch: tags: - Anything summary: Returns anything passed in request data. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '200': description: The request data. content: application/json: schema: $ref: '#/components/schemas/common' post: tags: - Anything summary: Returns anything passed in request data. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '200': description: The request data. content: application/json: schema: $ref: '#/components/schemas/common' put: tags: - Anything summary: Returns anything passed in request data. description: | This endpoint works for these other HTTP verbs as well, the same way as for `GET`: `CONNECT`, `DELETE`, `HEAD`, `MKCOL`, `OPTIONS`, `PATCH`, `POST`, `PROPFIND`, `PUT`, `REPORT`. responses: '200': description: The request data. content: application/json: schema: $ref: '#/components/schemas/common' components: parameters: status: name: status in: path required: true description: Status code. schema: type: integer schemas: get: properties: args: type: object headers: type: object origin: type: string path: type: string url: type: string required: - args - headers - origin - path - url common: properties: args: type: object data: type: object files: type: object form: type: object headers: type: object json: type: object method: type: string path: type: string origin: type: string url: type: string webfakes/inst/examples/httpbin/images/0000755000176200001440000000000014172041777017563 5ustar liggesuserswebfakes/inst/examples/httpbin/images/Rlogo.jpeg0000644000176200001440000001120614172041777021514 0ustar liggesusersJFIFvvC       C Ld G !"1Q#27Aaq$Bt3Wbs%Rruv2!A123QR"4aq#B ?V& :c֨j/@]Emx!+b9q|#B7a= 횥j3E9e)&'iy` s0eGr#[i2](򙏷@ s/zA ݹ]) Zz!,$ʼnI> <&2I#{4iihG@djTST̠7\}ߊ]W +0`zʚOn0xOeM.LysI vsIBW/;Uef߷#f,"CE@*k٫d^-T5q/L-C.Gq oDsWrw L&ݘ&fBy-lr߀ p{=3/EIr> )Om4TSTlL98Wpm,wg[-TM3Y(}\~ I'p/k3a"-傰wVirS{3iHEZrܹm'dPxn-zen4¦5)q#UR cQ-g:GWJ.T!!jVu]v_نM|hS0x4fǍUW |ңmCQsܵ \3݈1=:>YY[/'eϳG'y7'M)q>c 9Laz,gե\+Wِ.Ewp {|ؗle*/-7q FͶhϦ-Q-I7anFeEdWVҥ+嘂Yt`A縮8 9c{+WO~۪&sFu k*͵4tf!K)U,7<:ic!ޓgŎy?Oc2}ϬI2"Z{H^C2#?D$#$'b uyQWCSUNډ>A\jA%SQEECw Uy0UvۊhYYfxl/=]d*L<[O41;ľ p_$rU/Փ K^ZdT3BOz\j#Y8+=E-i2F'mjvW@ͫR7"+.@*Ô,UW4鴪VVo;ƪMrk u wH,yv,v*=Uܪ*!׹Tw`&/rVsd,M,oLU2J6} U`_F \dt+Eࡽ1W7,sw{ݙ(Rq\8̹0MEQ ]K!  \4pfܣ~uձ.`0Hwl7Vk>,u;{uFL wf>>b,Wӆ\ AWG*TSOJ]j+)<SkT [>`ݮsoHGS~]}>R$gVVٚ;݆ӚKySc !cc؏ iZ'f*:0.uBz+|GTfx41C` E"/&eF1k>T'}4LLLL}v4kebghАJ7U;{ӆfݭvNeGXV:n̑2Ȃxzw؋\> b BJ:MڃkiɁȒ;+op ۍSE圛sWU &QF-M|ռ7Qv UɬXI-4+x؂YIrwpFDiX%ѮzLGL. H#^b›ȓ;e\zXUVT*fC^xnLJcm6TX%n`|aOFy]2毩-1n35㨥WC5$#T'paA{nIJNE,3,(tjȵEp e2=*ŸDo>sA;^YVŒڮ.ٙMS:#+ Q4.c@kS6̳?Y3ewh؟t4;4㳇Xvzԩ KVP8 *dL>FK% e|*.e.wyx&=򞉪2v?a.H0ꈭng6d۪{f_dK"7"A:Ÿ?1M,/`^G HDV͓~=[bI6Z[T=V:^JQrC#~05A^pehh> `3$?$eJ`'CfuJHpxsY ށ2x2#}8D zB7ozM'ԯ? /MM,'Q&#wrYMaۖ0{B\PoѰBV:$ڶ;*@n4ߜ?a zUb|\7͙y ,v*nƷ6b~J^4*: aѼJPfq !-r¤ZfÌUHQ6߹0o4g筰>7)MB)R"0[:G9w"u Y%YA_{&gT+SěՆh.Qިy;rVj?.C½qE]y.ͤ|Y"9smb4cHcդys9_\WY?,.nI'h$IkԿN<˲;/G/N$9zÛ[kK_qie!q?!T0/*7)>O848ْ%S4$Bw4% oa,[K^#Q:KT;y{sdX0S.Y:]&L2w1b[GK Y"EC [؉4H<,ei~ k,&@GG6n'"QaoȫyDۛ webfakes/inst/examples/httpbin/images/Rlogo.png0000644000176200001440000002700614172041777021360 0ustar liggesusersPNG  IHDRdLbKGD pHYs.#.#x?vtIME' IDATx}w]e]O/[2d24H.(b(XAI\Z(CPB ϤM?3sgϜ$`;s2^]Yk(|S72JӴ*˲*ljv[i&l;6=aALv2EQIx1̓'Eԧff=rc>f$q&ڎ3u&۱Cu][wA4Lض u\`;&D@uiz3òCӾm'Nvwߤ6n.˅>Ѷcm۪v](7s[u] LeY( .ׅ8u8q\0YBQKh~76a9l?w_m+eEQE{}/a`[vݒzx[3uJ8 .na4EU5/)1ʋԮ]Ǫ#˴۶8(PěOnߍz,,ׅe T{-uJR$ǁm۰ٶ ۶`6,˂8@,|GnzŸLؓ2-Ӻ6 &P #`CQ޾#SUw/FTmۀ¶P8c_p]-SaIxb[lˆi 1 òUU^u ?tOj3M|۱#K( mwB"4M@ tdxRy3#aۻm8Fm{@X6,˄eZ0LeT 3oO% ?`LK øuoɞo> !0MA5 u=io?Р `g^R`;,˂i0-eum Ʋ,X 4a0=Z]U} T_bq8exJH˱x4!(2r  i.@348za0,X]*JD}Ӵ&ζ풭2*!B@34òi2M4Ų-4at]aPpU_y{VT˶INPe!Mҩ$t]E( ='x8EQ ,MӠit]aucXnS2Tq]qnS Àxa8.4Mi0b& ]aui&tW89;XpXy'L&}nSOQP8P,"N\dYqX  " y.`:TM(exb0-=h[k ^P8woE5EO=v,(ݿVg eq<\ǁ( e0m-ӄ=P)yYcE~ֶ鄐7D׃<Es8yP(/@(CQdȊ IQeo4GT ǶKIiP(B,-'CA Àa M8A4 MSjZ~tMנh}羻fCin̓ !8CYY2`5f @<G<GmM*+*P0%Q 5 #ni]Ne['s LB|}%j8}y`px׮'ˊq:N˱8E狎 # KP,C4 / 0E@4M#bb$3iE:/Cń6TW,d (EA.];cR)Bt+?c^[|JƵ7\vQضMqx<{{u\ **$Q(B\p/I_t? ;=ErLt:mUU 0i,Z(2$YBP%]]y&$i!kllgS>.ҲsL8 ˀJD$B.ȐUPͻCY4U] ?FUE>,[/̛ Ӵ   Q^^  !$ YV04ucvryomxB7z|eNPS+'y,! H B 5)//?!y|(v04!(/+9֯S΁eYBBè䉓1f8I D HXz HbQ)妧xV>f](Jp]S±-&$A33Vxel#&( `9Ȥ% 777Oy }se(@@f=t?TMC(B$F$CuU5LMca6XD6,+>ss_@umL qM0uÆ FQ]]I'cBK; "bd*w[ "#A?kɢeoj2F?[lV@ B0-rT:t:$B%h`ϵ67_}劋ٹ4͌Ϧ8-[ ˃y)NҫL`0'r2!4(B(Ix7qpACԢyxAh湮xΪ5+ѱl\B]Gqĉ/?]xq:L Сk*YD&5MbwϟcƠ::z?]~֍Wz^ KI|_L T0PUU!(t:y |g@1 (++C&UqhUS::u`ӦeDȴq,#^^C#Qq>s J{X>7ah V^wgmKu]tyo<-J.q]ѲL4nB:$I_?kǽ3(pASݫ,Xl1h'# 0 tk׭F6^QNᄒ`aR3,CcJ"X`Vċ Ӳ DIB._nX{'} B ux͗p羀h Z@6-R+Vyͷc2xݍW]V䥎 Hh$!egA}]=VY\.A pcs4]ǦM144BA$Pdy{K_=\kp(kaRF.=ɡi (1O aXdrP 4QG˰c-֯] ! A}i_׼kk.+(;,H$e+_G1}6888pUI<Ϗ+u7A zY ^rFe"Q(xy C3csa GنĠkVa릵 :k[dp@0p$@ ° }C7a:vuCovD咠( [vbGM|WG1O@:9L>=q @Ea .L,wvD.Pg=*.UU]YD"W`/#=f@u0@\ bUja`u@~l 0zlvlE<M{3k9+rP]]p 4̲<(-Y<#<,=ҁQfUAoOO)@i0n:|.*Ma۶Ntn]D7o y!6\BTmq\mnXرm3Ƕ ~4ҩ!| аn݆SL4e˗7LcrUe6`#dYigl]F__z1~\mrd30tCМt~8q"#I0"WEq+kjCӴH&j攼** uwy (קˑe >Tr{wiYq4a˲#Τ<XʼU#>F&)AD\^ukv,X P$L1Gߎ@D7giO3$fj^$7{Ao ݳN魮y8/p8lzx0E-Eh"Wm8s0MsɧJahewXSsO 4 ,d0Bzy"iCS 1 <e4uXq,9eNP5EBX*0B%ޣ«sEKð.M3,Fae 2e]q]&$A(؎4 |4SMeyUE4[iB(uJG cN8,'`sD}m&Ojkv_DMHnCAēN~7.< k7B2/Z?^9uV5weƼbJC!(RRfӅp( ghC$EV&޻pǥ+FoW'zm.N;|vR>p8OνG?rjhtEGc ]? ^cPCCCp <)1*P( x}}PTD"}_||868.$r>H 9Qz1:cՍېI%0ؿ(8AYY\l]dWӟ;oZ1aG}gEuL>{r/Nr޹X|YCCu]kv+s-˂i & ULò,T'JCA@Szz IL&|C=O6:KpQmHt[[7i{(C8E(Sl`8e!94MS1˧>4ff{kӴv IDAT}G1A_dC'9)>iYV,+ƓO<S rzB{y.a^?)/Ǯ9X2̂8R䩲W Iz]G^c яl6 ˴MeuMM :̼"8S\D,5譗/w㈕U!fҨk =1PH0pH`( ͙4o>Ļ}/+򍺮pI&Ŝ9OAKJ/^q}0@8w׿PF#}(;6F8]eAUXA@Q, ` 9 MզH\yJ4|OWTP(,z5p|5c HY4nlX;Ǯu,)O e`zqX @=] EƷ"B TU &Scwu\x׾U_9*_[*N8? C2!ھ};}P JaB[JZNf5MiwkQlY FҘ@74j,*b9,0g&ߘq=Y D?I Jy]KjլY/+&n0L6+04zw!+G*5]6 O@$ð^D4]#CGvg|K{xO~8Quo7ބeZQ!8 -w>?<d|.e+1nl3m5:a 46?Ͽ{+OfhA"9UU"łeM̀eY؎!8>N1b`@3 V0 YU,l a\eSOW5M+ 12Uy ebES8xjN!!|W|Mo03 ALz$\jGǑǝgB4V?ôrU' ªqc^ Gwϝ.HTc^S1IaZ;/oNd5B}XYێ]n MkU; JUuHB0RBs%,ʫGoB Uض#T㨊}t_<.vAQߚ#.va2LsgYC`Dxt`)}b5/  b@Q(qEP*t]E6Eee%G5b X%h po"A$k/Xx RI[n}G͸M@zq\@A*@ DID.fYds9,4ai'^Md<^h,p8\2@Q`!O\K%o͢{)FrxU#x6mMJoǫDMӎw\]<;R A e38ҫ.u(lSTׯK$ 4l&ʊ 4i@"*0fAe(dIp$]Ϧ/ˮO #㺫o< {~S*<[oi6u]q{KjI ǻ@?m{| f1~r&΀zedtڎLuc%/Mӵ UuP ]öNxygxS\]np/iph+~ɶ/1E Ǽf: ʴk\Xm6S5QUdc\hniC׮׀CA3+ n}myۦQKZWNe4/#:~|3:npm(g3phtMA>d_mNjinP??iTl:$ID&Ei쇦uY!QH%# s/14FS&5_?@є }4MKxйmgY^t9@lKйi ]Э}g_wwhnX۶0 @(+WU>SxaN a>rԖ=[!~qCQ‘X?kZfIENDB`webfakes/inst/examples/httpbin/data/0000755000176200001440000000000014172041777017227 5ustar liggesuserswebfakes/inst/examples/httpbin/data/example.json0000644000176200001440000000062714172041777021562 0ustar liggesusers{ "firstName": "John", "lastName": "Smith", "isAlive": true, "age": 27, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021-3100" }, "phoneNumbers": [ { "type": "home", "number": "212 555-1234" }, { "type": "office", "number": "646 555-4567" } ], "children": [], "spouse": null } webfakes/inst/examples/httpbin/data/robots.txt0000644000176200001440000000003614172041777021277 0ustar liggesusersUser-agent: * Disallow: /deny webfakes/inst/examples/httpbin/data/utf8.html0000644000176200001440000003371714172041777021016 0ustar liggesusers

Unicode Demo

Taken from http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-demo.txt

UTF-8 encoded sample plain-text file
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾

Markus Kuhn [ˈmaʳkʊs kuːn]  — 2002-07-25 CC BY


The ASCII compatible UTF-8 encoding used in this plain-text file
is defined in Unicode, ISO 10646-1, and RFC 2279.


Using Unicode/UTF-8, you can write in emails and source code things such as

Mathematics and sciences:

  ∮ E⋅da = Q,  n → ∞, ∑ f(i) = ∏ g(i),      ⎧⎡⎛┌─────┐⎞⎤⎫
                                            ⎪⎢⎜│a²+b³ ⎟⎥⎪
  ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β),    ⎪⎢⎜│───── ⎟⎥⎪
                                            ⎪⎢⎜⎷ c₈   ⎟⎥⎪
  ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ,                   ⎨⎢⎜       ⎟⎥⎬
                                            ⎪⎢⎜ ∞     ⎟⎥⎪
  ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (⟦A⟧ ⇔ ⟪B⟫),      ⎪⎢⎜ ⎲     ⎟⎥⎪
                                            ⎪⎢⎜ ⎳aⁱ-bⁱ⎟⎥⎪
  2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm     ⎩⎣⎝i=1    ⎠⎦⎭

Linguistics and dictionaries:

  ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn
  Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ]

APL:

  ((V⍳V)=⍳⍴V)/V←,V    ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈

Nicer typography in plain text files:

  ╔══════════════════════════════════════════╗
  ║                                          ║
  ║   • ‘single’ and “double” quotes         ║
  ║                                          ║
  ║   • Curly apostrophes: “We’ve been here” ║
  ║                                          ║
  ║   • Latin-1 apostrophe and accents: '´`  ║
  ║                                          ║
  ║   • ‚deutsche‘ „Anführungszeichen“       ║
  ║                                          ║
  ║   • †, ‡, ‰, •, 3–4, —, −5/+5, ™, …      ║
  ║                                          ║
  ║   • ASCII safety test: 1lI|, 0OD, 8B     ║
  ║                      ╭─────────╮         ║
  ║   • the euro symbol: │ 14.95 € │         ║
  ║                      ╰─────────╯         ║
  ╚══════════════════════════════════════════╝

Combining characters:

  STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑

Greek (in Polytonic):

  The Greek anthem:

  Σὲ γνωρίζω ἀπὸ τὴν κόψη
  τοῦ σπαθιοῦ τὴν τρομερή,
  σὲ γνωρίζω ἀπὸ τὴν ὄψη
  ποὺ μὲ βία μετράει τὴ γῆ.

  ᾿Απ᾿ τὰ κόκκαλα βγαλμένη
  τῶν ῾Ελλήνων τὰ ἱερά
  καὶ σὰν πρῶτα ἀνδρειωμένη
  χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά!

  From a speech of Demosthenes in the 4th century BC:

  Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι,
  ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς
  λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ
  τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿
  εἰς τοῦτο προήκοντα,  ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ
  πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν
  οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι,
  οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν
  ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον
  τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι
  γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν
  προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους
  σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ
  τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ
  τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς
  τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον.

  Δημοσθένους, Γ´ ᾿Ολυνθιακὸς

Georgian:

  From a Unicode conference invitation:

  გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
  კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს,
  ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს
  ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი,
  ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება
  ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში,
  ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში.

Russian:

  From a Unicode conference invitation:

  Зарегистрируйтесь сейчас на Десятую Международную Конференцию по
  Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии.
  Конференция соберет широкий круг экспертов по  вопросам глобального
  Интернета и Unicode, локализации и интернационализации, воплощению и
  применению Unicode в различных операционных системах и программных
  приложениях, шрифтах, верстке и многоязычных компьютерных системах.

Thai (UCS Level 2):

  Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese
  classic 'San Gua'):

  [----------------------------|------------------------]
    ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช  พระปกเกศกองบู๊กู้ขึ้นใหม่
  สิบสองกษัตริย์ก่อนหน้าแลถัดไป       สององค์ไซร้โง่เขลาเบาปัญญา
    ทรงนับถือขันทีเป็นที่พึ่ง           บ้านเมืองจึงวิปริตเป็นนักหนา
  โฮจิ๋นเรียกทัพทั่วหัวเมืองมา         หมายจะฆ่ามดชั่วตัวสำคัญ
    เหมือนขับไสไล่เสือจากเคหา      รับหมาป่าเข้ามาเลยอาสัญ
  ฝ่ายอ้องอุ้นยุแยกให้แตกกัน          ใช้สาวนั้นเป็นชนวนชื่นชวนใจ
    พลันลิฉุยกุยกีกลับก่อเหตุ          ช่างอาเพศจริงหนาฟ้าร้องไห้
  ต้องรบราฆ่าฟันจนบรรลัย           ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ

  (The above is a two-column text. If combining characters are handled
  correctly, the lines of the second column should be aligned with the
  | character above.)

Ethiopian:

  Proverbs in the Amharic language:

  ሰማይ አይታረስ ንጉሥ አይከሰስ።
  ብላ ካለኝ እንደአባቴ በቆመጠኝ።
  ጌጥ ያለቤቱ ቁምጥና ነው።
  ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው።
  የአፍ ወለምታ በቅቤ አይታሽም።
  አይጥ በበላ ዳዋ ተመታ።
  ሲተረጉሙ ይደረግሙ።
  ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል።
  ድር ቢያብር አንበሳ ያስር።
  ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም።
  እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም።
  የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ።
  ሥራ ከመፍታት ልጄን ላፋታት።
  ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል።
  የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ።
  ተንጋሎ ቢተፉ ተመልሶ ባፉ።
  ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው።
  እግርህን በፍራሽህ ልክ ዘርጋ።

Runes:

  ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ

  (Old English, which transcribed into Latin reads 'He cwaeth that he
  bude thaem lande northweardum with tha Westsae.' and means 'He said
  that he lived in the northern land near the Western Sea.')

Braille:

  ⡌⠁⠧⠑ ⠼⠁⠒  ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌

  ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞
  ⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎
  ⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂
  ⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙
  ⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑
  ⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲

  ⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲

  ⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹
  ⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞
  ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕
  ⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹
  ⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎
  ⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎
  ⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳
  ⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞
  ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲

  (The first couple of paragraphs of "A Christmas Carol" by Dickens)

Compact font selection example text:

  ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789
  abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ
  –—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд
  ∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა

Greetings in various languages:

  Hello world, Καλημέρα κόσμε, コンニチハ

Box drawing alignment tests:                                          █
                                                                      ▉
  ╔══╦══╗  ┌──┬──┐  ╭──┬──╮  ╭──┬──╮  ┏━━┳━━┓  ┎┒┏┑   ╷  ╻ ┏┯┓ ┌┰┐    ▊ ╱╲╱╲╳╳╳
  ║┌─╨─┐║  │╔═╧═╗│  │╒═╪═╕│  │╓─╁─╖│  ┃┌─╂─┐┃  ┗╃╄┙  ╶┼╴╺╋╸┠┼┨ ┝╋┥    ▋ ╲╱╲╱╳╳╳
  ║│╲ ╱│║  │║   ║│  ││ │ ││  │║ ┃ ║│  ┃│ ╿ │┃  ┍╅╆┓   ╵  ╹ ┗┷┛ └┸┘    ▌ ╱╲╱╲╳╳╳
  ╠╡ ╳ ╞╣  ├╢   ╟┤  ├┼─┼─┼┤  ├╫─╂─╫┤  ┣┿╾┼╼┿┫  ┕┛┖┚     ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
  ║│╱ ╲│║  │║   ║│  ││ │ ││  │║ ┃ ║│  ┃│ ╽ │┃  ░░▒▒▓▓██ ┊  ┆ ╎ ╏  ┇ ┋ ▎
  ║└─╥─┘║  │╚═╤═╝│  │╘═╪═╛│  │╙─╀─╜│  ┃└─╂─┘┃  ░░▒▒▓▓██ ┊  ┆ ╎ ╏  ┇ ┋ ▏
  ╚══╩══╝  └──┴──┘  ╰──┴──╯  ╰──┴──╯  ┗━━┻━━┛  ▗▄▖▛▀▜   └╌╌┘ ╎ ┗╍╍┛ ┋  ▁▂▃▄▅▆▇█
                                               ▝▀▘▙▄▟
webfakes/inst/examples/httpbin/data/example.html0000644000176200001440000000264314172041777021555 0ustar liggesusers

Don Quixote by Miguel de Cervantes

In a village of La Mancha, the name of which I have no desire to call to mind, there lived not long since one of those gentlemen that keep a lance in the lance-rack, an old buckler, a lean hack, and a greyhound for coursing. An olla of rather more beef than mutton, a salad on most nights, scraps on Saturdays, lentils on Fridays, and a pigeon or so extra on Sundays, made away with three-quarters of his income. The rest of it went in a doublet of fine cloth and velvet breeches and shoes to match for holidays, while on week-days he made a brave figure in his best homespun. He had in his house a housekeeper past forty, a niece under twenty, and a lad for the field and market-place, who used to saddle the hack as well as handle the bill-hook. The age of this gentleman of ours was bordering on fifty; he was of a hardy habit, spare, gaunt-featured, a very early riser and a great sportsman. They will have it his surname was Quixada or Quesada (for here there is some difference of opinion among the authors who write on the subject), although from reasonable conjectures it seems plain that he was called Quexana. This, however, is of but little importance to our tale; it will be enough not to stray a hair’s breadth from the truth in the telling of it.

webfakes/inst/examples/httpbin/data/example.xml0000644000176200001440000000114214172041777021402 0ustar liggesusers
New York 10021-3100 NY 21 2nd Street
27 John true Smith 212 555-1234 home 646 555-4567 office
webfakes/inst/examples/httpbin/data/deny.txt0000644000176200001440000000042714172041777020732 0ustar liggesusers -------------- Get out of here -------------- \ \ \ |\___/| ==) ^Y^ (== \ ^ / )=*=( / \ | | /| | | |\ \| | |_|/\ jgs //_// ___/ \_) webfakes/inst/examples/httpbin/doc-template.hbs0000644000176200001440000000072114172041777021372 0ustar liggesusers {{title}} {{{redocHead}}} {{{redocHTML}}} webfakes/inst/examples/httpbin/app.R0000644000176200001440000000014315026556433017216 0ustar liggesuserslibrary(webfakes) app <- httpbin_app() app$listen(as.integer(Sys.getenv("PORT", NA_character_))) webfakes/inst/examples/static/0000755000176200001440000000000015026556433016134 5ustar liggesuserswebfakes/inst/examples/static/public/0000755000176200001440000000000014172041777017413 5ustar liggesuserswebfakes/inst/examples/static/public/bar/0000755000176200001440000000000014172041777020157 5ustar liggesuserswebfakes/inst/examples/static/public/bar/foo.txt0000644000176200001440000000002514172041777021500 0ustar liggesusersThis is a text file. webfakes/inst/examples/static/public/foo/0000755000176200001440000000000014172041777020176 5ustar liggesuserswebfakes/inst/examples/static/public/foo/bar.json0000644000176200001440000000005314172041777021633 0ustar liggesusers{ "foo": "bar", "bar": [1, 2, 3] } webfakes/inst/examples/static/public/foo/bar.html0000644000176200001440000000006414172041777021630 0ustar liggesusersHello world! webfakes/inst/examples/static/app.R0000644000176200001440000000021715026556433017037 0ustar liggesuserslibrary(webfakes) app <- new_app() app$use(mw_log()) app$use(mw_static("public")) app$listen(as.integer(Sys.getenv("PORT", NA_character_))) webfakes/inst/examples/send-file/0000755000176200001440000000000015026556433016513 5ustar liggesuserswebfakes/inst/examples/send-file/Rlogo.png0000644000176200001440000002700614172041777020311 0ustar liggesusersPNG  IHDRdLbKGD pHYs.#.#x?vtIME' IDATx}w]e]O/[2d24H.(b(XAI\Z(CPB ϤM?3sgϜ$`;s2^]Yk(|S72JӴ*˲*ljv[i&l;6=aALv2EQIx1̓'Eԧff=rc>f$q&ڎ3u&۱Cu][wA4Lض u\`;&D@uiz3òCӾm'Nvwߤ6n.˅>Ѷcm۪v](7s[u] LeY( .ׅ8u8q\0YBQKh~76a9l?w_m+eEQE{}/a`[vݒzx[3uJ8 .na4EU5/)1ʋԮ]Ǫ#˴۶8(PěOnߍz,,ׅe T{-uJR$ǁm۰ٶ ۶`6,˂8@,|GnzŸLؓ2-Ӻ6 &P #`CQ޾#SUw/FTmۀ¶P8c_p]-SaIxb[lˆi 1 òUU^u ?tOj3M|۱#K( mwB"4M@ tdxRy3#aۻm8Fm{@X6,˄eZ0LeT 3oO% ?`LK øuoɞo> !0MA5 u=io?Р `g^R`;,˂i0-eum Ʋ,X 4a0=Z]U} T_bq8exJH˱x4!(2r  i.@348za0,X]*JD}Ӵ&ζ풭2*!B@34òi2M4Ų-4at]aPpU_y{VT˶INPe!Mҩ$t]E( ='x8EQ ,MӠit]aucXnS2Tq]qnS Àxa8.4Mi0b& ]aui&tW89;XpXy'L&}nSOQP8P,"N\dYqX  " y.`:TM(exb0-=h[k ^P8woE5EO=v,(ݿVg eq<\ǁ( e0m-ӄ=P)yYcE~ֶ鄐7D׃<Es8yP(/@(CQdȊ IQeo4GT ǶKIiP(B,-'CA Àa M8A4 MSjZ~tMנh}羻fCin̓ !8CYY2`5f @<G<GmM*+*P0%Q 5 #ni]Ne['s LB|}%j8}y`px׮'ˊq:N˱8E狎 # KP,C4 / 0E@4M#bb$3iE:/Cń6TW,d (EA.];cR)Bt+?c^[|JƵ7\vQضMqx<{{u\ **$Q(B\p/I_t? ;=ErLt:mUU 0i,Z(2$YBP%]]y&$i!kllgS>.ҲsL8 ˀJD$B.ȐUPͻCY4U] ?FUE>,[/̛ Ӵ   Q^^  !$ YV04ucvryomxB7z|eNPS+'y,! H B 5)//?!y|(v04!(/+9֯S΁eYBBè䉓1f8I D HXz HbQ)妧xV>f](Jp]S±-&$A33Vxel#&( `9Ȥ% 777Oy }se(@@f=t?TMC(B$F$CuU5LMca6XD6,+>ss_@umL qM0uÆ FQ]]I'cBK; "bd*w[ "#A?kɢeoj2F?[lV@ B0-rT:t:$B%h`ϵ67_}劋ٹ4͌Ϧ8-[ ˃y)NҫL`0'r2!4(B(Ix7qpACԢyxAh湮xΪ5+ѱl\B]Gqĉ/?]xq:L Сk*YD&5MbwϟcƠ::z?]~֍Wz^ KI|_L T0PUU!(t:y |g@1 (++C&UqhUS::u`ӦeDȴq,#^^C#Qq>s J{X>7ah V^wgmKu]tyo<-J.q]ѲL4nB:$I_?kǽ3(pASݫ,Xl1h'# 0 tk׭F6^QNᄒ`aR3,CcJ"X`Vċ Ӳ DIB._nX{'} B ux͗p羀h Z@6-R+Vyͷc2xݍW]V䥎 Hh$!egA}]=VY\.A pcs4]ǦM144BA$Pdy{K_=\kp(kaRF.=ɡi (1O aXdrP 4QG˰c-֯] ! A}i_׼kk.+(;,H$e+_G1}6888pUI<Ϗ+u7A zY ^rFe"Q(xy C3csa GنĠkVa릵 :k[dp@0p$@ ° }C7a:vuCovD咠( [vbGM|WG1O@:9L>=q @Ea .L,wvD.Pg=*.UU]YD"W`/#=f@u0@\ bUja`u@~l 0zlvlE<M{3k9+rP]]p 4̲<(-Y<#<,=ҁQfUAoOO)@i0n:|.*Ma۶Ntn]D7o y!6\BTmq\mnXرm3Ƕ ~4ҩ!| аn݆SL4e˗7LcrUe6`#dYigl]F__z1~\mrd30tCМt~8q"#I0"WEq+kjCӴH&j攼** uwy (קˑe >Tr{wiYq4a˲#Τ<XʼU#>F&)AD\^ukv,X P$L1Gߎ@D7giO3$fj^$7{Ao ݳN魮y8/p8lzx0E-Eh"Wm8s0MsɧJahewXSsO 4 ,d0Bzy"iCS 1 <e4uXq,9eNP5EBX*0B%ޣ«sEKð.M3,Fae 2e]q]&$A(؎4 |4SMeyUE4[iB(uJG cN8,'`sD}m&Ojkv_DMHnCAēN~7.< k7B2/Z?^9uV5weƼbJC!(RRfӅp( ghC$EV&޻pǥ+FoW'zm.N;|vR>p8OνG?rjhtEGc ]? ^cPCCCp <)1*P( x}}PTD"}_||868.$r>H 9Qz1:cՍېI%0ؿ(8AYY\l]dWӟ;oZ1aG}gEuL>{r/Nr޹X|YCCu]kv+s-˂i & ULò,T'JCA@Szz IL&|C=O6:KpQmHt[[7i{(C8E(Sl`8e!94MS1˧>4ff{kӴv IDAT}G1A_dC'9)>iYV,+ƓO<S rzB{y.a^?)/Ǯ9X2̂8R䩲W Iz]G^c яl6 ˴MeuMM :̼"8S\D,5譗/w㈕U!fҨk =1PH0pH`( ͙4o>Ļ}/+򍺮pI&Ŝ9OAKJ/^q}0@8w׿PF#}(;6F8]eAUXA@Q, ` 9 MզH\yJ4|OWTP(,z5p|5c HY4nlX;Ǯu,)O e`zqX @=] EƷ"B TU &Scwu\x׾U_9*_[*N8? C2!ھ};}P JaB[JZNf5MiwkQlY FҘ@74j,*b9,0g&ߘq=Y D?I Jy]KjլY/+&n0L6+04zw!+G*5]6 O@$ð^D4]#CGvg|K{xO~8Quo7ބeZQ!8 -w>?<d|.e+1nl3m5:a 46?Ͽ{+OfhA"9UU"łeM̀eY؎!8>N1b`@3 V0 YU,l a\eSOW5M+ 12Uy ebES8xjN!!|W|Mo03 ALz$\jGǑǝgB4V?ôrU' ªqc^ Gwϝ.HTc^S1IaZ;/oNd5B}XYێ]n MkU; JUuHB0RBs%,ʫGoB Uض#T㨊}t_<.vAQߚ#.va2LsgYC`Dxt`)}b5/  b@Q(qEP*t]E6Eee%G5b X%h po"A$k/Xx RI[n}G͸M@zq\@A*@ DID.fYds9,4ai'^Md<^h,p8\2@Q`!O\K%o͢{)FrxU#x6mMJoǫDMӎw\]<;R A e38ҫ.u(lSTׯK$ 4l&ʊ 4i@"*0fAe(dIp$]Ϧ/ˮO #㺫o< {~S*<[oi6u]q{KjI ǻ@?m{| f1~r&΀zedtڎLuc%/Mӵ UuP ]öNxygxS\]np/iph+~ɶ/1E Ǽf: ʴk\Xm6S5QUdc\hniC׮׀CA3+ n}myۦQKZWNe4/#:~|3:npm(g3phtMA>d_mNjinP??iTl:$ID&Ei쇦uY!QH%# s/14FS&5_?@є }4MKxйmgY^t9@lKйi ]Э}g_wwhnX۶0 @(+WU>SxaN a>rԖ=[!~qCQ‘X?kZfIENDB`webfakes/inst/examples/send-file/app.R0000644000176200001440000000024315026556433017415 0ustar liggesuserslibrary(webfakes) app <- new_app() app$use(mw_log()) app$use(mw_etag()) app$get("/logo", function(req, res) { res$send_file("Rlogo.png") }) app$listen(3000L) webfakes/inst/cert/0000755000176200001440000000000014740737023013762 5ustar liggesuserswebfakes/inst/cert/localhost/0000755000176200001440000000000014740737023015752 5ustar liggesuserswebfakes/inst/cert/localhost/server.key0000644000176200001440000000631014740737023017772 0ustar liggesusers-----BEGIN PRIVATE KEY----- MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDEdoXGbUDLiBgZ UfbF1EIIEJKmv3hJaFNVDOXrnw0Re5sLvzRA7y1MrNtLKwG+bNLgJyWn1SK6/FVB /05EDGcN7lIZfdBtaQNGOxIczv0Oy+y0/6VUMLtqu1DjXlnVsrjernkUQDtWosNW 292j4Tyvh06sL8mmjcKWEFkjIqdLc031lqWf7ehXMMnD22HBHm7lHNGfeiOL6nHr rfZJbWWYofu4D4/7BOoAQKQ+IiXjTAKGtXJOWLsJc4/VOZSAGjtcd9EvpO5RURLj Nk4BuV5rmqXlK7uVFulCooHT/SmF6fYBJv+TwHSOmyP24B8OXNUodA8ujiGuHglr esCKCxeMoQO1jWhMqjzbP2+BcikfYRaHuBTBnpSCaP/nig7QasVFh+n4InZn4FZd ZKHA38i2n/rq2ZhyQAZytSwusMTuh5Ijoiipz5LOAK3vx9cXyP64XdMsG9fBm4SY /xisP507k++8jkVsUGo+Yno4+sB9zcDql3bGDDk44/xjuSnkmOLCOsEB7ttD+DPe cPlEaR+oQasP8Y6xtY/Tq1XD3Ny3YOLBU78dJ0PW9g6JXrlTLkZW2Xpy85aA6Gkl js6XkawT6WFkXAPrRu8yxWgsWTeqUZmULR+Id5jARSq5CaHBAGaUGk5oajTEJ8oy Z98aeC1g4qFIimjakObchSk0FuW1/wIDAQABAoICABbjAnfjMlvY4Ysm6UCSlulU ROv3/ONQVqTfI8nByvFGclbOp3UJEpXkF903MrTO/fdEQuFntZa4M+vET4cjNWjX YpO6/GpChDHM9THgoHT2J1Uj6EwD1qbQZilBTJCAiYN81SNuzXrXleSrKF7MVm18 WHCRVe8j2eScHZuM5er8O7tobqhQPB4sKNUQMYsgfdANqL3oqfYavGVgQVi8eHbC KA4r10dpgyO/Drh48eumEdqaOKlih3zKYZnNY2dTpvwBWUqGRDJk53ZgqnsORS7z 4m+YG096+SGHcj29OEvJaEcqFov315w6poM+s197oQ6ytodjN2Pj9o+hdTH0/ivH hTQ2HuhPfphvyIWeE01Lly50XSOdx9Z/vp93IRXGu4n2JOSphF2fDdR4SjUmtrCB n250F0z2mWq3C+lVSlui9wH8EIqJMcp62hSGOEj5Eq0qlIjxl4PiJkRVHvJjxmOp 2ggOOsjIKpyv4dDjDvjUUkOOnv2vgPd7DbrfgbTNTwC5Mia2n6L3Tdg3e+yf50UH VktbuqNb4ujaTE3DNU7IGgwZ9Vn/Tylizpi1QcLQRyD1IKx0ket8C7GNhDkEEKQw k79Fpa2aRyXgfLlSc0RhriMhyIqloyGgVzFVnYg7JyFCHYo81UMs2LMKaT/8HOuD 2DjNHBuvyBpmYyPwES5BAoIBAQDm/Joce/1f79e/TdJZyTOfB4o4WKgcRKor/VES 7N/pkqYAqu4uJc7oacUVTEyba2WF35KgnepE+V0xuLeajSrDIrBhJKd04NXBmo0u NEPlDVx0pO8gwmeJ2gvikSnJTDXa2W9fNysA46Z+DS+JvCe8lFDF6ifxR+eLhCKV cMFw+5U28MqfJCHupf8jwfDpqfidKsj20Sj0Wj0Qilduq9J0FNI9chNgRZoOJgzU 6I28rmlWBsrD81q4zXnmc4d8DRykqi6EYkz6arGPVk4w26EOJNV9PEd4q2pJukya GjyoTK7Fnp1Ek7sIxbjh9mHav+AencPZ7QcZd6oDXIROD+VDAoIBAQDZvNsJ/UMX /vSIakm+ZAKvk/lEVLwPYpFvLhIdVvpYvL+pcRuIiIMJPqaXFyCKyRcPYP9nMWXN 8zLTnUypuJVFX/52UA9wubcVs6QLCLNMFI8PTfPPs2+QB4GNcSv+j7jn7ekeJm5H GKB7aVhSh9PEFS2BWLNv2CLklv5wHD7Rk+fMucaH7KPn6AU25uRnRqqXsUbSewns AjGRaWu7QTDWVUJg6kdocNjIWDqZM6nsp7aO7o1GUG/YGMFvSwRceQtvjGKA/9gQ RTFI8F2DxLFhPJvRNNUKoDGm6bSzs/Ca09L1aKaV3R+VXVvSZTLB1a+YKeawrT8s Mn/nMO8prkKVAoIBAQCMjQwhZPjqFYEMMQhcBefZTrc2TgwNF2MM3Vkl0Oj2sXs9 UMUZY3whQ6reqMy8jX77FO2dujlAuxOQG7vs2RU6I7N7iNg0cFLhOW/Ku5bMm3K0 r1+qaWCjKwCsXnQ0vqDOiBwSrfkG038NmGxivRDY2M7FfxPK51vnMwHwOOocG5nS EnbYmx3inzM+yNYU+I4E5HHgbakj9nzNwcAt4XNvmvPK280aeX+iOFj6fH8yXlZO OFfNIBkF9lHEfmvkef4B3GPtvfrlLWLZu0RcymeXuaYGTFWZAYTtU+Ukp+5c4jw+ l6NOhS37yoQTSt6EQtjXCFySEH6PapcS8Iq5DUcNAoIBAQCT2unGy8M+zTOSWtK+ xb0JK2uOGhgmPmHR5LAKWmDf1zQzRIpU2ZZZtcB8QwknFUxidhSZJ3MhOi9egado bN54YKoz/0Os4X/Q7c7Ma1kNpbxLwTx54zgzztULjjk4wLHoVKcDgUdLYg7AHxYJ 3RBRS6w99FTM8zEmlt4qlROXT1+Npu2IqYnX1beMw5eABf2bypb0IPbo28h7HOI6 IxedxAGyPATHiDG9QiRwmiOef3i5cIZgpAh+7riT8ZYBkXTRh7vwK0u2KLZB+G8Y Jn3pMLYCh2TPtV5iILtDeEI/cO4FFc5hX+mtjNrocS3ZcFiv9Gwht1N5mMU/4fvW Cu5NAoIBAQCfSalJ64EZyQvU/XOIfxaEBXvX8fTA22pmJn/Pf2AUJBlD+8hDufDH GNXnIXvgMHB6U5hz2p6WQFXKvjNdC+ERqKl5j/s7PQuH1PhJ1S6ulNQmME5qK2+2 bsoZIQCsIHkwvYjOlWxDsHSC6eiZF6Iy7K7tWRjJ9vDR5zZt6QfdC9ZJvkNbVKiz ugzQXEQB7MyPjH3ahRSecxMnSsUj/d3h9XEmFqSMiIPIXVfl01dqp1ZCc1BvmMAm JcdXyIypFlrgnQqwfXqD5IypRUNpsb2asBtDdCADcaYIkrZpHHyyNv6NUsWEylLg Y2Y8rdEwbYpTnwPlG4+8G6KuzQ8Ki0Ag -----END PRIVATE KEY----- webfakes/inst/cert/localhost/ca.key0000644000176200001440000000631014740737023017047 0ustar liggesusers-----BEGIN PRIVATE KEY----- MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCo9SyPFWJccHls sg/DKCTriDURHYJ3ho6G7nVBLK9BU7QHpKc/unK/5FtfD1MfCOf8feR+aRYBufvX 1+fXVoGmpLSXglg82BKZPIyVSJDBFmIuky6nMCwcH5/XYOa6Bx8Dt/BLn1fFXpPW 5lbbmuT8JHHMly0RsJQPAmbdtpbTKTmb6uoa6LCzFI4xFecH9ZsV9ZIqL3fFg0QP sxTN5f5wh23s19T/CuwRxIrprNbcesesZNxK8qPRY39uG9mryNce4yV6G/ilZ/6q A+yCFVAn9IkmvnPdn79sDCXq6li9Kjk6E2eMt3Umvwa9ti5n0nGLD/TZlMnUnmaR S+OjcBmj78bG1/n/frcYatIeT5MjPbgdmDaRVk1BM+Uaj6QGGqVqBMmLueVd6To+ oh0G9bWSBIzl/4SEYDtwOPJjCDac3nSaz1luP6J2SHxLamI8QBDx0E3kpZvHxQFm ie/gbpRNvHr/JL71iBdgsgorVWLIxr7d9Gnyv22GZDdGvlTHX1frlVlr1/BMwzb9 iob8NFYkNmlMZswQ3vNltLJpi8Ovta7VtqPANPspjoKMbmkF0At9h7FOkXd2LjsP VnFlXrGRAiVp5BWvV8sIJlKTPVTg5swXVtXSTf6tenJONLwNV74p7Ns1iia7ZFAg soOe2CcVv+AdpM9Plgpr2vsGRykUiQIDAQABAoICABgq/eU3s1qysgPE0rFhSCqy 0JhypqtvQWr2qCoa+LS5AusG9++LPYfKY/GMkSDC1uBMp8cXRBEaJ/afiSfJ1YDf VX/IotONOtfVi+x8tUwRZhjwb791ihG5ylT2JPreMucGxCYlFFqEpVQbnbgLB48z rV2NEGLT5dHhz5IOYLOy1W1CpJsVxtTO72oBDouaa8Uv2+kR4imMFcvDG4o6SHOT Q7uZwft7dfoyqYY0dYWTQIWd5c8Itzsn5t36uN+0OmVOK5m0b5RFdG2gYw/WeaFF fureWleM1sZfVHsua2QfqpDunqTHx0e0EoRHj4rFVP2F2knXWSmDQPuupdDGo7wO cmFcAJLMpYZb44g12050ZCcozRGGsEmk6nKf7omvwEhtT/wNjei0L0o78m3DjMqo +04x6od4cwz375aDW/BD5G2JZ+9enkHNEY3/XGSqcHUIfRCKi9xgX2WrDXvD+8FD rx3uftuIM+H/y57/UIWJ/6zVZJXDT4lWcXzsOob0MVDGnk6gfVoUt6EgoViS5Tma RAXXuuqkzhS+3UAdVQF/oIQZGYNlp1t8XjqYmPym9duzH9M0dETClwCvz/R0dND4 k2IMhMNDvL0xGryV8q16U2sm4Bmb10DT9UOOWlJ4qEUeHM1tWK6K+pXRfQeCjgGP OdrWTZY0YOwjYOBBWLkjAoIBAQDXk0xOoTiA7xxrZd1ni6c971PmhZrIVHsLoovG GKwW6pkxJlN66WdwNAw5DULQcjlrsiKqbt+p1U6q9l+bwDK+yOaEYOi58U2OqMID 8W0x46S6nJ+H7r9b9N3AVOaeIMuEeNLx/DM8cvyigsNtDgcmjbAFXmvWzM5QrR7g I0Vqww62/cZvi8xwDvPf+lM57erSUJYARie+Qk6tbqie1x76VNRTGMw/LwZiPpbY yek3X1hoeRqAIOpLIa8hq07tdnTvYJ19+FfMe7meG1KeH0wpAtssLnRsU0NdGM6+ +U92751Yf4pt3qTEZ2ou8ecs+BPqZeP5LlIMTXrNeVREu0xHAoIBAQDIo/5QqC5c N6yoBrSgqLP5tJCYFWu2iwb7L3fhCd3uphICM0mSbNx1jmX9LShacbIliIUQVImA IxsDw0g6Wn0UhhNbYjzJHMFbEjGC4pLfcwv70LpmulIDVRdE3r7z14uSz61A3wWp uJDozX9y61Zb3/84q4HjCP22bHm31yrZonoK07aXE47dUOwZG2veoGkjttZUlpXw 7HhXpW9zDuxxSqNyG88acB5txZQLabCwlJZehOOmvdVkCni/X05mKehTzplA4pgu uLRT0EEwuiL9QMNm7fjpTlSFlQr5WSVgYkBTJgHBTTYwPhxphXvEGhKGxxwM6ofs QyWc2LkCCJCvAoIBAGcNeh/ogBtasspActvJ7dP0sbX0Tm7Pu9ZvCMRVDQcTdNID EUsjgpgnuWQYi8UbpYlvKZUx1WfZmXauuju5YEjFvzSvIvGogbvdvommAt4jhZ7T uot/vSiXYN5Nd8VFxiR4odaeClwuV8jUG9npJ8/tUaTvYzvWwhXc/HKHSerkfgdK P28ZdExpSXnbr6d0rZmGfn55Cwyvo+7ShHcSPTPME4f5xcG6mCGk6/WMaBlZUej3 Y4y2r2nlG1RMEToBM5svI3qRml8dEjmbtB30tjKws9dmCa+zCfPaJRM0GSGxIBWr OqCVG0zsZt00NJ/Ro6ucs6Nt2jkZXMgW5QrKQocCggEBAMdWHrlVjdGywoehOd2Q HlbMrQdb6MrQL1xpGanrmqGaPrQO7l5aZ2En224AamIJKVue2cySoJU8y38eiejn s/MrDZox7IBGYFexqJ0Hq7HyZAqHolmjbQ3AgUC8KGysTg/K4q9bpA2tv9J7L88l voPC9JcB1iaQ7ThLZ1ZdoEXe5W9STcqk9MAuwJJlKvNg3XRNF32sqkVVOm6hfyuJ vSEFbYNV25nBoImgzWfVVmTpCsfXMTGc0p/0w2gmMQbRRe/Vh27ucRGiEg5fDhVy KIcBy+C8Nxrb5p9cpy16AudSVeQGE6JPqrGdU68GniMDYDqlINo4PFhfkcPVkWFS zyMCggEBAMrwXMF3LjIRWlaI9YHa+mCoJsc1bRAbkIH+ykIQnwgd6GrHzzYVWdL0 jE2GYDTPUei9JUOlrSLU3kZ5mR7yn0SjqhJyEJZ7E9ihQcaoY/alI77c/gLW5gkB THAPl0vvvNpG5zuK5AFrc9wQIVx675PorPbJPqC3kHx36ZEBKV7xza+folDs+6lb MAYYuvcRhkyAkA3kRVlp7BPhdIzn93tQuWEJ1p1/pWRIvTPYbtnCCbCku5TIM4D9 jlkgvpkITxFVbLOGt2N90aPGFl4VZWPEXqLq7E0BmPC1k6/0n1Joklzx6v5ivCnA vxahdzo5SsrJSyucKfAJObso9PxPpkc= -----END PRIVATE KEY----- webfakes/inst/cert/localhost/server.pem0000644000176200001440000001235614740737023017772 0ustar liggesusers-----BEGIN CERTIFICATE----- MIIF1zCCA7+gAwIBAgIB/zANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJFUzES MBAGA1UECAwJQmFyY2Vsb25hMRIwEAYDVQQHDAlCYXJjZWxvbmExGzAZBgNVBAoM EndlYmZha2VzLnItbGliLm9yZzELMAkGA1UECwwCQ0ExHjAcBgNVBAMMFWNhLndl YmZha2VzLnItbGliLm9yZzAgFw0yNTAxMTExNjQzMjNaGA8yMTI0MTIxODE2NDMy M1owZjELMAkGA1UEBhMCRVMxEjAQBgNVBAgMCUJhcmNlbG9uYTESMBAGA1UEBwwJ QmFyY2Vsb25hMRswGQYDVQQKDBJ3ZWJmYWtlcy5yLWxpYi5vcmcxEjAQBgNVBAMM CWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMR2hcZt QMuIGBlR9sXUQggQkqa/eEloU1UM5eufDRF7mwu/NEDvLUys20srAb5s0uAnJafV Irr8VUH/TkQMZw3uUhl90G1pA0Y7EhzO/Q7L7LT/pVQwu2q7UONeWdWyuN6ueRRA O1aiw1bb3aPhPK+HTqwvyaaNwpYQWSMip0tzTfWWpZ/t6FcwycPbYcEebuUc0Z96 I4vqceut9kltZZih+7gPj/sE6gBApD4iJeNMAoa1ck5Yuwlzj9U5lIAaO1x30S+k 7lFREuM2TgG5XmuapeUru5UW6UKigdP9KYXp9gEm/5PAdI6bI/bgHw5c1Sh0Dy6O Ia4eCWt6wIoLF4yhA7WNaEyqPNs/b4FyKR9hFoe4FMGelIJo/+eKDtBqxUWH6fgi dmfgVl1kocDfyLaf+urZmHJABnK1LC6wxO6HkiOiKKnPks4Are/H1xfI/rhd0ywb 18GbhJj/GKw/nTuT77yORWxQaj5iejj6wH3NwOqXdsYMOTjj/GO5KeSY4sI6wQHu 20P4M95w+URpH6hBqw/xjrG1j9OrVcPc3Ldg4sFTvx0nQ9b2DoleuVMuRlbZenLz loDoaSWOzpeRrBPpYWRcA+tG7zLFaCxZN6pRmZQtH4h3mMBFKrkJocEAZpQaTmhq NMQnyjJn3xp4LWDioUiKaNqQ5tyFKTQW5bX/AgMBAAGjdTBzMDEGA1UdEQQqMCiH BH8AAAGCCWxvY2FsaG9zdIIVbG9jYWxob3N0LmxvY2FsZG9tYWluMB0GA1UdDgQW BBSlIvWCz21lRoZ/8YoPGiN3dYpimTAfBgNVHSMEGDAWgBQHu0A+nYwAplDxwE7k vrdunNJXwDANBgkqhkiG9w0BAQsFAAOCAgEALcTwWDhp+t15OkxJhm6NISHoaSP0 YoaNqSd8kK6+JSQq2dhfuvDEwnhMfcmqhg/cMBFyeFD8wWFtxtbr8vLbqBfR42C2 jELokpuWHueyDR0wbIO+X5nYDZKAyhKrto8y8rW1zOdgJ3zTd1YLBGD4kBc64Iff uKvMNxCbFf+SpGSX8eUUWaPk4bimSBbJ7qyXUdRN4CvzUaSgshNqB3XTZ97HTs7a yiJPftzbGkwuotcGUYRKqLxigkeY956eyYbxUE/fbl1GmAYHhBkUHSVM1XHcSZjs wY7LXjcyk1s/fdMnaPXPw8Cjyzeh7ud2et1XnAVsRRLzbk/i0b3E60/JC0bEAgjb ozuCxde5JTaEY1Ob8siBtl6av2/nkAE7u4VAS/tQ1CNE5eBoEZHLasxUAwZAev7K kWGGc6aQsWfwuhZGlvH1+vkJ0LUsRZEUoPdKzRLrYfF9Vwe2hQbmRgDYHefnt/sm j6UTeBYzZfR/4I1G0JnXwYtcwVo2MYjnK3P96gaM4ZrwWd/UL7c8TttOnrwr4BYR ecjiTMk6gcK1bguukdTba5C4YV2o/+i1P41XzWbr6Z5Mh89KzEKznG0Nq4rbHQ+8 QiR/fj1px+TnDjFO/bbjXWccIVGV2pdvful2nRCdCekXFkycn6mxr3qtOq7QBOTt xJiRqw2aFCnhX2k= -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDEdoXGbUDLiBgZ UfbF1EIIEJKmv3hJaFNVDOXrnw0Re5sLvzRA7y1MrNtLKwG+bNLgJyWn1SK6/FVB /05EDGcN7lIZfdBtaQNGOxIczv0Oy+y0/6VUMLtqu1DjXlnVsrjernkUQDtWosNW 292j4Tyvh06sL8mmjcKWEFkjIqdLc031lqWf7ehXMMnD22HBHm7lHNGfeiOL6nHr rfZJbWWYofu4D4/7BOoAQKQ+IiXjTAKGtXJOWLsJc4/VOZSAGjtcd9EvpO5RURLj Nk4BuV5rmqXlK7uVFulCooHT/SmF6fYBJv+TwHSOmyP24B8OXNUodA8ujiGuHglr esCKCxeMoQO1jWhMqjzbP2+BcikfYRaHuBTBnpSCaP/nig7QasVFh+n4InZn4FZd ZKHA38i2n/rq2ZhyQAZytSwusMTuh5Ijoiipz5LOAK3vx9cXyP64XdMsG9fBm4SY /xisP507k++8jkVsUGo+Yno4+sB9zcDql3bGDDk44/xjuSnkmOLCOsEB7ttD+DPe cPlEaR+oQasP8Y6xtY/Tq1XD3Ny3YOLBU78dJ0PW9g6JXrlTLkZW2Xpy85aA6Gkl js6XkawT6WFkXAPrRu8yxWgsWTeqUZmULR+Id5jARSq5CaHBAGaUGk5oajTEJ8oy Z98aeC1g4qFIimjakObchSk0FuW1/wIDAQABAoICABbjAnfjMlvY4Ysm6UCSlulU ROv3/ONQVqTfI8nByvFGclbOp3UJEpXkF903MrTO/fdEQuFntZa4M+vET4cjNWjX YpO6/GpChDHM9THgoHT2J1Uj6EwD1qbQZilBTJCAiYN81SNuzXrXleSrKF7MVm18 WHCRVe8j2eScHZuM5er8O7tobqhQPB4sKNUQMYsgfdANqL3oqfYavGVgQVi8eHbC KA4r10dpgyO/Drh48eumEdqaOKlih3zKYZnNY2dTpvwBWUqGRDJk53ZgqnsORS7z 4m+YG096+SGHcj29OEvJaEcqFov315w6poM+s197oQ6ytodjN2Pj9o+hdTH0/ivH hTQ2HuhPfphvyIWeE01Lly50XSOdx9Z/vp93IRXGu4n2JOSphF2fDdR4SjUmtrCB n250F0z2mWq3C+lVSlui9wH8EIqJMcp62hSGOEj5Eq0qlIjxl4PiJkRVHvJjxmOp 2ggOOsjIKpyv4dDjDvjUUkOOnv2vgPd7DbrfgbTNTwC5Mia2n6L3Tdg3e+yf50UH VktbuqNb4ujaTE3DNU7IGgwZ9Vn/Tylizpi1QcLQRyD1IKx0ket8C7GNhDkEEKQw k79Fpa2aRyXgfLlSc0RhriMhyIqloyGgVzFVnYg7JyFCHYo81UMs2LMKaT/8HOuD 2DjNHBuvyBpmYyPwES5BAoIBAQDm/Joce/1f79e/TdJZyTOfB4o4WKgcRKor/VES 7N/pkqYAqu4uJc7oacUVTEyba2WF35KgnepE+V0xuLeajSrDIrBhJKd04NXBmo0u NEPlDVx0pO8gwmeJ2gvikSnJTDXa2W9fNysA46Z+DS+JvCe8lFDF6ifxR+eLhCKV cMFw+5U28MqfJCHupf8jwfDpqfidKsj20Sj0Wj0Qilduq9J0FNI9chNgRZoOJgzU 6I28rmlWBsrD81q4zXnmc4d8DRykqi6EYkz6arGPVk4w26EOJNV9PEd4q2pJukya GjyoTK7Fnp1Ek7sIxbjh9mHav+AencPZ7QcZd6oDXIROD+VDAoIBAQDZvNsJ/UMX /vSIakm+ZAKvk/lEVLwPYpFvLhIdVvpYvL+pcRuIiIMJPqaXFyCKyRcPYP9nMWXN 8zLTnUypuJVFX/52UA9wubcVs6QLCLNMFI8PTfPPs2+QB4GNcSv+j7jn7ekeJm5H GKB7aVhSh9PEFS2BWLNv2CLklv5wHD7Rk+fMucaH7KPn6AU25uRnRqqXsUbSewns AjGRaWu7QTDWVUJg6kdocNjIWDqZM6nsp7aO7o1GUG/YGMFvSwRceQtvjGKA/9gQ RTFI8F2DxLFhPJvRNNUKoDGm6bSzs/Ca09L1aKaV3R+VXVvSZTLB1a+YKeawrT8s Mn/nMO8prkKVAoIBAQCMjQwhZPjqFYEMMQhcBefZTrc2TgwNF2MM3Vkl0Oj2sXs9 UMUZY3whQ6reqMy8jX77FO2dujlAuxOQG7vs2RU6I7N7iNg0cFLhOW/Ku5bMm3K0 r1+qaWCjKwCsXnQ0vqDOiBwSrfkG038NmGxivRDY2M7FfxPK51vnMwHwOOocG5nS EnbYmx3inzM+yNYU+I4E5HHgbakj9nzNwcAt4XNvmvPK280aeX+iOFj6fH8yXlZO OFfNIBkF9lHEfmvkef4B3GPtvfrlLWLZu0RcymeXuaYGTFWZAYTtU+Ukp+5c4jw+ l6NOhS37yoQTSt6EQtjXCFySEH6PapcS8Iq5DUcNAoIBAQCT2unGy8M+zTOSWtK+ xb0JK2uOGhgmPmHR5LAKWmDf1zQzRIpU2ZZZtcB8QwknFUxidhSZJ3MhOi9egado bN54YKoz/0Os4X/Q7c7Ma1kNpbxLwTx54zgzztULjjk4wLHoVKcDgUdLYg7AHxYJ 3RBRS6w99FTM8zEmlt4qlROXT1+Npu2IqYnX1beMw5eABf2bypb0IPbo28h7HOI6 IxedxAGyPATHiDG9QiRwmiOef3i5cIZgpAh+7riT8ZYBkXTRh7vwK0u2KLZB+G8Y Jn3pMLYCh2TPtV5iILtDeEI/cO4FFc5hX+mtjNrocS3ZcFiv9Gwht1N5mMU/4fvW Cu5NAoIBAQCfSalJ64EZyQvU/XOIfxaEBXvX8fTA22pmJn/Pf2AUJBlD+8hDufDH GNXnIXvgMHB6U5hz2p6WQFXKvjNdC+ERqKl5j/s7PQuH1PhJ1S6ulNQmME5qK2+2 bsoZIQCsIHkwvYjOlWxDsHSC6eiZF6Iy7K7tWRjJ9vDR5zZt6QfdC9ZJvkNbVKiz ugzQXEQB7MyPjH3ahRSecxMnSsUj/d3h9XEmFqSMiIPIXVfl01dqp1ZCc1BvmMAm JcdXyIypFlrgnQqwfXqD5IypRUNpsb2asBtDdCADcaYIkrZpHHyyNv6NUsWEylLg Y2Y8rdEwbYpTnwPlG4+8G6KuzQ8Ki0Ag -----END PRIVATE KEY----- webfakes/inst/cert/localhost/generate.sh0000755000176200001440000000172014740737023020103 0ustar liggesusers#! /bin/bash # https://transang.me/create-a-multiple-domains-self-signed-ssl-certificate-with-testing-scripts/ # https://github.com/civetweb/civetweb/blob/master/docs/OpenSSL.md openssl genrsa -out server.key 4096 openssl req \ -new \ -key server.key \ -nodes \ -out server.csr \ -subj "/C=ES/ST=Barcelona/L=Barcelona/O=webfakes.r-lib.org/CN=localhost" \ -addext "subjectAltName=IP:127.0.0.1,DNS:localhost,DNS:localhost.localdomain" openssl genrsa -out ca.key 4096 openssl req \ -new \ -x509 \ -nodes \ -days 36500 \ -key ca.key \ -out ca.crt \ -subj "/C=ES/ST=Barcelona/L=Barcelona/O=webfakes.r-lib.org/OU=CA/CN=ca.webfakes.r-lib.org" openssl x509 \ -req \ -in server.csr \ -CAkey ca.key \ -CA ca.crt \ -set_serial -01 \ -out server.crt \ -days 36500 \ -sha256 \ -extfile <(printf "subjectAltName=IP:127.0.0.1,DNS:localhost,DNS:localhost.localdomain") openssl verify -CAfile ca.crt server.crt cp server.crt server.pem cat server.key >> server.pem webfakes/inst/cert/localhost/server.csr0000644000176200001440000000337514740737023020001 0ustar liggesusers-----BEGIN CERTIFICATE REQUEST----- MIIE7zCCAtcCAQAwZjELMAkGA1UEBhMCRVMxEjAQBgNVBAgMCUJhcmNlbG9uYTES MBAGA1UEBwwJQmFyY2Vsb25hMRswGQYDVQQKDBJ3ZWJmYWtlcy5yLWxpYi5vcmcx EjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC ggIBAMR2hcZtQMuIGBlR9sXUQggQkqa/eEloU1UM5eufDRF7mwu/NEDvLUys20sr Ab5s0uAnJafVIrr8VUH/TkQMZw3uUhl90G1pA0Y7EhzO/Q7L7LT/pVQwu2q7UONe WdWyuN6ueRRAO1aiw1bb3aPhPK+HTqwvyaaNwpYQWSMip0tzTfWWpZ/t6FcwycPb YcEebuUc0Z96I4vqceut9kltZZih+7gPj/sE6gBApD4iJeNMAoa1ck5Yuwlzj9U5 lIAaO1x30S+k7lFREuM2TgG5XmuapeUru5UW6UKigdP9KYXp9gEm/5PAdI6bI/bg Hw5c1Sh0Dy6OIa4eCWt6wIoLF4yhA7WNaEyqPNs/b4FyKR9hFoe4FMGelIJo/+eK DtBqxUWH6fgidmfgVl1kocDfyLaf+urZmHJABnK1LC6wxO6HkiOiKKnPks4Are/H 1xfI/rhd0ywb18GbhJj/GKw/nTuT77yORWxQaj5iejj6wH3NwOqXdsYMOTjj/GO5 KeSY4sI6wQHu20P4M95w+URpH6hBqw/xjrG1j9OrVcPc3Ldg4sFTvx0nQ9b2Dole uVMuRlbZenLzloDoaSWOzpeRrBPpYWRcA+tG7zLFaCxZN6pRmZQtH4h3mMBFKrkJ ocEAZpQaTmhqNMQnyjJn3xp4LWDioUiKaNqQ5tyFKTQW5bX/AgMBAAGgRDBCBgkq hkiG9w0BCQ4xNTAzMDEGA1UdEQQqMCiHBH8AAAGCCWxvY2FsaG9zdIIVbG9jYWxo b3N0LmxvY2FsZG9tYWluMA0GCSqGSIb3DQEBCwUAA4ICAQAvkGu4XksSsT74H7ND nA0GzARCmNkOF6hiMDFxBrQrmYP2AawMPJp7YfKX+3rU2yh/2QrQlhSLtvdTGigj eMjR0ZlET//tsFUW1Wpsun0WUFdBBgaH8fm1h7PkI+LZOcNq8SZ69PUYSYVEsi/Y dY4GfYCIRkaL6sbev8uB6lohXp5fPjwlQZ/uxpaOvEc3AiT9L4bcjc2t92qxHwjd KB8EpNSaGaNBu3HdJ/JAHda81AG/nwnILm4ZZ+aKfVrL4sTBnk9ZNrAG9TVD/yXu UUNS0/z6tYpjx+Efs/BXdYYliDRkC1PzntJuskmeBiwYxU1PbWCEIbdERilsynrG Z33p8bdrbBqXjuvqxVdDtjyn2cFGxlCJk20JTHRGbBkQeNzqeRbtTCcOzwfv7+Iq 5HqIrSBce08CvcrfRDNyJdcZK2GhNuj5NK2coYlNSyES4U98E7zs9Gm0DwYMSMtm SoiBQcHZ6413F9JWf+s0LMsX/EK3s3BwYCpuA+Nb2+CRxeN/ljvZUUC08EcXJFLE FYlbFlgqPptMPvIk22jVeUXj/Wcz8E2rFi3SC+DbK8F6zgqRfJ9POTYoYqQMza3k 5nnhWd+r1vJ4US+zK7t6iI+g6S+j5Cbu60DkoeMsDQXsrKjsIoNmVM3vT07h88ym E7frtVoDUX0VZeYumCXmPn+1og== -----END CERTIFICATE REQUEST----- webfakes/inst/cert/localhost/server.crt0000644000176200001440000000404614740737023017776 0ustar liggesusers-----BEGIN CERTIFICATE----- MIIF1zCCA7+gAwIBAgIB/zANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJFUzES MBAGA1UECAwJQmFyY2Vsb25hMRIwEAYDVQQHDAlCYXJjZWxvbmExGzAZBgNVBAoM EndlYmZha2VzLnItbGliLm9yZzELMAkGA1UECwwCQ0ExHjAcBgNVBAMMFWNhLndl YmZha2VzLnItbGliLm9yZzAgFw0yNTAxMTExNjQzMjNaGA8yMTI0MTIxODE2NDMy M1owZjELMAkGA1UEBhMCRVMxEjAQBgNVBAgMCUJhcmNlbG9uYTESMBAGA1UEBwwJ QmFyY2Vsb25hMRswGQYDVQQKDBJ3ZWJmYWtlcy5yLWxpYi5vcmcxEjAQBgNVBAMM CWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMR2hcZt QMuIGBlR9sXUQggQkqa/eEloU1UM5eufDRF7mwu/NEDvLUys20srAb5s0uAnJafV Irr8VUH/TkQMZw3uUhl90G1pA0Y7EhzO/Q7L7LT/pVQwu2q7UONeWdWyuN6ueRRA O1aiw1bb3aPhPK+HTqwvyaaNwpYQWSMip0tzTfWWpZ/t6FcwycPbYcEebuUc0Z96 I4vqceut9kltZZih+7gPj/sE6gBApD4iJeNMAoa1ck5Yuwlzj9U5lIAaO1x30S+k 7lFREuM2TgG5XmuapeUru5UW6UKigdP9KYXp9gEm/5PAdI6bI/bgHw5c1Sh0Dy6O Ia4eCWt6wIoLF4yhA7WNaEyqPNs/b4FyKR9hFoe4FMGelIJo/+eKDtBqxUWH6fgi dmfgVl1kocDfyLaf+urZmHJABnK1LC6wxO6HkiOiKKnPks4Are/H1xfI/rhd0ywb 18GbhJj/GKw/nTuT77yORWxQaj5iejj6wH3NwOqXdsYMOTjj/GO5KeSY4sI6wQHu 20P4M95w+URpH6hBqw/xjrG1j9OrVcPc3Ldg4sFTvx0nQ9b2DoleuVMuRlbZenLz loDoaSWOzpeRrBPpYWRcA+tG7zLFaCxZN6pRmZQtH4h3mMBFKrkJocEAZpQaTmhq NMQnyjJn3xp4LWDioUiKaNqQ5tyFKTQW5bX/AgMBAAGjdTBzMDEGA1UdEQQqMCiH BH8AAAGCCWxvY2FsaG9zdIIVbG9jYWxob3N0LmxvY2FsZG9tYWluMB0GA1UdDgQW BBSlIvWCz21lRoZ/8YoPGiN3dYpimTAfBgNVHSMEGDAWgBQHu0A+nYwAplDxwE7k vrdunNJXwDANBgkqhkiG9w0BAQsFAAOCAgEALcTwWDhp+t15OkxJhm6NISHoaSP0 YoaNqSd8kK6+JSQq2dhfuvDEwnhMfcmqhg/cMBFyeFD8wWFtxtbr8vLbqBfR42C2 jELokpuWHueyDR0wbIO+X5nYDZKAyhKrto8y8rW1zOdgJ3zTd1YLBGD4kBc64Iff uKvMNxCbFf+SpGSX8eUUWaPk4bimSBbJ7qyXUdRN4CvzUaSgshNqB3XTZ97HTs7a yiJPftzbGkwuotcGUYRKqLxigkeY956eyYbxUE/fbl1GmAYHhBkUHSVM1XHcSZjs wY7LXjcyk1s/fdMnaPXPw8Cjyzeh7ud2et1XnAVsRRLzbk/i0b3E60/JC0bEAgjb ozuCxde5JTaEY1Ob8siBtl6av2/nkAE7u4VAS/tQ1CNE5eBoEZHLasxUAwZAev7K kWGGc6aQsWfwuhZGlvH1+vkJ0LUsRZEUoPdKzRLrYfF9Vwe2hQbmRgDYHefnt/sm j6UTeBYzZfR/4I1G0JnXwYtcwVo2MYjnK3P96gaM4ZrwWd/UL7c8TttOnrwr4BYR ecjiTMk6gcK1bguukdTba5C4YV2o/+i1P41XzWbr6Z5Mh89KzEKznG0Nq4rbHQ+8 QiR/fj1px+TnDjFO/bbjXWccIVGV2pdvful2nRCdCekXFkycn6mxr3qtOq7QBOTt xJiRqw2aFCnhX2k= -----END CERTIFICATE----- webfakes/inst/cert/localhost/ca.crt0000644000176200001440000000406214740737023017051 0ustar liggesusers-----BEGIN CERTIFICATE----- MIIF4TCCA8mgAwIBAgIUT3y6fx57eiwoN3axReC0Aypxb64wDQYJKoZIhvcNAQEL BQAwfzELMAkGA1UEBhMCRVMxEjAQBgNVBAgMCUJhcmNlbG9uYTESMBAGA1UEBwwJ QmFyY2Vsb25hMRswGQYDVQQKDBJ3ZWJmYWtlcy5yLWxpYi5vcmcxCzAJBgNVBAsM AkNBMR4wHAYDVQQDDBVjYS53ZWJmYWtlcy5yLWxpYi5vcmcwIBcNMjUwMTExMTY0 MzIzWhgPMjEyNDEyMTgxNjQzMjNaMH8xCzAJBgNVBAYTAkVTMRIwEAYDVQQIDAlC YXJjZWxvbmExEjAQBgNVBAcMCUJhcmNlbG9uYTEbMBkGA1UECgwSd2ViZmFrZXMu ci1saWIub3JnMQswCQYDVQQLDAJDQTEeMBwGA1UEAwwVY2Eud2ViZmFrZXMuci1s aWIub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqPUsjxViXHB5 bLIPwygk64g1ER2Cd4aOhu51QSyvQVO0B6SnP7pyv+RbXw9THwjn/H3kfmkWAbn7 19fn11aBpqS0l4JYPNgSmTyMlUiQwRZiLpMupzAsHB+f12DmugcfA7fwS59XxV6T 1uZW25rk/CRxzJctEbCUDwJm3baW0yk5m+rqGuiwsxSOMRXnB/WbFfWSKi93xYNE D7MUzeX+cIdt7NfU/wrsEcSK6azW3HrHrGTcSvKj0WN/bhvZq8jXHuMlehv4pWf+ qgPsghVQJ/SJJr5z3Z+/bAwl6upYvSo5OhNnjLd1Jr8GvbYuZ9Jxiw/02ZTJ1J5m kUvjo3AZo+/Gxtf5/363GGrSHk+TIz24HZg2kVZNQTPlGo+kBhqlagTJi7nlXek6 PqIdBvW1kgSM5f+EhGA7cDjyYwg2nN50ms9Zbj+idkh8S2piPEAQ8dBN5KWbx8UB Zonv4G6UTbx6/yS+9YgXYLIKK1ViyMa+3fRp8r9thmQ3Rr5Ux19X65VZa9fwTMM2 /YqG/DRWJDZpTGbMEN7zZbSyaYvDr7Wu1bajwDT7KY6CjG5pBdALfYexTpF3di47 D1ZxZV6xkQIlaeQVr1fLCCZSkz1U4ObMF1bV0k3+rXpyTjS8DVe+KezbNYomu2RQ ILKDntgnFb/gHaTPT5YKa9r7BkcpFIkCAwEAAaNTMFEwHQYDVR0OBBYEFAe7QD6d jACmUPHATuS+t26c0lfAMB8GA1UdIwQYMBaAFAe7QD6djACmUPHATuS+t26c0lfA MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAHKm0AXnOcdAVpCu 3EEOCi40bUkj0o35dP4LjoOMK6JcbKJS+eEOMGGRvgn0+B0eq+a9nTgpPj7Ewwg6 rJzUO10/PhcoWTd9pVQhi+7JNbCYKDqFOLXEq+9TlP40gbdVUwkhrOYz+cbZXPUO J01at2f/wnwFPjCdvY6RCsUkdOT5ocOpG9fjvQMGVK/HBZDCa7HwaCK+9uad8hlv WNOiwdPJjqURQ/GYxQF+m8XyGuIANc1HElAOBD1SekfRxEyxNAVHPDNjTq+yxVuZ 7kSIbZwaIBxTy0UDqlUtDDz4fN1tcDWDsSApHlsodQKu0+hBKa1Yy6IKeMp7wpAf AkDdLifK5pKJsf6aSyKUUv69BYQVgdeu7Pc9cXl1uJoRpf7VhidtxsE6570aEot5 7p18tOwamDHQWmPpVJxxWufLwvHoWg195TH2YpeN1kr394+9OKOuvvuUcNj5gCKU eZuyC0fEFGoRgHkUZHMZn8MUd24eipHqcRjzSZ1OVt+fQqdmL/zm4FbkNLVdqcSh If+9PRpWnvVcPSdT4KmLTi28izp4iF1dD2NaVpCofz3w15XxtBq7cP/HnXB/4nFe tfe9i1bL8EdG+dVbl+w5kOQKKiU+0OwbpTW6sAJjbMlpeSyu9JNi05kWAXNlUV/y dclMC8hq1gQTkfIrvY2JfUMNbrrO -----END CERTIFICATE----- webfakes/README.md0000644000176200001440000001122115026556433013326 0ustar liggesusers # webfakes > Your own web server for happy HTTP testing [![R build status](https://github.com/r-lib/webfakes/workflows/R-CMD-check/badge.svg)](https://github.com/r-lib/webfakes/actions) [![CRAN status](https://www.r-pkg.org/badges/version/webfakes)](https://CRAN.R-project.org/package=webfakes) [![R-CMD-check](https://github.com/r-lib/webfakes/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/r-lib/webfakes/actions/workflows/R-CMD-check.yaml) [![Codecov test coverage](https://codecov.io/gh/r-lib/webfakes/graph/badge.svg)](https://app.codecov.io/gh/r-lib/webfakes) Lightweight fake web apps for testing. Built using the [civetweb](https://github.com/civetweb/civetweb) embedded web server. ## Features - Complete web app framework, define handlers for HTTP requests in R. - Write your own app for your custom test cases; our use app similar to the `https://httpbin.org` API, so often you don’t need to write your own web app (e.g. if you are writing an HTTP client (httr, curl, crul). - Run one web app per test suite, per test file or per test case. - Flexible path matching, with parameters and regular expressions. - Built in templating system using glue or bring your own template engine. - Middleware to parse JSON, multipart and URL encoded request bodies. - A web app is just an R object. It can be saved to disk, copied to another R process, etc. - A web app is extensible, by adding new routes and middleware to it. - Helper functions for sending JSON, files from disk, etc. - App-specific environment to store any data including data from requests to the fake app. - After a web app is launched from R, you can interact with it from R but also from the command line, your browser, etc. Nice for debugging. - The web server runs in the R process, so it has no problems with local firewalls. - Multi-threaded web server supports concurrent HTTP requests. - Limit download speed to simulate low bandwidth. ## Optional dependencies - The jsonlite package is needed for the `mw_json()` middleware, the `response$send_json()` method and the `httpbin_app()` app. - The glue package is needed for the `tmpl_glue()` template engine. - The callr package is needed for `new_app_process()` and `local_app_process` to work. - The `/brotli` endpoint of `httpbin_app()` needs the brotli package. - The `/deflate` endpoint of `httpbin_app()` needs the zip package. - The `/digest-auth` endpoint of `httpbin_app()` needs the digest package. - `git_app()` requires the processx package. ## Installation Install the release version from CRAN: ``` r install.packages("webfakes") ``` If you need the development version of the package, install it from GitHub: ``` r pak::pak("r-lib/webfakes") ``` ## Usage Start a web app at the beginning of your tests or test file, and stop it after. Here is an example with the testthat package. Suppose you want to test that your `get_hello()` function can query an API: `local_app_process()` helps you clean up the web server process after the test block, or test file. It is similar to the `withr::local_*` functions. ``` r app <- webfakes::new_app() app$get("/hello/:user", function(req, res) { res$send(paste0("Hello ", req$params$user, "!")) }) web <- webfakes::local_app_process(app) test_that("can use hello API", { url <- web$url("/hello/Gabor") expect_equal(get_hello(url), "Hello Gabor!") }) ``` When testing HTTP clients you can often use the built in `httpbin_app()`: ``` r httpbin <- webfakes::local_app_process(webfakes::httpbin_app()) ``` ``` r test_that("HTTP errors are caught", { url <- httpbin$url("/status/404") resp <- httr::GET(url) expect_error(httr::stop_for_status(resp), class = "http_404") }) ``` #> Test passed 🌈 ## Documentation See ## Links ### Other solutions for HTTP testing in R: - [vcr](https://github.com/ropensci/vcr) - [httptest](https://github.com/nealrichardson/httptest) ### R web application frameworks webfakes focuses on testing, these packages are for writing real web apps: - [shiny](https://github.com/rstudio/shiny) - [opencpu](https://www.opencpu.org/) - [plumber](https://github.com/rstudio/plumber) - [fiery](https://github.com/thomasp85/fiery) - [RestRserve](https://github.com/rexyai/RestRserve) ## Code of Conduct Please note that the webfakes project is released with a [Contributor Code of Conduct](https://webfakes.r-lib.org/dev/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. ## License MIT © RStudio webfakes/configure0000755000176200001440000000163315026563043013757 0ustar liggesusers#! /usr/bin/env sh # Check that this is not just ./configure. We need to run this # from R CMD INSTALL, to have the R env vars set. if [ -z "$R_HOME" ]; then echo >&2 R_HOME is not set, are you running R CMD INSTALL? exit 1 fi # Find the R binary we need to use. This is a bit trickier on # Windows, because it has two architectures. On windows R_ARCH_BIN # is set, so this should work everywhere. RBIN="${R_HOME}/bin${R_ARCH_BIN}/R" unset WINDOWS if [ "$R_OSTYPE" = "windows" ]; then WINDOWS=true; fi OBJECTS=`ls src/*.c | sed 's/[.]c$/.o/' | sed 's|^src/||'` OBJECTS="`echo $OBJECTS | tr '\n' ' '`" MBED="$OBJECTS `ls src/mbedtls/library/*.c | sed 's/[.]c$/.o/' | sed 's|^src/||'`" MBED="`echo $MBED | tr '\n' ' '`" if [ -n "$WINDOWS" ]; then LIBS=-lws2_32 fi cat src/Makevars.in | \ sed "s|@OBJECTS@|${OBJECTS}|" | \ sed "s|@MBED@|${MBED}|" | \ sed "s/@LIBS@/${LIBS}/" \ > src/Makevars webfakes/man/0000755000176200001440000000000015026557545012632 5ustar liggesuserswebfakes/man/local_app_process.Rd0000644000176200001440000000144314172041777016607 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/local-app-process.R \name{local_app_process} \alias{local_app_process} \title{App process that is cleaned up automatically} \usage{ local_app_process(app, ..., .local_envir = parent.frame()) } \arguments{ \item{app}{\code{webfakes_app} object, the web app to run.} \item{...}{Passed to \code{\link[=new_app_process]{new_app_process()}}.} \item{.local_envir}{The environment to attach the process cleanup to. Typically a frame. When this frame finishes, the process is stopped.} } \description{ You can start the process with an explicit \verb{$start()} call. Alternatively it starts up at the first \verb{$url()} or \verb{$get_port()} call. } \seealso{ \code{\link[=new_app_process]{new_app_process()}} for more details. } webfakes/man/rmd-fragments/0000755000176200001440000000000014172041777015374 5ustar liggesuserswebfakes/man/rmd-fragments/oauth2.Rmd0000644000176200001440000000120714172041777017242 0ustar liggesusersThe webfakes package comes with two fake apps that allow to imitate the OAuth2.0 flow in your test cases. (See [Aaron Parecki's tutorial](https://aaronparecki.com/oauth-2-simplified/) for a good introduction to OAuth2.0.) One app (`oauth2_resource_app()`) is the API server that serves both as the resource and provides authorization. `oauth2_third_party_app()` plays the role of the third-party app. They are useful when testing or demonstrating code handling OAuth2.0 authorization, token caching, etc. in a package. The apps can be used in your tests directly, or you could adapt one or both of them to better mimic a particular OAuth2.0 flow. webfakes/man/glossary.Rd0000644000176200001440000001057614740243712014763 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/docs.R \name{glossary} \alias{glossary} \title{webfakes glossary} \description{ webfakes glossary } \section{Webfakes glossary}{ The webfakes package uses vocabulary that is standard for web apps, especially those developed with Express.js, but not necessarily well known to all R package developers. \subsection{app}{ (Also: fake web app, webfakes app.) A web application that can be served by webfakes's web server, typically in another process, an \emph{app process}. Sometimes we call it a \emph{fake} web app, to emphasize that we use it for testing real web apps and APIs. You can create a webfakes app with the \code{new_app()} function. A webfakes app is an R object that you can save to disk with \code{saveRDS()} , and you can also include it in your package. You can start an with its \verb{$listen()} method. Since the main R process runs that test suite code, you usually run them in a subprocess, see \code{new_app_process()} or \code{local_app_process()}. } \subsection{app process}{ (Also: web server process, webfakes subprocess.) An app process is an R subprocess, started from the main R process, to serve a webfakes \emph{app}. You can create an app process object with \code{new_app_process()} or \code{local_app_process()}. By default the actual process does not start yet, when you create it. You can start it explicitly with the \verb{$start} method of the app process object, or by querying its URL with \verb{$url()} or its port with \verb{$get_port()}. For test cases, you typically start app processes at these places: \itemize{ \item In a \code{setup*.R} file, to start an app that the whole test suite can use. \item Alternatively, in a \code{helper*.R} file, to start an app that the whole test suite can use, and it works better for interactive development. \item At the beginning of a test file, to create an app for a single test file. \item Inside \code{test_that()}, to create an app for a single test block. } See the How-to for details about each. } \subsection{handler}{ (Or handler function.) A handler is a \emph{route} or a \emph{middleware}. } \subsection{handler stack}{ This is a stack of handler functions, which are called by the app one after the other, passing the request and response objects to them. Handlers typically manipulate the request and/or response objects. A terminal handler instructs the app to return the response to the HTTP client. A non-terminal handler tells the app to keep calling handlers, by returning the string \code{"next"}. } \subsection{httpbin app}{ This is an example app, which implements the excellent \verb{https://httpbin.org/} web service. You can use it to simulate certain HTTP responses. It is most handy for HTTP clients, but potentially useful for other tools as well. Use \code{httpbin_app()} to create an instance of this app. } \subsection{middleware}{ A middleware is a handler function that is not bound to a path. It is called by the router, like other handler functions. It may manipulate the request or the response, or can have a side effect. Some example built-in middleware functions in webfakes: \itemize{ \item \code{mw_json()} parses a request's JSON body into an R object. \item \code{mw_log()} logs requests and responses to the screen or to a file. \item \code{mw_static()} serves static files from the directory. } You can also write your own middleware functions. } \subsection{path matching}{ The router performs path matching when it goes over the handler stack. If the HTTP method and path of a \emph{route} match the HTTP method and URL of the request, then the handler is called, otherwise it is not. Paths can have parameters and be regular expressions. See \code{?new_regexp()} for regular expressions and "Path parameters" in \code{?new_app()} for parameters. } \subsection{route}{ A route is a handler function that is bound to certain paths of you web app. If the request URL matches the path of the route, then the handler function is called, to give it a chance to send the appropriate response. Route paths may have parameters or they can be regular expressions in webfakes. } \subsection{routing}{ Routing is the process of going over the handlers stack, and calling handler functions, one after the other, until one handles the request. If a handler function is a \emph{route}, then the router only calls it if its path matches the request URL. } } webfakes/man/introduction.Rd0000644000176200001440000001627015026555712015642 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/docs.R \name{introduction} \alias{introduction} \title{Happy HTTP testing with webfakes} \description{ Happy HTTP testing with webfakes } \section{Happy HTTP testing with webfakes}{ \subsection{What is webfakes?}{ Webfakes is an R package that can spin up web servers on your machine to facilitate testing R code. R code that needs an HTTP connection is not trivial to test: \itemize{ \item Connectivity problems might prevent the tests from accessing the web server. \item The web server might need authentication, and it is not easy to convey login information to the test suite in a secure way. \item The web server might have rate limits, i.e, it limits the number of queries per hour or day, causing some spurious test failures. \item You might want to test in non-normal conditions, e.g. with low bandwidth, or when the client is rate limited. These conditions don't normally happen on the web server and they are hard to trigger. } With webfakes you can easily start a custom web app, that is running on the local machine. \itemize{ \item Webfakes does not need a network connection. \item Webfakes does not need authentication. Well, unless you want it to. \item Webfakes does not have rate limits. \item Webfakes can simulate low bandwidth, or a broken connection. } } \subsection{Webfakes vs mocking}{ Mocking is a general technique to mimic the behavior of a function or object that is needed in test case. In the case of HTTP requests, this typically means that both the request and its response are recorded when the tests run the first time, and saved to disk. Subsequent test runs intercept the HTTP requests, match them against the recorded requests and then replay the corresponding recorded response. See for example the \href{https://docs.ropensci.org/vcr/}{vcr} and \href{https://enpiar.com/r/httptest/}{httptest} R packages. The advantages of using your own webfakes server, over mocking: \itemize{ \item Simpler infrastructure. No separate recording and replaying phases, no recorded files. No request matching. \item You can use any web client you want. E.g. curl and base R's HTTP functions do not explicitly support mocking currently. \item No need to worry about sensitive information in recorded requests or responses. \item Often easier to use when testing non-normal conditions, e.g. errors that are hard to trigger, low bandwidth, or rate limits. \item Works if you stream data from a HTTP connection, instead of reading the whole response at once. \item You can reuse the same app for multiple tests, in multiple packages. \item Easier to use for tests that require multiple rounds of requests. \item Comes with a built-in \verb{https://httpbin.org} compatible app, chances are, you don't even need to write your testing app, just start writing tests right away. \item Better test writing experience. This is subjective, and your mileage may vary. } } \subsection{Webfakes vs the real API}{ \itemize{ \item No network needed. No more \code{skip_if_offline()}. \item Much faster. \item No rate limits. But you can simulate one if you want to. \item You can write your custom app. \item Simulate low bandwidth or a broken connection. } } \subsection{Webfakes vs httpbin.org}{ \itemize{ \item No network needed. No more \code{skip_if_offline()}. \item Much faster. \item You can use the built-in \code{webfakes::httpbin_app()} app, so it is easy to switch from httpbin.org. \item You can write your custom app, httpbin.org might not have what you need. } } \subsection{Using \code{webfakes::httpbin_app()} with testthat}{ You can use testthat's setup files. You start the app in a setup file and also register a teardown expression for it. \code{local_app_process()} can do both in one go. Your \code{tests/testthat/setup-http.R} may look like this: \if{html}{\out{
}}\preformatted{http <- webfakes::local_app_process( webfakes::httpbin_app(), .local_envir = testthat::teardown_env() ) }\if{html}{\out{
}} (Before testthat 3.0.0, you had to write the teardown expression in a \code{tests/testthat/teardown-http.R} file. That still works, but a single setup file is considered to be better practice, see \href{https://testthat.r-lib.org/articles/test-fixtures.html}{this testthat vignette}.) In the test cases you can query the \code{http} app process to get the URLs you need to connect to: \if{html}{\out{
}}\preformatted{test_that("fails on 404", \{ url <- http$url("/status/404") response <- httr::GET(url) expect_error( httr::stop_for_status(response), class = "http_404" ) \}) #> Test passed }\if{html}{\out{
}} When writing your tests interactively, you may create a \code{http} app process in the global environment, for convenience. You can \code{source()} your \code{setup-http.R} file for this. Alternatively, you can start the app process in a helper file. See "How do I start the app when writing the tests?" just below. You can also create a web server for a test file, or even for a single test case. See \code{vignette("how-to")} for details how. } \subsection{Writing apps}{ If the builtin \code{httpbin_app()} is not appropriate for your tests, you can write your own app. You can also extend the \code{httpbin_app()} app, if you don't want to start from scratch. You create a new app with \code{new_app()}. This returns an object with methods to add middleware and API endpoints to it. For example, a simple app that returns the current time in JSON would look like this: \if{html}{\out{
}}\preformatted{time <- webfakes::new_app() time$get("/time", function(req, res) \{ res$send_json(list(time = format(Sys.time())), auto_unbox = TRUE) \}) }\if{html}{\out{
}} Now you can start this app on a random port using \code{web$listen()}. Alternatively, you can start it in a subprocess with \code{new_app_process()}. \if{html}{\out{
}}\preformatted{web <- webfakes::new_app_process(time) web$url() #> [1] "http://127.0.0.1:64358/" }\if{html}{\out{
}} Use \code{web$url()} to query the URL of the app. For example: \if{html}{\out{
}}\preformatted{url <- web$url("/time") httr::content(httr::GET(url)) #> $time #> [1] "2025-01-14 10:07:33" }\if{html}{\out{
}} \code{web$stop()} stops the app and the subprocess as well: \if{html}{\out{
}}\preformatted{web$stop() web$get_state() #> [1] "not running" }\if{html}{\out{
}} \code{local_app_process()} is similar to \code{new_app_process()}, but it stops the server process at the end of the calling block. This means that the process is automatically cleaned up at the end of a \code{test_that()} block or at the end of the test file. You can create your app at the beginning of your test file. Or, if you want to use the same app in multiple test files, use a \href{https://testthat.r-lib.org/reference/test_file.html#special-files}{testthat helper file}. Sometimes it useful if your users can create and use your test app, for example to create reproducible examples. You can include a (possibly internal) function in your package, that creates the app. See \code{?new_app()}, \code{?new_app_process()} and \code{?local_app_process} for more details. } } webfakes/man/new_regexp.Rd0000644000176200001440000000140114172041777015254 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/path.R \name{new_regexp} \alias{new_regexp} \alias{webfakes_regexp} \title{Create a new regular expression to use in webfakes routes} \usage{ new_regexp(x) } \arguments{ \item{x}{String scalar containing a regular expression.} } \value{ String with class \code{webfakes_regexp}. } \description{ Note that webfakes uses PERL regular expressions. } \details{ As R does not have data type or class for regular expressions, you can use \code{new_regexp()} to mark a string as a regular expression, when adding routes. } \examples{ new_regexp("^/api/match/(?.*)$") } \seealso{ The 'Path specification' and 'Path parameters' chapters of the manual of \code{\link[=new_app]{new_app()}}. } webfakes/man/webfakes_request.Rd0000644000176200001440000000376614172041777016470 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/request.R \name{webfakes_request} \alias{webfakes_request} \title{A webfakes request object} \description{ webfakes creates a \code{webfakes_request} object for every incoming HTTP request. This object is passed to every matched route and middleware, until the response is sent. It has reference semantics, so handlers can modify it. } \details{ Fields and methods: \itemize{ \item \code{app}: The \code{webfakes_app} object itself. \item \code{headers}: Named list of HTTP request headers. \item \code{hostname}: The Host header, the server hostname and maybe port. \item \code{method}: HTTP method. \item \code{path}: Server path. \item \code{protocol}: \code{"http"} or \code{"https"}. \item \code{query_string}: The raw query string, without the starting \verb{?}. \item \code{query}: Parsed query parameters in a named list. \item \code{remote_addr}: String, the domain name or IP address of the client. webfakes runs on the localhost, so this is \verb{127.0.0.1}. \item \code{url}: The full URL of the request. \item \code{get_header(field)}: Function to query a request header. Returns \code{NULL} if the header is not present. } Body parsing middleware adds additional fields to the request object. See \code{\link[=mw_raw]{mw_raw()}}, \code{\link[=mw_text]{mw_text()}}, \code{\link[=mw_json]{mw_json()}}, \code{\link[=mw_multipart]{mw_multipart()}} and \code{\link[=mw_urlencoded]{mw_urlencoded()}}. } \examples{ # This is how you can see the request and response objects: app <- new_app() app$get("/", function(req, res) { browser() res$send("done") }) app # Now start this app on a port: # app$listen(3000) # and connect to it from a web browser: http://127.0.0.1:3000 # You can also use another R session to connect: # httr::GET("http://127.0.0.1:3000") # or the command line curl tool: # curl -v http://127.0.0.1:3000 # The app will stop while processing the request. } \seealso{ \link{webfakes_response} for the webfakes response object. } webfakes/man/mw_multipart.Rd0000644000176200001440000000161014740243712015631 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-multipart.R \name{mw_multipart} \alias{mw_multipart} \title{Parse a multipart HTTP request body} \usage{ mw_multipart(type = "multipart/form-data") } \arguments{ \item{type}{Content type to match before parsing. If it does not match, then the request object is not modified.} } \value{ Handler function. } \description{ Adds the parsed form fields in the \code{form} element of the request and the parsed files to the \code{files} element. } \examples{ app <- new_app() app$use(mw_multipart()) app } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_cookie_parser}()}, \code{\link{mw_etag}()}, \code{\link{mw_json}()}, \code{\link{mw_log}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_raw}()}, \code{\link{mw_static}()}, \code{\link{mw_text}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/new_app_process.Rd0000644000176200001440000000671714740737024016315 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/app-process.R \name{new_app_process} \alias{new_app_process} \alias{webfakes_app_process} \title{Run a webfakes app in another process} \usage{ new_app_process( app, port = NULL, opts = server_opts(remote = TRUE), start = FALSE, auto_start = TRUE, process_timeout = NULL, callr_opts = NULL ) } \arguments{ \item{app}{\code{webfakes_app} object, the web app to run.} \item{port}{Port(s) to use. By default the OS assigns a port. Add an \code{"s"} suffix to the port to use HTTPS. Use \code{"0s"} to use an OS assigned port with HTTPS. See the \link{how-to} on how to run the web server on multiple ports.} \item{opts}{Server options. See \code{\link[=server_opts]{server_opts()}} for the defaults.} \item{start}{Whether to start the web server immediately. If this is \code{FALSE}, and \code{auto_start} is \code{TRUE}, then it is started as neeed.} \item{auto_start}{Whether to start the web server process automatically. If \code{TRUE} and the process is not running, then \verb{$start()}, \verb{$get_port()}, \verb{$get_ports()} and \verb{$url()} start the process.} \item{process_timeout}{How long to wait for the subprocess to start, in milliseconds.} \item{callr_opts}{Options to pass to \code{\link[callr:r_session_options]{callr::r_session_options()}} when setting up the subprocess.} } \value{ A \code{webfakes_app_process} object. \subsection{Methods}{ The \code{webfakes_app_process} class has the following methods: \if{html}{\out{
}}\preformatted{get_app() get_port() get_ports() stop() get_state() local_env(envvars) url(path = "/", query = NULL) }\if{html}{\out{
}} \itemize{ \item \code{envvars}: Named list of environment variables. The \code{{url}} substring is replaced by the URL of the app. \item \code{path}: Path to return the URL for. \item \code{query}: Additional query parameters, a named list, to add to the URL. } \code{get_app()} returns the app object. \code{get_port()} returns the (first) port the web server is running on. \code{get_ports()} returns all ports the web server is running on, and whether it uses SSL on those ports, in a data frame with columns \code{ipv4}, \code{ipv6}, \code{port} and \code{ssl}. \code{stop()} stops the web server, and also the subprocess. If the error log file is not empty, then it dumps its contents to the screen. \code{get_state()} returns a string, the state of the web server: \itemize{ \item \code{"not running"} the server is not running (because it was stopped already). \item \code{"live"} means that the server is running. \item \code{"dead"} means that the subprocess has quit or crashed. } \code{local_env()} sets the given environment variables for the duration of the app process. It resets them in \verb{$stop()}. Webfakes replaces \code{{url}} in the value of the environment variables with the app URL, so you can set environment variables that point to the app. \code{url()} returns the URL of the web app. You can use the \code{path} parameter to return a specific path. } } \description{ Runs an app in a subprocess, using \link[callr:r_session]{callr::r_session}. } \examples{ app <- new_app() app$get("/foo", function(req, res) { res$send("Hello world!") }) proc <- new_app_process(app) url <- proc$url("/foo") resp <- curl::curl_fetch_memory(url) cat(rawToChar(resp$content)) proc$stop() } \seealso{ \code{\link[=local_app_process]{local_app_process()}} for automatically cleaning up the subprocess. } webfakes/man/mw_cookie_parser.Rd0000644000176200001440000000143214740243712016437 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-cookie-parser.R \name{mw_cookie_parser} \alias{mw_cookie_parser} \title{Middleware to parse Cookies} \usage{ mw_cookie_parser() } \value{ Handler function. } \description{ Adds the cookies as the \code{cookies} element of the request object. } \details{ It ignores cookies in an invalid format. It ignores duplicate cookies: if two cookies have the same name, only the first one is included. } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_etag}()}, \code{\link{mw_json}()}, \code{\link{mw_log}()}, \code{\link{mw_multipart}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_raw}()}, \code{\link{mw_static}()}, \code{\link{mw_text}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/oauth2_third_party_app.Rd0000644000176200001440000000615214172041777017574 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/oauth.R \name{oauth2_third_party_app} \alias{oauth2_third_party_app} \title{App representing the third-party app} \usage{ oauth2_third_party_app(name = "Third-Party app") } \arguments{ \item{name}{Name of the third-party app} } \value{ webfakes app } \description{ The webfakes package comes with two fake apps that allow to imitate the OAuth2.0 flow in your test cases. (See \href{https://aaronparecki.com/oauth-2-simplified/}{Aaron Parecki’s tutorial} for a good introduction to OAuth2.0.) One app (\code{oauth2_resource_app()}) is the API server that serves both as the resource and provides authorization. \code{oauth2_third_party_app()} plays the role of the third-party app. They are useful when testing or demonstrating code handling OAuth2.0 authorization, token caching, etc. in a package. The apps can be used in your tests directly, or you could adapt one or both of them to better mimic a particular OAuth2.0 flow. } \details{ Endpoints: \itemize{ \item \code{POST /login/config} Use this endpoint to configure the client ID and the client secret of the app, received from \code{\link[=oauth2_resource_app]{oauth2_resource_app()}} (or another resource app). You need to send in a JSON or URL encoded body: \itemize{ \item \code{auth_url}, the authorization URL of the resource app. \item \code{token_url}, the token URL of the resource app. \item \code{client_id}, the client ID, received from the resource app. \item \code{client_secret} the client secret, received from the resource app. } \item \code{GET /login} Use this endpoint to start the login process. It will redirect to the resource app for authorization and after the OAuth2.0 dance to \verb{/login/redirect}. \item \code{GET /login/redirect}, \code{POST /login/redirect} This is the redirect URI of the third party app. (Some HTTP clients redirect a \code{POST} to a \code{GET}, others don't, so it has both.) This endpoint is used by the resource app, and it received the \code{code} that can be exchanged to an access token and the \code{state} which was generated in \verb{/login}. It contacts the resource app to get an access token, and then stores the token in its \code{app$locals} local variables. It fails with HTTP code 500 if it cannot obtain an access token. On success it returns a JSON dictionary with \code{access_token}, \code{expiry} and \code{refresh_token} (optionally) by default. This behavior can be changed by redefining the \code{app$redirect_hook()} function. \item \code{GET /locals} returns the tokens that were obtained from the resource app. \item \code{GET /data} is an endpoint that uses the obtained token(s) to connect to the \verb{/data} endpoint of the resource app. The \verb{/data} endpoint of the resource app needs authorization. It responds with the response of the resource app. It tries to refresh the access token of the app if needed. } For more details see \code{vignette("oauth", package = "webfakes")}. } \seealso{ Other OAuth2.0 functions: \code{\link{oauth2_httr_login}()}, \code{\link{oauth2_login}()}, \code{\link{oauth2_resource_app}()} } \concept{OAuth2.0 functions} webfakes/man/mw_cgi.Rd0000644000176200001440000000534314740430520014354 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-cgi.R \name{mw_cgi} \alias{mw_cgi} \title{Middleware that calls a CGI script} \usage{ mw_cgi(command, args = character(), timeout = as.difftime(Inf, units = "secs")) } \arguments{ \item{command}{External command to run.} \item{args}{Arguments to pass to the external command.} \item{timeout}{Timeout for the external command. If the command does not terminate in time, the web server kills it and returns an 500 response.} } \value{ A function with signature \if{html}{\out{
}}\preformatted{function(req, res, env = character()) }\if{html}{\out{
}} See \href{https://datatracker.ietf.org/doc/html/rfc3875}{RFC 3875} for details on the CGI protocol. The request body (if any) is passed to the external command as standard intput. \code{mw_cgi()} sets \code{CONTENT_LENGTH}, \code{CONTENT_TYPE}, \code{GATEWAY_INTERFACE}, \code{PATH_INFO}, \code{QUERY_STRING}, \code{REMOTE_ADDR}, \code{REMOTE_HOST}, \code{REMOTE_USER}, \code{REQUEST_METHOD}, \code{SERVER_NAME}, \code{SERVER_PORT}, \code{SERVER_PROTOCOL}, \code{SERVER_SOFTEWARE}. It does not currently set the \code{AUTH_TYPE}, \code{PATH_TRANSLATED}, \code{REMOTE_IDENT}, \code{SCRIPT_NAME} environment variables. The standard output of the external command is used to set the response status code, the response headers and the response body. Example output from git's CGI: \if{html}{\out{
}}\preformatted{Status: 200 OK Expires: Fri, 01 Jan 1980 00:00:00 GMT Pragma: no-cache Cache-Control: no-cache, max-age=0, must-revalidate Content-Type: application/x-git-upload-pack-advertisement 000eversion 2 0015agent=git/2.42.0 0013ls-refs=unborn 0020fetch=shallow wait-for-done 0012server-option 0017object-format=sha1 0010object-info 0000 }\if{html}{\out{
}} } \description{ You can use it as an unconditional middleware in \code{app$use()}, as a handler on \code{app$get()}, \code{app$post()}, etc., or you can call it from a handler. See examples below. } \examples{ app <- new_app() app$use(mw_cgi("echo", "Status: 200\n\nHello")) app app2 <- new_app() app2$get("/greet", mw_cgi("echo", "Status: 200\n\nHello")) app2 # Using `mw_cgi()` in a handler, you can pass extra environment variables app3 <- new_app() cgi <- mw_cgi("echo", "Status: 200\n\nHello") app2$get("/greet", function(req, res) { cgi(req, res, env = c("EXTRA_VAR" = "EXTRA_VALUE")) }) app3 } \seealso{ Other middleware: \code{\link{mw_cookie_parser}()}, \code{\link{mw_etag}()}, \code{\link{mw_json}()}, \code{\link{mw_log}()}, \code{\link{mw_multipart}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_raw}()}, \code{\link{mw_static}()}, \code{\link{mw_text}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/mw_json.Rd0000644000176200001440000000212314740243712014561 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-json.R \name{mw_json} \alias{mw_json} \title{Middleware to parse a JSON body} \usage{ mw_json(type = "application/json", simplifyVector = FALSE, ...) } \arguments{ \item{type}{Content type to match before parsing. If it does not match, then the request object is not modified.} \item{simplifyVector}{Whether to simplify lists to vectors, passed to \code{\link[jsonlite:fromJSON]{jsonlite::fromJSON()}}.} \item{...}{Arguments to pass to \code{\link[jsonlite:fromJSON]{jsonlite::fromJSON()}}, that performs the JSON parsing.} } \value{ Handler function. } \description{ Adds the parsed object as the \code{json} element of the request object. } \examples{ app <- new_app() app$use(mw_json()) app } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_cookie_parser}()}, \code{\link{mw_etag}()}, \code{\link{mw_log}()}, \code{\link{mw_multipart}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_raw}()}, \code{\link{mw_static}()}, \code{\link{mw_text}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/git_app.Rd0000644000176200001440000000224315026555712014537 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/git-app.R \name{git_app} \alias{git_app} \title{Web app that acts as a git http server} \usage{ git_app( git_root, git_cmd = "git", git_timeout = as.difftime(1, units = "mins"), filter = TRUE, cleanup = TRUE ) } \arguments{ \item{git_root}{Path to the root of the directory tree to be served.} \item{git_cmd}{Command to call, by default it is \code{"git"}. It may also be a full path to git.} \item{git_timeout}{A \code{difftime} object, time limit for the git command.} \item{filter}{Whether to support the \code{filter} capability in the server.} \item{cleanup}{Whether to clean up \code{git_root} when the app is garbage collected.} } \description{ It is useful for tests that need an HTTP git server. } \examples{ \dontshow{if (FALSE) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} dir.create(tmp <- tempfile()) setwd(tmp) system("git clone --bare https://github.com/cran/crayon") system("git clone --bare https://github.com/cran/glue") app <- git_app(tmp) git <- new_app_process(app) system(paste("git ls-remote", git$url("/crayon"))) \dontshow{\}) # examplesIf} } webfakes/man/oauth2_httr_login.Rd0000644000176200001440000000250314172041777016550 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/oauth.R \name{oauth2_httr_login} \alias{oauth2_httr_login} \title{Helper function to use httr's OAuth2.0 functions non-interactively, e.g. in test cases} \usage{ oauth2_httr_login(expr) } \arguments{ \item{expr}{Expression that calls \code{\link[httr:oauth2.0_token]{httr::oauth2.0_token()}}, either directly, or indirectly.} } \value{ The return value of \code{expr}. } \description{ To perform an automatic acknowledgement and log in for a local OAuth2.0 app, run by httr, wrap the expression that obtains the OAuth2.0 token in \code{oauth2_httr_login()}. } \details{ In interactive sessions, \code{oauth2_httr_login()} overrides the \code{browser} option, and when httr opens a browser page, it calls \code{\link[=oauth2_login]{oauth2_login()}} in a subprocess. In non-interactive sessions, httr does not open a browser page, only messages the user to do it manually. \code{oauth2_httr_login()} listens for these messages, and calls \code{\link[=oauth2_login]{oauth2_login()}} in a subprocess. } \seealso{ See \code{?vignette("oauth", package = "webfakes")} for a case study that uses this function. Other OAuth2.0 functions: \code{\link{oauth2_login}()}, \code{\link{oauth2_resource_app}()}, \code{\link{oauth2_third_party_app}()} } \concept{OAuth2.0 functions} webfakes/man/server_opts.Rd0000644000176200001440000000541314740737024015471 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/server.R \name{server_opts} \alias{server_opts} \title{Webfakes web server options} \usage{ server_opts( remote = FALSE, port = NULL, num_threads = 1, interfaces = "127.0.0.1", enable_keep_alive = FALSE, access_log_file = remote, error_log_file = TRUE, tcp_nodelay = FALSE, throttle = Inf, decode_url = TRUE, ssl_certificate = NULL ) } \arguments{ \item{remote}{Meta-option. If set to \code{TRUE}, webfakes uses slightly different defaults, that are more appropriate for a background server process.} \item{port}{Port to start the web server on. Defaults to a randomly chosen port.} \item{num_threads}{Number of request handler threads to use. Typically you don't need more than one thread, unless you run test cases in parallel or you make concurrent HTTP requests.} \item{interfaces}{The network interfaces to listen on. Being a test web server, it defaults to the localhost. Only bind to a public interface if you know what you are doing. webfakes was not designed to serve public web pages.} \item{enable_keep_alive}{Whether the server keeps connections alive.} \item{access_log_file}{\code{TRUE}, \code{FALSE}, or a path. See 'Logging' below.} \item{error_log_file}{\code{TRUE}, \code{FALSE}, or a path. See 'Logging' below.} \item{tcp_nodelay}{if \code{TRUE} then packages will be sent as soon as possible, instead of waiting for a full buffer or timeout to occur.} \item{throttle}{Limit download speed for clients. If not \code{Inf}, then it is the maximum number of bytes per second, that is sent to as connection.} \item{decode_url}{Whether the server should automatically decode URL-encodded URLs. If \code{TRUE} (the default), \verb{/foo\%2fbar} will be converted to \verb{/foo/bar} automatically. If \code{FALSE}, URLs as not URL-decoded.} \item{ssl_certificate}{Path to the SSL certificate of the server, needed if you want to server HTTPS requests.} } \value{ List of options that can be passed to \code{webfakes_app$listen()} (see \code{\link[=new_app]{new_app()}}), and \code{\link[=new_app_process]{new_app_process()}}. } \description{ Webfakes web server options } \section{Logging}{ \itemize{ \item For \code{access_log_file}, \code{TRUE} means \verb{/access.log}. \item For \code{error_log_file}, \code{TRUE} means \verb{/error.log}. } \verb{} is set to the contents of the \code{WEBFAKES_LOG_DIR} environment variable, if it is set. Otherwise it is set to \verb{/webfakes} for local apps and \verb{//webfakes} for remote apps (started with \code{new_app_procss()}). \verb{} is the session temporary directory of the \emph{main process}. \verb{} is the process id of the subprocess. } \examples{ # See the defaults server_opts() } webfakes/man/tmpl_glue.Rd0000644000176200001440000000306114172041777015105 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tmpl-glue.R \name{tmpl_glue} \alias{tmpl_glue} \title{glue based template engine} \usage{ tmpl_glue( sep = "", open = "{", close = "}", na = "NA", transformer = NULL, trim = TRUE ) } \arguments{ \item{sep}{Separator used to separate elements.} \item{open}{The opening delimiter. Doubling the full delimiter escapes it.} \item{close}{The closing delimiter. Doubling the full delimiter escapes it.} \item{na}{Value to replace NA values with. If \code{NULL} missing values are propagated, that is an \code{NA} result will cause \code{NA} output. Otherwise the value is replaced by the value of \code{na}.} \item{transformer}{A function taking three parameters \code{code}, \code{envir} and \code{data} used to transform the output of each block before during or after evaluation.} \item{trim}{Whether to trim the input template with \code{\link[glue:trim]{glue::trim()}} or not.} } \value{ Template function. } \description{ Use this template engine to create pages with glue templates. See \code{\link[glue:glue]{glue::glue()}} for the syntax. } \examples{ # See th 'hello' app at hello_root <- system.file(package = "webfakes", "examples", "hello") hello_root app <- new_app() app$engine("txt", tmpl_glue()) app$use(mw_log()) app$get("/view", function(req, res) { txt <- res$render("test") res$ set_type("text/plain")$ send(txt) }) # Switch to the app's root: setwd(hello_root) # Now start the app with: app$listen(3000L) # Or start it in another process: new_process(app) } webfakes/man/new_app.Rd0000644000176200001440000003366415026556433014561 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/app.R \name{new_app} \alias{new_app} \alias{webfakes_app} \title{Create a new web application} \usage{ new_app() } \value{ A new \code{webfakes_app}. } \description{ Create a new web application } \details{ The typical workflow of creating a web application is: \enumerate{ \item Create a \code{webfakes_app} object with \code{new_app()}. \item Add middleware and/or routes to it. \item Start is with the \code{webfakes_app$listen()} method, or start it in another process with \code{\link[=new_app_process]{new_app_process()}}. \item Make queries to the web app. \item Stop it via \code{CTRL+C} / \code{ESC}, or, if it is running in another process, with the \verb{$stop()} method of \code{\link[=new_app_process]{new_app_process()}}. } A web application can be \itemize{ \item restarted, \item saved to disk, \item copied to another process using the callr package, or a similar way, \item embedded into a package, \item extended by simply adding new routes and/or middleware. } The webfakes API is very much influenced by the \href{https://expressjs.com/}{express.js} project. \subsection{Create web app objects}{ \if{html}{\out{
}}\preformatted{new_app() }\if{html}{\out{
}} \code{new_app()} returns a \code{webfakes_app} object the has the methods listed on this page. An app is an environment with S3 class \code{webfakes_app}. } \subsection{The handler stack}{ An app has a stack of handlers. Each handler can be a route or middleware. The differences between the two are: \itemize{ \item A route is bound to one or more paths on the web server. Middleware is not (currently) bound to paths, but run for all paths. \item A route is usually (but not always) the end of the handler stack for a request. I.e. a route takes care of sending out the response to the request. Middleware typically performs some action on the request or the response, and then the next handler in the stack is invoked. } } \subsection{Routes}{ The following methods define routes. Each method corresponds to the HTTP verb with the same name, except for \code{app$all()}, which creates a route for all HTTP methods. \if{html}{\out{
}}\preformatted{app$all(path, ...) app$delete(path, ...) app$get(path, ...) app$head(path, ...) app$patch(path, ...) app$post(path, ...) app$put(path, ...) ... (see list below) }\if{html}{\out{
}} \itemize{ \item \code{path} is a path specification, see 'Path specification' below. \item \code{...} is one or more handler functions. These will be placed in the handler stack, and called if they match an incoming HTTP request. See 'Handler functions' below. } webfakes also has methods for the less frequently used HTTP verbs: \code{CONNECT}, \code{MKCOL}, \code{OPTIONS}, \code{PROPFIND}, \code{REPORT}. (The method names are always in lowercase.) If a request is not handled by any routes (or handler functions in general), then webfakes will send a simple HTTP 404 response. } \subsection{Middleware}{ \code{app$use()} adds a middleware to the handler stack. A middleware is a handler function, see 'Handler functions' below. webfakes comes with middleware to perform common tasks: \itemize{ \item \code{\link[=mw_cookie_parser]{mw_cookie_parser()}} parses \code{Cookie} headers. \item \code{\link[=mw_etag]{mw_etag()}} adds an \code{ETag} header to the response. \item \code{\link[=mw_json]{mw_json()}} parses JSON request bodies. \item \code{\link[=mw_log]{mw_log()}} logs each requests to standard output, or another connection. \item \code{\link[=mw_multipart]{mw_multipart()}} parses multipart request bodies. \item \code{\link[=mw_range_parser]{mw_range_parser()}} parses \code{Range} headers. \item \code{\link[=mw_raw]{mw_raw()}} parses raw request bodies. \item \code{\link[=mw_static]{mw_static()}} serves static files from a directory. \item \code{\link[=mw_text]{mw_text()}} parses plain text request bodies. \item \code{\link[=mw_urlencoded]{mw_urlencoded()}} parses URL encoded request bodies. } \if{html}{\out{
}}\preformatted{app$use(..., .first = FALSE) }\if{html}{\out{
}} \itemize{ \item \code{...} is a set of (middleware) handler functions. They are added to the handler stack, and called for every HTTP request. (Unless an HTTP response is created before reaching this point in the handler stack.) \item \code{.first} set to \code{TRUE} is you want to add the handler function to the bottom of the stack. } } \subsection{Handler functions}{ A handler function is a route or middleware. A handler function is called by webfakes with the incoming HTTP request and the outgoing HTTP response objects (being built) as arguments. The handler function may query and modify the members of the request and/or the response object. If it returns the string \code{"next"}, then it is \emph{not} a terminal handler, and once it returns, webfakes will move on to call the next handler in the stack. A typical route: \if{html}{\out{
}}\preformatted{app$get("/user/:id", function(req, res) \{ id <- req$params$id ... res$ set_status(200L)$ set_header("X-Custom-Header", "foobar")$ send_json(response, auto_unbox = TRUE) \}) }\if{html}{\out{
}} \itemize{ \item The handler belongs to an API path, which is a wildcard path in this case. It matches \verb{/user/alice}, \verb{/user/bob}, etc. The handler will be only called for GET methods and matching API paths. \item The handler receives the request (\code{req}) and the response (\code{res}). \item It sets the HTTP status, additional headers, and sends the data. (In this case the \code{webfakes_response$send_json()} method automatically converts \code{response} to JSON and sets the \code{Content-Type} and \code{Content-Length} headers. \item This is a terminal handler, because it does \emph{not} return \code{"next"}. Once this handler function returns, webfakes will send out the HTTP response. } A typical middleware: \if{html}{\out{
}}\preformatted{app$use(function(req, res) \{ ... "next" \}) }\if{html}{\out{
}} \itemize{ \item There is no HTTP method and API path here, webfakes will call the handler for each HTTP request. \item This is not a terminal handler, it does return \code{"next"}, so after it returns webfakes will look for the next handler in the stack. } } \subsection{Errors}{ If a handler function throws an error, then the web server will return a HTTP 500 \code{text/plain} response, with the error message as the response body. } \subsection{Request and response objects}{ See \link{webfakes_request} and \link{webfakes_response} for the methods of the request and response objects. } \subsection{Path specification}{ Routes are associated with one or more API paths. A path specification can be \itemize{ \item A "plain" (i.e. without parameters) string. (E.g. \code{"/list"}.) \item A parameterized string. (E.g. \code{"/user/:id"}.) \item A regular expression created via \code{\link[=new_regexp]{new_regexp()}} function. \item A list or character vector of the previous ones. (Regular expressions must be in a list.) } } \subsection{Path parameters}{ Paths that are specified as parameterized strings or regular expressions can have parameters. For parameterized strings the keys may contain letters, numbers and underscores. When webfakes matches an API path to a handler with a parameterized string path, the parameters will be added to the request, as \code{params}. I.e. in the handler function (and subsequent handler functions, if the current one is not terminal), they are available in the \code{req$params} list. For regular expressions, capture groups are also added as parameters. It is best to use named capture groups, so that the parameters are in a named list. If the path of the handler is a list of parameterized strings or regular expressions, the parameters are set according to the first matching one. } \subsection{Templates}{ webfakes supports templates, using any template engine. It comes with a template engine that uses the glue package, see \code{\link[=tmpl_glue]{tmpl_glue()}}. \code{app$engine()} registers a template engine, for a certain file extension. The \verb{$render()} method of \link{webfakes_response} can be called from the handler function to evaluate a template from a file. \if{html}{\out{
}}\preformatted{app$engine(ext, engine) }\if{html}{\out{
}} \itemize{ \item \code{ext}: the file extension for which the template engine is added. It should not contain the dot. E.g. \verb{"html"', }"brew"`. \item \code{engine}: the template engine, a function that takes the file path (\code{path}) of the template, and a list of local variables (\code{locals}) that can be used in the template. It should return the result. } An example template engine that uses glue might look like this: \if{html}{\out{
}}\preformatted{app$engine("txt", function(path, locals) \{ txt <- readChar(path, nchars = file.size(path)) glue::glue_data(locals, txt) \}) }\if{html}{\out{
}} (The built-in \code{\link[=tmpl_glue]{tmpl_glue()}} engine has more features.) This template engine can be used in a handler: \if{html}{\out{
}}\preformatted{app$get("/view", function(req, res) \{ txt <- res$render("test") res$ set_type("text/plain")$ send(txt) \}) }\if{html}{\out{
}} The location of the templates can be set using the \code{views} configuration parameter, see the \verb{$set_config()} method below. In the template, the variables passed in as \code{locals}, and also the response local variables (see \code{locals} in \link{webfakes_response}), are available. } \subsection{Starting and stopping}{ \if{html}{\out{
}}\preformatted{app$listen(port = NULL, opts = server_opts(), cleanup = TRUE) }\if{html}{\out{
}} \itemize{ \item \code{port}: port to listen on. When \code{NULL}, the operating system will automatically select a free port. Add an \code{"s"} suffix to the port to use HTTPS. Use \code{"0s"} to use an OS assigned port with HTTPS. See the \link{how-to} manual page if you want to start the web server on more than one ports. \item \code{opts}: options to the web server. See \code{\link[=server_opts]{server_opts()}} for the list of options and their default values. \item \code{cleanup}: stop the server (with an error) if the standard input of the process is closed. This is handy when the app runs in a \code{callr::r_session} subprocess, because it stops the app (and the subprocess) if the main process has terminated. } This method does not return, and can be interrupted with \code{CTRL+C} / \code{ESC} or a SIGINT signal. See \code{\link[=new_app_process]{new_app_process()}} for interrupting an app that is running in another process. When \code{port} is \code{NULL}, the operating system chooses a port where the app will listen. To be able to get the port number programmatically, before the listen method blocks, it advertises the selected port in a \code{webfakes_port} condition, so one can catch it: webfakes by default binds only to the loopback interface at 127.0.0.1, so the webfakes web app is never reachable from the network. \if{html}{\out{
}}\preformatted{withCallingHandlers( app$listen(), "webfakes_port" = function(msg) print(msg$port) ) }\if{html}{\out{
}} } \subsection{Logging}{ webfakes can write an access log that contains an entry for all incoming requests, and also an error log for the errors that happen while the server is running. This is the default behavior for local app (the ones started by \code{app$listen()} and for remote apps (the ones started via \code{new_app_process()}: \itemize{ \item Local apps do not write an access log by default. \item Remote apps write an access log into the \verb{/webfakes//access.log} file, where \verb{} is the session temporary directory of the \emph{main process}, and \verb{} is the process id of the \emph{subprocess}. \item Local apps write an error log to \verb{/webfakes/error.log}, where \verb{} is the session temporary directory of the current process. \item Remote app write an error log to the \verb{/webfakes//error.log}, where \verb{} is the session temporary directory of the \emph{main process} and \verb{} is the process id of the \emph{subprocess}`. } See \code{\link[=server_opts]{server_opts()}} for changing the default logging behavior. } \subsection{Shared app data}{ \if{html}{\out{
}}\preformatted{app$locals }\if{html}{\out{
}} It is often useful to share data between handlers and requests in an app. \code{app$locals} is an environment that supports this. E.g. a middleware that counts the number of requests can be implemented as: \if{html}{\out{
}}\preformatted{app$use(function(req, res) \{ locals <- req$app$locals if (is.null(locals$num)) locals$num <- 0L locals$num <- locals$num + 1L "next" \}) }\if{html}{\out{
}} \link{webfakes_response} objects also have a \code{locals} environment, that is initially populated as a copy of \code{app$locals}. } \subsection{Configuration}{ \if{html}{\out{
}}\preformatted{app$get_config(key) app$set_config(key, value) }\if{html}{\out{
}} \itemize{ \item \code{key}: configuration key. \item \code{value}: configuration value. } Currently used configuration values: \itemize{ \item \code{views}: path where webfakes searches for templates. } } } \examples{ # see example web apps in the `/examples` directory in system.file(package = "webfakes", "examples") app <- new_app() app$use(mw_log()) app$get("/hello", function(req, res) { res$send("Hello there!") }) app$get(new_regexp("^/hi(/.*)?$"), function(req, res) { res$send("Hi indeed!") }) app$post("/hello", function(req, res) { res$send("Got it, thanks!") }) app # Start the app with: app$listen() # Or start it in another R session: new_app_process(app) } \seealso{ \link{webfakes_request} for request objects, \link{webfakes_response} for response objects. } webfakes/man/oauth2_resource_app.Rd0000644000176200001440000001321514306332713017060 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/oauth.R \name{oauth2_resource_app} \alias{oauth2_resource_app} \title{Fake OAuth 2.0 resource and authorization app} \usage{ oauth2_resource_app( access_duration = 3600L, refresh_duration = 7200L, refresh = TRUE, seed = NULL, authorize_endpoint = "/authorize", token_endpoint = "/token" ) } \arguments{ \item{access_duration}{After how many seconds should access tokens expire.} \item{refresh_duration}{After how many seconds should refresh tokens expire (ignored if \code{refresh} is \code{FALSE}).} \item{refresh}{Should a refresh token be returned (logical).} \item{seed}{Random seed used when creating tokens. If \code{NULL}, we rely on R to provide a seed. The app uses its own RNG stream, so it does not affect reproducibility of the tests.} \item{authorize_endpoint}{The authorization endpoint of the resource server. Change this from the default if the real app that you are faking does not use \verb{/authorize}.} \item{token_endpoint}{The endpoint to request tokens. Change this if the real app that you are faking does not use \verb{/token}.} } \value{ a \code{webfakes} app webfakes app } \description{ The webfakes package comes with two fake apps that allow to imitate the OAuth2.0 flow in your test cases. (See \href{https://aaronparecki.com/oauth-2-simplified/}{Aaron Parecki’s tutorial} for a good introduction to OAuth2.0.) One app (\code{oauth2_resource_app()}) is the API server that serves both as the resource and provides authorization. \code{oauth2_third_party_app()} plays the role of the third-party app. They are useful when testing or demonstrating code handling OAuth2.0 authorization, token caching, etc. in a package. The apps can be used in your tests directly, or you could adapt one or both of them to better mimic a particular OAuth2.0 flow. } \details{ The app has the following endpoints: \itemize{ \item \code{GET /register} is the endpoint that you can use to register your third party app. It needs to receive the \code{name} of the third party app, and its \code{redirect_uri} as query parameters, otherwise returns an HTTP 400 error. On success it returns a JSON dictionary with entries \code{name} (the name of the third party app), \code{client_id}, \code{client_secret} and \code{redirect_uri}. \item \code{GET /authorize} is the endpoint where the user of the third party app is sent. You can change the URL of this endpoint with the \code{authorize_endpoint} argument. It needs to receive the \code{client_id} of the third party app, and its correct \code{redirect_uri} as query parameters. It may receive a \code{state} string as well, which can be used by a client to identify the request. Otherwise it generates a random \code{state} string. On error it fails with a HTTP 400 error. On success it returns a simple HTML login page. \item \code{POST /authorize/decision} is the endpoint where the HTML login page generated at \verb{/authorize} connects back to, either with a positive or negative result. The form on the login page will send the \code{state} string and the user's choice in the \code{action} variable. If the user authorized the third party app, then they are redirected to the \code{redirect_uri} of the app, with a temporary \code{code} and the \code{state} string supplied as query parameters. Otherwise a simple HTML page is returned. \item \code{POST /token} is the endpoint where the third party app requests a temporary access token. It is also uses for refreshing an access token with a refresh token. You can change the URL of this endpoint with the \code{token_endpoint} argument. To request a new token or refresh an existing one, the following data must be included in either a JSON or an URL encoded request body: \itemize{ \item \code{grant_type}, this must be \code{authorization_code} for new tokens, and \code{refresh_token} for refreshing. \item \code{code}, this must be the temporary code obtained from the \verb{/authorize/decision} redirection, for new tokens. It is not needed when refreshing. \item \code{client_id} must be the client id of the third party app. \item \code{client_secret} must be the client secret of the third party app. \item \code{redirect_uri} must be the correct redirection URI of the third party app. It is not needed when refreshing tokens. \item \code{refresh_token} must be the refresh token obtained previously, when refreshing a token. It is not needed for new tokens. On success a JSON dictionary is returned with entries: \code{access_token}, \code{expiry} and \code{refresh_token}. (The latter is omitted if the \code{refresh} argument is \code{FALSE}). } \item \code{GET /locals} returns a list of current apps, access tokens and refresh tokens. \item \code{GET /data} is an endpoint that returns a simple JSON response, and needs authorization. } \subsection{Notes}{ \itemize{ \item Using this app in your tests requires the glue package, so you need to put it in \code{Suggests}. \item You can add custom endpoints to the app, as needed. \item If you need authorization in your custom endpoint, call \code{app$is_authorized()} in your handler: \if{html}{\out{
}}\preformatted{if (!app$is_authorized(req, res)) return() }\if{html}{\out{
}} \code{app$is_authorized()} returns an HTTP 401 response if the client is not authorized, so you can simply return from your handler. } For more details see \code{vignette("oauth", package = "webfakes")}. } } \section{\code{oauth2_resource_app()}}{ App representing the API server (resource/authorization) } \seealso{ Other OAuth2.0 functions: \code{\link{oauth2_httr_login}()}, \code{\link{oauth2_login}()}, \code{\link{oauth2_third_party_app}()} } \concept{OAuth2.0 functions} webfakes/man/httpbin_app.Rd0000644000176200001440000000155214740243712015422 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/httpbin.R \name{httpbin_app} \alias{httpbin_app} \title{Generic web app for testing HTTP clients} \usage{ httpbin_app(log = interactive()) } \arguments{ \item{log}{Whether to log requests to the standard output.} } \value{ A \code{webfakes_app}. } \description{ A web app similar to \verb{https://httpbin.org}. See \href{https://webfakes.r-lib.org/httpbin.html}{its specific docs}. You can also see these docs locally, by starting the app: \if{html}{\out{
}}\preformatted{httpbin <- new_app_process(httpbin_app()) browseURL(httpbin$url()) }\if{html}{\out{
}} } \examples{ app <- httpbin_app() proc <- new_app_process(app) url <- proc$url("/get") resp <- curl::curl_fetch_memory(url) curl::parse_headers_list(resp$headers) cat(rawToChar(resp$content)) proc$stop() } webfakes/man/mw_range_parser.Rd0000644000176200001440000000225014740243712016261 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-range-parser.R \name{mw_range_parser} \alias{mw_range_parser} \title{Middleware to parse a Range header} \usage{ mw_range_parser() } \value{ Handler function. } \description{ Adds the requested ranges to the \code{ranges} element of the request object. \code{request$ranges} is a data frame with two columns, \code{from} and \code{to}. Each row corresponds one requested interval. } \details{ When the last \code{n} bytes of the file are requested, the matrix row is set to \code{c(0, -n)}. When all bytes after a \code{p} position are requested, the matrix row is set to \code{c(p, Inf)}. If the intervals overlap, then \code{ranges} is not set, i.e. the \code{Range} header is ignored. If its syntax is invalid or the unit is not \code{bytes}, then the \code{Range} header is ignored. } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_cookie_parser}()}, \code{\link{mw_etag}()}, \code{\link{mw_json}()}, \code{\link{mw_log}()}, \code{\link{mw_multipart}()}, \code{\link{mw_raw}()}, \code{\link{mw_static}()}, \code{\link{mw_text}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/mw_static.Rd0000644000176200001440000000235714740243712015110 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-static.R \name{mw_static} \alias{mw_static} \title{Middleware function to serve static files} \usage{ mw_static(root, set_headers = NULL) } \arguments{ \item{root}{Root path of the served files. Everything under this directory is served automatically. Directory lists are not currently supports.} \item{set_headers}{Callback function to call before a file is served.} } \value{ Handler function. } \description{ The content type of the response is set automatically from the extension of the file. Note that this is a terminal middleware handler function. If a file is served, then the rest of the handler functions will not be called. If a file was not found, however, the rest of the handlers are still called. } \examples{ root <- system.file(package = "webfakes", "examples", "static", "public") app <- new_app() app$use(mw_static(root = root)) app } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_cookie_parser}()}, \code{\link{mw_etag}()}, \code{\link{mw_json}()}, \code{\link{mw_log}()}, \code{\link{mw_multipart}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_raw}()}, \code{\link{mw_text}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/mw_text.Rd0000644000176200001440000000161714740243712014603 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-text.R \name{mw_text} \alias{mw_text} \title{Middleware to parse a plain text body} \usage{ mw_text(default_charset = "utf-8", type = "text/plain") } \arguments{ \item{default_charset}{Encoding to set on the text.} \item{type}{Content type to match before parsing. If it does not match, then the request object is not modified.} } \value{ Handler function. } \description{ Adds the parsed object as the \code{text} element of the request object. } \examples{ app <- new_app() app$use(mw_text()) app } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_cookie_parser}()}, \code{\link{mw_etag}()}, \code{\link{mw_json}()}, \code{\link{mw_log}()}, \code{\link{mw_multipart}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_raw}()}, \code{\link{mw_static}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/mw_log.Rd0000644000176200001440000000256514740243712014403 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-log.R \name{mw_log} \alias{mw_log} \title{Log requests to the standard output or other connection} \usage{ mw_log(format = "dev", stream = "stdout") } \arguments{ \item{format}{Log format. Not implemented currently.} \item{stream}{R connection to log to. \code{"stdout"} means the standard output, \code{"stderr"} is the standard error. You can also supply a connection object, but then you need to be sure that it will be valid when the app is actually running.} } \value{ Handler function. } \description{ A one line log entry for every request. The output looks like this: \if{html}{\out{
}}\preformatted{GET http://127.0.0.1:3000/image 200 3 ms - 4742 }\if{html}{\out{
}} and contains \itemize{ \item the HTTP method, \item the full request URL, \item the HTTP status code of the response, \item how long it took to process the response, in ms, \item and the size of the response body, in bytes. } } \examples{ app <- new_app() app$use(mw_log()) app } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_cookie_parser}()}, \code{\link{mw_etag}()}, \code{\link{mw_json}()}, \code{\link{mw_multipart}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_raw}()}, \code{\link{mw_static}()}, \code{\link{mw_text}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/webfakes_response.Rd0000644000176200001440000001251014740243712016613 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/response.R \name{webfakes_response} \alias{webfakes_response} \title{A webfakes response object} \description{ webfakes creates a \code{webfakes_response} object for every incoming HTTP request. This object is passed to every matched route and middleware, until the HTTP response is sent. It has reference semantics, so handlers can modify it. } \details{ Fields and methods: \itemize{ \item \code{app}: The \code{webfakes_app} object itself. \item \code{req}: The request object. \item \code{headers_sent}: Whether the response headers were already sent out. \item \code{locals}: Local variables, the are shared between the handler functions. This is for the end user, and not for the middlewares. \item \code{delay(secs)}: delay the response for a number of seconds. If a handler calls \code{delay()}, the same handler will be called again, after the specified number of seconds have passed. Use the \code{locals} environment to distinguish between the calls. If you are using \code{delay()}, and want to serve requests in parallel, then you probably need a multi-threaded server, see \code{\link[=server_opts]{server_opts()}}. \item \code{add_header(field, value)}: Add a response header. Note that \code{add_header()} may create duplicate headers. You usually want \code{set_header()}. \item \code{get_header(field)}: Query the currently set response headers. If \code{field} is not present it return \code{NULL}. \item \code{on_response(fun)}: Run the \code{fun} handler function just before the response is sent out. At this point the headers and the body are already properly set. \item \code{redirect(path, status = 302)}: Send a redirect response. It sets the \code{Location} header, and also sends a \code{text/plain} body. \item \code{render(view, locals = list())}: Render a template page. Searches for the \code{view} template page, using all registered engine extensions, and calls the first matching template engine. Returns the filled template. \item \code{send(body)}. Send the specified body. \code{body} can be a raw vector, or HTML or other text. For raw vectors it sets the content type to \code{application/octet-stream}. \item \code{send_json(object = NULL, text = NULL, ...)}: Send a JSON response. Either \code{object} or \code{text} must be given. \code{object} will be converted to JSON using \code{\link[jsonlite:fromJSON]{jsonlite::toJSON()}}. \code{...} are passed to \code{\link[jsonlite:fromJSON]{jsonlite::toJSON()}}. It sets the content type appropriately. \item \code{send_file(path, root = ".")}: Send a file. Set \code{root = "/"} for absolute file names. It sets the content type automatically, based on the extension of the file, if it is not set already. \item \code{send_status(status)}: Send the specified HTTP status code, without a response body. \item \code{send_chunk(data)}: Send a chunk of a response in chunked encoding. The first chunk will automatically send the HTTP response headers. Webfakes will automatically send a final zero-lengh chunk, unless \verb{$delay()} is called. \item \code{set_header(field, value)}: Set a response header. If the headers have been sent out already, then it throws a warning, and does nothing. \item \code{set_status(status)}: Set the response status code. If the headers have been sent out already, then it throws a warning, and does nothing. \item \code{set_type(type)}: Set the response content type. If it contains a \code{/} character then it is set as is, otherwise it is assumed to be a file extension, and the corresponding MIME type is set. If the headers have been sent out already, then it throws a warning, and does nothing. \item \code{add_cookie(name, value, options)}: Adds a cookie to the response. \code{options} is a named list, and may contain: \itemize{ \item \code{domain}: Domain name for the cookie, not set by default. \item \code{expires}: Expiry date in GMT. It must be a POSIXct object, and will be formatted correctly. \item 'http_only': if TRUE, then it sets the 'HttpOnly' attribute, so Javasctipt cannot access the cookie. \item \code{max_age}: Maximum age, in number of seconds. \item \code{path}: Path for the cookie, defaults to "/". \item \code{same_site}: The 'SameSite' cookie attribute. Possible values are "strict", "lax" and "none". \item \code{secure}: if TRUE, then it sets the 'Secure' attribute. } \item \code{clear_cookie(name, options = list())}: clears a cookie. Typically, web browsers will only clear a cookie if the options also match. \item \code{write(data)}: writes (part of) the body of the response. It also sends out the response headers, if they haven't been sent out before. } Usually you need one of the \code{send()} methods, to send out the HTTP response in one go, first the headers, then the body. Alternatively, you can use \verb{$write()} to send the response in parts. } \examples{ # This is how you can see the request and response objects: app <- new_app() app$get("/", function(req, res) { browser() res$send("done") }) app # Now start this app on a port: # app$listen(3000) # and connect to it from a web browser: http://127.0.0.1:3000 # You can also use another R session to connect: # httr::GET("http://127.0.0.1:3000") # or the command line curl tool: # curl -v http://127.0.0.1:3000 # The app will stop while processing the request. } \seealso{ \link{webfakes_request} for the webfakes request object. } webfakes/man/mw_etag.Rd0000644000176200001440000000202014740243712014524 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-etag.R \name{mw_etag} \alias{mw_etag} \title{Middleware that add an \code{ETag} header to the response} \usage{ mw_etag(algorithm = "crc32") } \arguments{ \item{algorithm}{Checksum algorithm to use. Only \code{"crc32"} is implemented currently.} } \value{ Handler function. } \description{ If the response already has an \code{ETag} header, then it is kept. } \details{ This middleware handles the \code{If-None-Match} headers, and it sets the status code of the response to 304 if \code{If-None-Match} matches the \code{ETag}. It also removes the response body in this case. } \examples{ app <- new_app() app$use(mw_etag()) app } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_cookie_parser}()}, \code{\link{mw_json}()}, \code{\link{mw_log}()}, \code{\link{mw_multipart}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_raw}()}, \code{\link{mw_static}()}, \code{\link{mw_text}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/oauth2_login.Rd0000644000176200001440000000170114172041777015506 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/oauth.R \name{oauth2_login} \alias{oauth2_login} \title{Helper function to log in to a third party OAuth2.0 app without a browser} \usage{ oauth2_login(login_url) } \arguments{ \item{login_url}{The login URL of the third party app.} } \value{ A named list with \itemize{ \item \code{login_response} The curl HTTP response object for the login page. \item \code{token_response} The curl HTTP response object for submitting the login page. } } \description{ It works with \code{\link[=oauth2_resource_app]{oauth2_resource_app()}}, and any third party app, including the fake \code{\link[=oauth2_third_party_app]{oauth2_third_party_app()}}. } \details{ See \code{test-oauth.R} in webfakes for an example. } \seealso{ Other OAuth2.0 functions: \code{\link{oauth2_httr_login}()}, \code{\link{oauth2_resource_app}()}, \code{\link{oauth2_third_party_app}()} } \concept{OAuth2.0 functions} webfakes/man/mw_raw.Rd0000644000176200001440000000150214740243712014401 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-raw.R \name{mw_raw} \alias{mw_raw} \title{Middleware to read the raw body of a request} \usage{ mw_raw(type = "application/octet-stream") } \arguments{ \item{type}{Content type to match. If it does not match, then the request object is not modified.} } \value{ Handler function. } \description{ Adds the raw body, as a raw object to the \code{raw} field of the request. } \examples{ app <- new_app() app$use(mw_raw()) app } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_cookie_parser}()}, \code{\link{mw_etag}()}, \code{\link{mw_json}()}, \code{\link{mw_log}()}, \code{\link{mw_multipart}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_static}()}, \code{\link{mw_text}()}, \code{\link{mw_urlencoded}()} } \concept{middleware} webfakes/man/http_time_stamp.Rd0000644000176200001440000000065114740243712016312 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils.R \name{http_time_stamp} \alias{http_time_stamp} \title{Format a time stamp for HTTP} \usage{ http_time_stamp(t = Sys.time()) } \arguments{ \item{t}{Date-time value to format, defaults to the current date and time. It must be a POSIXct object.} } \value{ Character vector, formatted date-time. } \description{ Format a time stamp for HTTP } webfakes/man/mw_urlencoded.Rd0000644000176200001440000000163514740243712015743 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/mw-urlencoded.R \name{mw_urlencoded} \alias{mw_urlencoded} \title{Middleware to parse an url-encoded request body} \usage{ mw_urlencoded(type = "application/x-www-form-urlencoded") } \arguments{ \item{type}{Content type to match before parsing. If it does not match, then the request object is not modified.} } \value{ Handler function. } \description{ This is typically data from a form. The parsed data is added as the \code{form} element of the request object. } \examples{ app <- new_app() app$use(mw_urlencoded()) app } \seealso{ Other middleware: \code{\link{mw_cgi}()}, \code{\link{mw_cookie_parser}()}, \code{\link{mw_etag}()}, \code{\link{mw_json}()}, \code{\link{mw_log}()}, \code{\link{mw_multipart}()}, \code{\link{mw_range_parser}()}, \code{\link{mw_raw}()}, \code{\link{mw_static}()}, \code{\link{mw_text}()} } \concept{middleware} webfakes/man/how-to.Rd0000644000176200001440000006545615026555712014350 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/docs.R \name{how-to} \alias{how-to} \title{How to use webfakes in your tests} \description{ How to use webfakes in your tests } \section{How to use webfakes in your tests}{ \subsection{How do I use webfakes in my package?}{ First, you need to add webfakes to the \code{DESCRIPTION} file of your package. Use the \code{Suggests} field, as webfakes is only needed for testing: \if{html}{\out{
}}\preformatted{... Suggests: webfakes, testthat ... }\if{html}{\out{
}} Then, unless the URL to the web service is an argument of your package functions, you might need to tweak your package code slightly to make sure every call to a real web service can be targeted at another URL instead (of a fake app). See next subsection. Last but not least, you need to decide if you want a single web app for all your test cases. The alternative is to use different apps for some or all test files. Occasionally you may want to use a special app for a single test case. Each app runs in a new subprocess, and it takes typically about 100-400ms to start. See the sections later on on writing tests with a single app or multiple apps. } \subsection{How do I make my app connect to webfakes when the tests are running?}{ In the typical scenario, you want your package to connect to the test app only when running the tests. If the URL to the web service is not an argument of the functions, one way to achieve this is to allow specifying the web server URL(s) via environment variables. E.g. when writing a GitHub API client, your package can check use \code{GITHUB_URL} environment variable. E.g. \if{html}{\out{
}}\preformatted{service_url <- function() \{ Sys.getenv("GITHUB_URL", "https://api.github.com") \} # rest of the package code foobar <- function() \{ httr::GET(service_url()) \} }\if{html}{\out{
}} When this is not set, the package connects to the proper GitHub API. When testing, you can point it to your test app. \code{new_app_process()} helps you setting up temporary environment variables. These are active while the process is running, and they are removed or reset in \verb{$stop()}. For example: In \verb{$local_env()} environment variables, webfakes replaces \code{{url}} with the actual app URL. This is needed by default, because the web server process starts up only later, so the URL is not known yet. \if{html}{\out{
}}\preformatted{http <- webfakes::local_app_process(webfakes::httpbin_app(), start = TRUE) http$local_env(list(GITHUB_API = "\{url\}")) Sys.getenv("GITHUB_API") #> [1] "http://127.0.0.1:64362/" http$stop() Sys.getenv("GITHUB_API") #> [1] "" }\if{html}{\out{
}} } \subsection{How can I write my own app?}{ You create a new app with \code{new_app()}. This returns an object with methods to add middleware and API endpoints to it. For example, a simple app that returns the current time in JSON would look like this: \if{html}{\out{
}}\preformatted{time <- webfakes::new_app() time$get("/time", function(req, res) \{ res$send_json(list(time = format(Sys.time())), auto_unbox = TRUE) \}) }\if{html}{\out{
}} Now you can start this app on a random port using \code{web$listen()}. Alternatively, you can start it in a subprocess with \code{new_app_process()}. \if{html}{\out{
}}\preformatted{web <- webfakes::new_app_process(time) web$url() #> [1] "http://127.0.0.1:64364/" }\if{html}{\out{
}} Use \code{web$url()} to query the URL of the app. For example: \if{html}{\out{
}}\preformatted{url <- web$url("/time") httr::content(httr::GET(url)) #> $time #> [1] "2025-01-14 10:07:38" }\if{html}{\out{
}} \code{web$stop()} stops the app and the subprocess as well: \if{html}{\out{
}}\preformatted{web$stop() web$get_state() #> [1] "not running" }\if{html}{\out{
}} \code{local_app_process()} is similar to \code{new_app_process()}, but it stops the server process at the end of the calling block. This means that the process is automatically cleaned up at the end of a \code{test_that()} block or at the end of the test file. You can create your app at the beginning of your test file. Or, if you want to use the same app in multiple test files, use a \href{https://testthat.r-lib.org/reference/test_file.html#special-files}{testthat helper file}. Sometimes it useful if your users can create and use your test app, for example to create reproducible examples. You can include a (possibly internal) function in your package, that creates the app. See \code{?new_app()}, \code{?new_app_process()} and \code{?local_app_process} for more details. } \subsection{How do I use \code{httpbin_app()} (or another app) with testthat?}{ You can use testthat's setup files. You start the app in a setup file and also register a teardown expression for it. \code{local_app_process()} can do both in one go. Your \code{tests/testthat/setup-http.R} may look like this: \if{html}{\out{
}}\preformatted{http <- webfakes::local_app_process( webfakes::httpbin_app(), .local_envir = testthat::teardown_env() ) }\if{html}{\out{
}} (Before testthat 3.0.0, you had to write the teardown expression in a \code{tests/testthat/teardown-http.R} file. That still works, but a single setup file is considered to be better practice, see \href{https://testthat.r-lib.org/articles/test-fixtures.html}{this testthat vignette}.) In the test cases you can query the \code{http} app process to get the URLs you need to connect to: \if{html}{\out{
}}\preformatted{test_that("fails on 404", \{ url <- http$url("/status/404") response <- httr::GET(url) expect_error( httr::stop_for_status(response), class = "http_404" ) \}) #> Test passed }\if{html}{\out{
}} When writing your tests interactively, you may create a \code{http} app process in the global environment, for convenience. You can \code{source()} your \code{setup-http.R} file for this. Alternatively, you can start the app process in a helper file. See "How do I start the app when writing the tests?" just below. } \subsection{How do I start the app when writing the tests?}{ It is convenient to start the webfakes server process(es) when working on the tests interactively, e.g. when using \code{devtools::load_all()}. With \code{local_app_process()} in the testthat \code{setup*.R} file this is not automatic, because \code{devtools::load_all()} does not run these files. So you would need to source the \code{setup*.R} files manually, which is error prone. One solution is to create server processes in the testthat \code{helper*.R} files. \code{load_all()} executes the helper files by default. So instead of using a setup file, you can simply do this in the \code{helper-http.R} file: \if{html}{\out{
}}\preformatted{httpbin <- local_app_process(httpbin_app()) }\if{html}{\out{
}} If the app process is created in the helper file, then it is ready use after \code{load_all()}, and (by default) the actual process will be started at the first \verb{$url()} or \verb{$get_port()} call. You can also start it manually with \verb{$start()}. Processes created in helper files are not cleaned up automatically at the end of the test suite, unless you clean them up by registering a \verb{$stop()} call in a setup file, like this: \if{html}{\out{
}}\preformatted{withr::defer(httpbin$stop(), testthat::teardown_env()) }\if{html}{\out{
}} In practice this is not necessary, because \verb{R CMD check} runs the tests in a separate process, and when that finishes, the webfakes processes are cleaned up as well. When running \code{devtools::test()}, \code{testthat::test_local()} or another testthat function to run (part of) the test suite in the current session, the \code{helper*.R} files are (re)loaded first. This will terminate the currently running app processes, if any, and create new app process objects. Should the test suite auto-start some of the test processes from \code{helper*.R}, these will not be cleaned up at the end of the test suite, but only at the next \code{load_all()} or \code{test()} call, or at the end of the R session. This lets you run your test code interactively, either via \code{test()} or manually, without thinking too much about the webfakes processes. } \subsection{Can I have an app for a single testthat test file?}{ To run a web app for a single test file, start it with \code{new_app_process()} at the beginning of the file, and register its cleanup using \code{withr::defer()}. Even simpler, use \code{local_app_process()} which is the same as \code{new_app_process()} but it automatically stops the web server process, at the end of the test file: \if{html}{\out{
}}\preformatted{app <- webfakes::new_app() app$get("/hello/:user", function(req, res) \{ res$send(paste0("Hello ", req$params$user, "!")) \}) }\if{html}{\out{
}} \if{html}{\out{
}}\preformatted{web <- webfakes::local_app_process(app) }\if{html}{\out{
}} Then in the test cases, use \code{web$url()} to get the URL to connect to. \if{html}{\out{
}}\preformatted{test_that("can use hello API", \{ url <- web$url("/hello/Gabor") expect_equal(httr::content(httr::GET(url)), "Hello Gabor!") \}) #> No encoding supplied: defaulting to UTF-8. #> Test passed }\if{html}{\out{
}} } \subsection{Can I use an app for a single testthat test?}{ Sure. For this you need to create the app process within the \code{testthat::test_that()} test case. \code{local_app_process()} automatically cleans it up at the end of the block. It goes like this: \if{html}{\out{
}}\preformatted{test_that("query works", \{ app <- webfakes::new_app() app$get("/hello", function(req, res) res$send("hello there")) web <- webfakes::local_app_process(app) echo <- httr::content(httr::GET(web$url("/hello"))) expect_equal(echo, "hello there") \}) #> No encoding supplied: defaulting to UTF-8. #> Test passed }\if{html}{\out{
}} } \subsection{How do I test a sequence of requests?}{ To test a sequence of requests, the app needs state information that is kept between requests. \code{app$locals} is an environment that belongs to the app, and it can be used to record information and then retrieve it in future requests. You could store anything in \code{app$locals}, something simple like a counter variable, something fancier like a sqlite database. You can add something to \code{app$locals} via methods or directly after creating the app. \if{html}{\out{
}}\preformatted{store <- webfakes::new_app() store$locals$packages <- list("webfakes") ls(store$locals) #> [1] "packages" store$locals$packages #> [[1]] #> [1] "webfakes" }\if{html}{\out{
}} E.g. here is an end point that fails three times, then succeeds once, fails again three times, etc. Note that the \code{counter} created by the code below starts at 0, not 1. \if{html}{\out{
}}\preformatted{flaky <- webfakes::new_app() flaky$get("/unstable", function(req, res) \{ if (identical(res$app$locals$counter, 3L)) \{ res$app$locals$counter <- NULL res$send_json(object = list(result = "ok")) \} else \{ res$app$locals$counter <- c(res$app$locals$counter, 0L)[[1]] + 1L res$send_status(401) \} \}) }\if{html}{\out{
}} Let's run this app in another process and connect to it: \if{html}{\out{
}}\preformatted{pr <- webfakes::new_app_process(flaky) url <- pr$url("/unstable") httr::RETRY("GET", url, times = 4) #> Request failed [401]. Retrying in 1 seconds... #> Request failed [401]. Retrying in 1 seconds... #> Request failed [401]. Retrying in 2.1 seconds... #> Response [http://127.0.0.1:64374/unstable] #> Date: 2025-01-14 10:07 #> Status: 200 #> Content-Type: application/json #> Size: 17 B }\if{html}{\out{
}} Another example where we send information to an app and then retrieve it. On a POST request we store the \code{name} query parameter in \code{app$locals$packages}, which can be queried with a GET request. \if{html}{\out{
}}\preformatted{store <- webfakes::new_app() # Initial "data" for the app store$locals$packages <- list("webfakes") # Get method store$get("/packages", function(req, res) \{ res$send_json(res$app$locals$packages, auto_unbox = TRUE) \}) # Post method, store information from the query store$post("/packages", function(req, res) \{ res$app$locals$packages <- c(res$app$locals$packages, req$query$name) res$send_json(res$app$locals$packages, auto_unbox = TRUE) \}) }\if{html}{\out{
}} Now we start the app in a subprocess, and run a GET query against it. \if{html}{\out{
}}\preformatted{web <- webfakes::local_app_process(store, start = TRUE) # Get current information get_packages <- function() \{ httr::content( httr::GET( httr::modify_url( web$url(), path = "packages" ) ) ) \} get_packages() #> [[1]] #> [1] "webfakes" }\if{html}{\out{
}} Let's POST some new information. \if{html}{\out{
}}\preformatted{post_package <- function(name) \{ httr::POST( httr::modify_url( web$url(), path = "packages", query = list(name = name) ) ) \} post_package("vcr") #> Response [http://127.0.0.1:64380/packages?name=vcr] #> Date: 2025-01-14 10:07 #> Status: 200 #> Content-Type: application/json #> Size: 18 B # Get current information get_packages() #> [[1]] #> [1] "webfakes" #> #> [[2]] #> [1] "vcr" post_package("httptest") #> Response [http://127.0.0.1:64380/packages?name=httptest] #> Date: 2025-01-14 10:07 #> Status: 200 #> Content-Type: application/json #> Size: 29 B # Get current information get_packages() #> [[1]] #> [1] "webfakes" #> #> [[2]] #> [1] "vcr" #> #> [[3]] #> [1] "httptest" }\if{html}{\out{
}} Stop the app process: \if{html}{\out{
}}\preformatted{web$stop() }\if{html}{\out{
}} } \subsection{How can I debug an app?}{ To debug an app, it is best to run it in the main R process, i.e. \emph{not} via \code{new_app_process()}. You can add breakpoints, or \code{browser()} calls to your handler functions, and then invoke your app from another process. You might find the \code{curl} command line tool to send HTTP requests to the app, or you can just use another R process. Here is an example. We will simply print the incoming request object to the screen now. For a real debugging session you probably want to place a \code{browser()} command there. \if{html}{\out{
}}\preformatted{app <- webfakes::new_app() app$get("/debug", function(req, res) \{ print(req) res$send("Got your back") \}) }\if{html}{\out{
}} Now start the app on port 3000: \if{html}{\out{
}}\preformatted{app$listen(port = 3000) }\if{html}{\out{
}} \if{html}{\out{
}}\preformatted{#> Running webfakes web app on port 3000 }\if{html}{\out{
}} Connect to the app from another R or \code{curl} process: \if{html}{\out{
}}\preformatted{curl -v http://127.0.0.1:3000/debug }\if{html}{\out{
}} \if{html}{\out{
}}\preformatted{#> * Trying 127.0.0.1... #> * TCP_NODELAY set #> * Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0) #> > GET /debug HTTP/1.1 #> > Host: 127.0.0.1:3000 #> > User-Agent: curl/7.54.0 #> > Accept: */* #> > #> < HTTP/1.1 200 OK #> < Content-Type: text/plain #> < Content-Length: 13 #> < #> * Connection #0 to host 127.0.0.1 left intact #> Got your back }\if{html}{\out{
}} Your main R session will print the incoming request: \if{html}{\out{
}}\preformatted{#> #> method: #> get #> url: #> http://127.0.0.1:3000/debug #> client: #> 127.0.0.1 #> query: #> headers: #> Host: 127.0.0.1:3000 #> User-Agent: curl/7.54.0 #> Accept: */* #> fields and methods: #> app # the webfakes_app the request belongs to #> headers # HTTP request headers #> hostname # server hostname, the Host header #> method # HTTP method of request (lowercase) #> path # server path #> protocol # http or https #> query_string # raw query string without '?' #> query # named list of query parameters #> remote_addr # IP address of the client #> url # full URL of the request #> get_header(field) # get a request header #> # see ?webfakes_request for details }\if{html}{\out{
}} Press \code{CTRL+C} or \code{ESC} to interrupt the app in the main session. } \subsection{How can I test HTTPS requests?}{ Serving HTTPS from \code{localhost} or \verb{127.0.0.1} instead of HTTP is easy, all you need to do is \enumerate{ \item Set the port to an HTTPS port by adding an \code{"s"} suffix to the port number. Use \code{"0s"} for an OS assigned free port: \if{html}{\out{
}}\preformatted{new_app_process(app, port = "0s") }\if{html}{\out{
}} By default webfakes uses the server key + certificate in the file at \if{html}{\out{
}}\preformatted{system.file("cert/localhost/server.pem", package = "webfakes") }\if{html}{\out{
}} This certificate includes \code{localhost}, \verb{127.0.0.1} and \code{localhost.localdomain}. If you need another domain or IP address, you'll need to create your own certificate. The \code{generate.sh} file in the same directory helps with that. \item Specify the certificate bundle to the HTTP client you are using. For the default server key use the \code{ca.crt} file from the webfakes package: \if{html}{\out{
}}\preformatted{system.file("cert/localhost/ca.crt", package = "webfakes") }\if{html}{\out{
}} See examples for HTTP clients below. } If you are using the curl package, use the \code{ca_info} option in \code{curl::new_handle()} or \code{curl::handle_setopt()}: \if{html}{\out{
}}\preformatted{cainfo <- system.file("cert/localhost/ca.crt", package = "webfakes") curl::curl_fetch_memory( http$url("/path/to/endpoint"), handle = curl::new_handle(cainfo = cainfo) ) }\if{html}{\out{
}} For the httr package, use \code{httr::config(cainfo = ...)}: \if{html}{\out{
}}\preformatted{httr::GET( http$url("/headers", https = TRUE), httr::config(cainfo = cainfo) ) }\if{html}{\out{
}} For the httr2 package: \if{html}{\out{
}}\preformatted{httr2::request("https://example.com") |> httr2::req_options(cainfo = cainfo) |> httr2::req_perform() }\if{html}{\out{
}} For \code{utils::download.file} point the \code{CURL_CA_BUNDLE} environment variable to the \code{ca.crt} file. Don't forget to undo this, once the HTTP request is done. \if{html}{\out{
}}\preformatted{Sys.setenv( CURL_CA_BUNDLE = system.file("cert/localhost/ca.crt", package = "webfakes") ) download.file(http$url("/path/to/endpoint"), res <- tempfile()) }\if{html}{\out{
}} \subsection{Special considerations for tests on Windows}{ Unfortunately things are not that simple on Windows, for the HTTP clients. As far as I can tell, it is not easily possible to make the HTTP clients accept a new self-signed certificate. It is possible with libcurl, though, but you need to set the \code{CURL_SSL_BACKEND=openssl} environment variable. (And libcurl must be built with openssl support of course.) You need to set this env var \emph{before} loading libcurl, so it is best to set it before starting R. One way to do this in the tests is to run the tests in a subprocess, with the callr package. Look at the \code{test-https.R} file in webfakes for a complete, current example. The tests use this helper function, defined in \code{helper.R}: \if{html}{\out{
}}\preformatted{callr_curl <- function(url, options = list()) \{ callr::r( function(url, options) \{ h <- curl::new_handle() curl::handle_setopt(h, .list = options) curl::curl_fetch_memory(url, handle = h) \}, list(url = url, options = options), env = c( callr::rcmd_safe_env(), CURL_SSL_BACKEND = "openssl", CURL_CA_BUNDLE = if ("cainfo" \%in\% names(options)) options$cainfo ) ) \} }\if{html}{\out{
}} Example test case: \if{html}{\out{
}}\preformatted{# ... cainfo <- system.file("cert/localhost/ca.crt", package = "webfakes") resp <- if (.Platform$OS.type == "windows") \{ callr_curl(http$url("/hello"), list(cainfo = cainfo)) \} else \{ curl::curl_fetch_memory( http$url("/hello"), handle = curl::new_handle(cainfo = cainfo) ) \} # ... }\if{html}{\out{
}} It seems like a good idea to \code{skip_on_cran()} HTTPS tests, at least on Windows, because this setup is not yet tested enough to consider it robust. webfakes uses \href{https://www.trustedfirmware.org/projects/mbed-tls/}{Mbed TLS} for serving HTTPS. } } \subsection{How can I run a server on multiple ports?}{ You can specify multiple port numbers, in a vector. webfakes will then listen on all those ports. You can also mix HTTP and HTTP ports. To redirect from an HTTP port to an HTTPS port, append an \code{"r"} suffix to the HTTP port number. THis port will be redirected to the next HTTPS port. E.g. \if{html}{\out{
}}\preformatted{new_app_process(app, port = c("3000r", "3001s")) }\if{html}{\out{
}} will redirect HTTP from port 3000 to HTTPS on port 3001. To redirect from an OS assigned HTTP port to an OS assigned HTTPS port, use zeros for the port numbers: \if{html}{\out{
}}\preformatted{http <- new_app_process(app, port = c("0r", "0s")) }\if{html}{\out{
}} Then you can use \code{http$get_ports()} to query all port numbers. You can also use \if{html}{\out{
}}\preformatted{http$url(..., https = TRUE) }\if{html}{\out{
}} to get an HTTPS URL instead of the default one (the one with the first port). } \subsection{Can I test asynchronous or parallel HTTP requests?}{ R is single threaded and a webfakes app runs an R interpreter, so it cannot process multiple requests at the same time. The web server itself runs in a separate thread, and it can also process each request in a separate thread, but at any time only one request can use the R interpreter. This is important, because sometimes test requests may take longer to process. For example the \verb{/delay/:secs} end point of \code{httpbin_app()} wait for the specified number of seconds before responding, to simulate a slow web server. If this wait is implemented via the standard \code{Sys.sleep()} R function, then no other requests can be processed until the sleep is over. To avoid this, webfakes can put the waiting request on hold, return from the R interpreter, and respond to other incoming requests. Indeed, the \verb{/delay/} end point is implemented using this feature. However, the request thread of the web server is still busy while on hold, so to take advantage of this, you need to allow multiple threads. The \code{num_threads} argument of the \verb{$listen()} method of \code{webfakes_app} lets you specify the number of request threads the web server will use. Similarly, the \code{num_threads} argument of \code{local_app_process()} lets you modify the number of threads. When testing asynchronous or parallel code, that might invoke multiple, possibly delayed requests, it is best to increase the number of threads. The code below calls the same API request concurrently, three times. Each request takes 1 second to answer, but if the web server has more than three threads, together they'll still take about 1 second. \if{html}{\out{
}}\preformatted{web <- webfakes::local_app_process( webfakes::httpbin_app(), opts = webfakes::server_opts(num_threads = 6, enable_keep_alive = TRUE) ) }\if{html}{\out{
}} \if{html}{\out{
}}\preformatted{testthat::test_that("parallel requests", \{ url <- web$url("/delay/0.5") p <- curl::new_pool() handles <- replicate(3, curl::new_handle(url = url)) resps <- list() for (handle in handles) \{ curl::multi_add( handle, done = function(x) resps <<- c(resps, list(x)), fail = stop, pool = p ) \} st <- system.time(curl::multi_run(timeout = 3, pool = p)) testthat::expect_true(st[["elapsed"]] < 1.5) \}) #> Test passed }\if{html}{\out{
}} (If this should fail for you and webfakes appears to process the requests sequentially, see \href{https://github.com/r-lib/webfakes/issues/108}{issue #108} for possible workarounds.) } \subsection{How to make sure that my code works with the \emph{real} API?}{ Indeed, if you use webfakes for your test cases, then they never touch the real web server. As you might suspect, this is not ideal, especially when you do not control the server. The web service might change their API, and your test cases will fail to warn you. One practical solution is to write (at least some) flexible tests, that can run against a local fake webserver, or a real one, and you have a quick switch to change their behavior. I have found that environment variables work great for this. E.g. if the \code{FAKE_HTTP_TESTS} environment variable is not set, the tests run with the real web server, otherwise they use a fake one. Another solution, that works best is the HTTP requests are in the downstream package code, is to introduce one environment variable for each API you need to connect to. These might be set to the real API servers, or to the fake ones. Once you have some tests that can use both kinds or servers, you can set up your continuous integration (CI) framework, to run the tests agains the real server (say) once a day. This special CI run makes sure that your code works well with the real API. You can run all the other tests, locally and in the CI, against the fake local web server. See the question on \href{#how-do-i-make-my-app-connect-to-webfakes-when-the-tests-are-running-}{how webfakes helps you setting environment variables that point to your local server}. } \subsection{How do I simulate a slow internet connection?}{ You need to use the \code{throttle} server option when you start your web app. This means that you can run the very same app with different connection speed. This is how it goes: \if{html}{\out{
}}\preformatted{library(webfakes) slow <- new_app_process( httpbin_app(), opts = server_opts(throttle = 100) ) resp <- curl::curl_fetch_memory(slow$url("/bytes/200")) resp$times #> redirect namelookup connect pretransfer starttransfer #> 0.000000 0.000087 0.000266 0.000284 0.004878 #> total #> 2.013756 }\if{html}{\out{
}} \code{throttle} gives the number of bytes per second, so downloading 200 random bytes from the fake app will take about 2 seconds. } } webfakes/man/webfakes-package.Rd0000644000176200001440000000261015026557545016300 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/webfakes-package.R \docType{package} \name{webfakes-package} \alias{webfakes} \alias{webfakes-package} \title{webfakes: Fake Web Apps for HTTP Testing} \description{ Create a web app that makes it easier to test web clients without using the internet. It includes a web app framework with path matching, parameters and templates. Can parse various 'HTTP' request bodies. Can send 'JSON' data or files from the disk. Includes a web app that implements the 'httpbin.org' web service. } \seealso{ Useful links: \itemize{ \item \url{https://webfakes.r-lib.org/} \item \url{https://github.com/r-lib/webfakes} \item Report bugs at \url{https://github.com/r-lib/webfakes/issues} } } \author{ \strong{Maintainer}: Gábor Csárdi \email{csardi.gabor@gmail.com} Other contributors: \itemize{ \item Posit Software, PBC (\href{https://ror.org/03wc8by49}{ROR}) [copyright holder, funder] \item Civetweb contributors (see inst/credits/ciwetweb.md) [contributor] \item Redoc contributors (see inst/credits/redoc.md) [contributor] \item L. Peter Deutsch (src/md5.h) [contributor] \item Martin Purschke (src/md5.h) [contributor] \item Aladdin Enterprises (src/md5.h) [copyright holder] \item Maëlle Salmon \email{maelle.salmon@yahoo.se} (\href{https://orcid.org/0000-0002-2815-0399}{ORCID}) [contributor] } } \keyword{internal} webfakes/DESCRIPTION0000644000176200001440000000437715026575142013571 0ustar liggesusersPackage: webfakes Title: Fake Web Apps for HTTP Testing Version: 1.4.0 Authors@R: c( person("Gábor", "Csárdi", , "csardi.gabor@gmail.com", role = c("aut", "cre")), person("Posit Software, PBC", role = c("cph", "fnd"), comment = c(ROR = "03wc8by49")), person(, "Civetweb contributors", role = "ctb", comment = "see inst/credits/ciwetweb.md"), person(, "Redoc contributors", role = "ctb", comment = "see inst/credits/redoc.md"), person("L. Peter", "Deutsch", role = "ctb", comment = "src/md5.h"), person("Martin", "Purschke", role = "ctb", comment = "src/md5.h"), person(, "Aladdin Enterprises", role = "cph", comment = "src/md5.h"), person("Maëlle", "Salmon", , "maelle.salmon@yahoo.se", role = "ctb", comment = c(ORCID = "0000-0002-2815-0399")) ) Description: Create a web app that makes it easier to test web clients without using the internet. It includes a web app framework with path matching, parameters and templates. Can parse various 'HTTP' request bodies. Can send 'JSON' data or files from the disk. Includes a web app that implements the 'httpbin.org' web service. License: MIT + file LICENSE URL: https://webfakes.r-lib.org/, https://github.com/r-lib/webfakes BugReports: https://github.com/r-lib/webfakes/issues Depends: R (>= 3.6) Imports: stats, tools, utils Suggests: brotli, callr, covr, curl, digest, glue, httpuv, httr, jsonlite, processx, testthat (>= 3.0.0), withr, xml2, zip (>= 2.3.0) Biarch: true Config/Needs/website: tidyverse/tidytemplate Config/testthat/edition: 3 Config/usethis/last-upkeep: 2025-04-28 Encoding: UTF-8 RoxygenNote: 7.3.2 NeedsCompilation: yes Packaged: 2025-06-24 17:53:38 UTC; gaborcsardi Author: Gábor Csárdi [aut, cre], Posit Software, PBC [cph, fnd] (ROR: ), Civetweb contributors [ctb] (see inst/credits/ciwetweb.md), Redoc contributors [ctb] (see inst/credits/redoc.md), L. Peter Deutsch [ctb] (src/md5.h), Martin Purschke [ctb] (src/md5.h), Aladdin Enterprises [cph] (src/md5.h), Maëlle Salmon [ctb] (ORCID: ) Maintainer: Gábor Csárdi Repository: CRAN Date/Publication: 2025-06-24 19:20:02 UTC